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

Arc*_*son 12 go

假设我有围棋结构类型,我想作为一个地图要使用的密钥,但我希望使用Go的内置平等的操作.建立这样一张地图的最佳方法是什么?

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

type Key struct {
    a *int
}

func Equal(x Key, y Key) bool {
    return *x.a == *y.a
}
Run Code Online (Sandbox Code Playgroud)

如何构建Equal用于密钥比较的地图?

mae*_*ics 13

Go 对用作映射键的值具有严格的可比较语义.因此,您无法像许多其他语言一样为地图键定义自己的哈希码和相等函数.

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

例如:

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"
Run Code Online (Sandbox Code Playgroud)

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


eva*_*nal 7

这在 Go 中是不可能的。没有您可以覆盖的运算符重载或“平等”方法(因为不是从像 .NET 这样的公共基类继承的,您的示例让我想起了)。如果您有兴趣,这个答案有更多关于等式比较的信息;是否可以为命名类型/结构定义相等性?

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