使用用户定义的密钥与用户定义的相等进行映射?

时间:2015-04-15 22:25:07

标签: go

假设我在Go中有一个结构类型,我想用它作为地图中的一个键,但我不想想要使用Go的内置相等操作。建立这样一张地图的最佳方法是什么?

对于一个具体的例子,这是我的键类型和相等操作:

type Key struct {
    a *int
}

func Equal(x Key, y Key) bool {
    return *x.a == *y.a
}

如何构建使用Equal进行密钥比较的地图?

2 个答案:

答案 0 :(得分:12)

Go有strict comparable semantics for values used as map keys。因此,您无法像在许多其他语言中那样为地图键定义自己的哈希码和相等函数。

但是,请考虑以下解决方法。不要直接使用struct实例作为键,而是使用struct的派生属性,该属性本质上可用作键并具有您想要的等同语义。通常,将整数或字符串值派生为散列代码很简单,该散列代码用作实例的标识。

例如:

type Key struct {
  a *int
}

func (k *Key) HashKey() int {
  return *(*k).a
}

k1, k2 := Key{intPtr(1)}, Key{intPtr(2)}
m := map[int]string{}
m[k1.HashKey()] = "one"
m[k2.HashKey()] = "two"
// m = map[int]string{1:"one", 2:"two"}
m[k1.HashKey()] // => "one"

当然,不变性是这种方法的关键问题。在上面的示例中,如果您修改字段a,则实例不能再用作哈希键,因为它的标识已更改。

答案 1 :(得分:3)

这在Go中是不可能的。没有运算符重载或'Equaluality'方法可以覆盖(由于不是从.NET中常见的基类继承而你的例子提醒我)。如果您有兴趣,这个答案有关于平等比较的更多信息; Is it possible to define equality for named types/structs?

如评论中所提到的,如果你想做这样的工作,我会建议在对象上使用属性作为键。您可以根据如何设置该属性的值来定义相等性(如果您正在寻找成员相等的话,它可能是对象字节的校验和或其他内容)。