maps and unhashable types

4,020 views
Skip to first unread message

Ronny Brendel

unread,
Aug 22, 2010, 12:56:52 PM8/22/10
to golang-nuts, Ronny
Hi there,

I've question regarding maps

http://nf.id.au/go-maps

1. The article says maps take the interface{} for key and value.

Consider this example
""
package main¬
¬
import (¬
» "fmt"¬

¬
type Woot struct {¬
» a,b,c int¬

¬
func main() {¬
¬
» a := make(map[interface{}]interface{})¬
¬
» a[Woot{1,2,3}] = true¬
¬
» fmt.Println(a)¬
}
""

Maps cannot take types which are not "hashable", which makes perfect sense.

I would expect it to require a "Hashable" interface so that I can create a
type which provides the hashing function. Why is that way?

-----
2. And secondly how would you implement a compound key. I.e. indexing with
more than one variable? (Best practice so to speak)

signature.asc

Andrew Gerrand

unread,
Aug 22, 2010, 9:02:09 PM8/22/10
to Ronny Brendel, golang-nuts
On 23 August 2010 02:56, Ronny Brendel <ronnyb...@gmail.com> wrote:
> Maps cannot take types which are not "hashable", which makes perfect sense.
>
> I would expect it to require a "Hashable" interface so that I can create a
> type which provides the hashing function. Why is that way?

This is a kind of magic that Go shies away from. If your type has a
Hash function that you want to use to generate the hashes, just call
it when writing or reading from the map:

m := make(map[string]interface{})
m[key.Hash()] = value
value = m[key.Hash()]

This has been discussed before. Search these groups for hashable or
hash map for more.

> 2. And secondly how would you implement a compound key. I.e. indexing with
> more than one variable? (Best practice so to speak)

You could maintain two maps. I'm not sure what you mean specifically, though.

Andrew

Brian Slesinsky

unread,
Aug 24, 2010, 4:05:11 AM8/24/10
to golang-nuts
On Aug 22, 6:02 pm, Andrew Gerrand <a...@golang.org> wrote:

> This is a kind of magic that Go shies away from. If your type has aHashfunction that you want to use to generate the hashes, just call
> it when writing or reading from the map:
>
> m := make(map[string]interface{})
> m[key.Hash()] = value
> value = m[key.Hash()]

This doesn't actually work if Hash() could return the same value for
two different keys, which is likely for any non-crypto hash function.
You'd have to wrap the map in an object that knows how to deal with
collisions. If we don't want the "magic" to be reinvented by each user
then this might be a good contribution to the standard library.

- Brian

John Asmuth

unread,
Aug 24, 2010, 10:10:23 AM8/24/10
to golang-nuts


On Aug 24, 4:05 am, Brian Slesinsky <bslesin...@gmail.com> wrote:
> You'd have to wrap the map in an object that knows how to deal with
> collisions. If we don't want the "magic" to be reinvented by each user
> then this might be a good contribution to the standard library.

For what it's worth, I did this here: http://code.google.com/p/gohash/
:)

- John
Reply all
Reply to author
Forward
0 new messages