如何防止将类型用作地图键?

Mat*_*ner 4 struct dictionary key unique go

我有一个可以用作地图键的类型,但我想防止这种情况发生.我假设如果类型包含私有成员,则无法从其他包中进行,但这似乎无论如何都可行.使类型无法用作地图键的最佳方法是什么?

type MyType struct {
    A *A
    b b

    preventUseAsKey ?
}
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 10

我认为不允许使用某种类型作为密钥的任何好处.它只是一个可能使用或不使用的选项,因为你禁止将它用作地图键,所以类型不会更好或更小或更快.

但是如果你想这样做:规范:地图类型:

比较操作符 ==和=必须为键类型的操作数被完全定义!; 因此,键类型不能是函数,映射或切片.

因此,如果您违反比较运算符的条款,您就会隐式得到您想要的结果.你有一个类型的struct术语struct:

如果所有字段都具有可比性,则结构值可比较.如果相应的非空白字段相等,则两个结构值相等.

因此,struct如果所有字段都具有可比性,则值只能进行比较(因此只能用作映射中的键).只需添加类型无法比较的字段.

切片,贴图和函数值无法比较.

例如,添加一个类型为切片的字段,您就完成了:

type MyType struct {
    S             string
    i             int
    notComparable []int
}
Run Code Online (Sandbox Code Playgroud)

试图使用以上MyType作为关键:

m := map[MyType]int{}
Run Code Online (Sandbox Code Playgroud)

您收到编译时错误:

invalid map key type MyType
Run Code Online (Sandbox Code Playgroud)

注意:

我写过没有任何好处,禁止将类型作为密钥.它不止于此:从现在开始,你将无法再对类型的值使用比较运算符(因为额外的,不可比较的字段),所以例如你失去了比较这些值的选项:

p1, p2 := MyType{}, MyType{}
fmt.Println(p1 == p2)
Run Code Online (Sandbox Code Playgroud)

编译时错误:

invalid operation: p1 == p2 (struct containing []int cannot be compared)
Run Code Online (Sandbox Code Playgroud)

请注意,通过一个小技巧,您仍然可以保留类型的可比性质,例如,不导出您的类型,而是包含原始类型的包装类型; 并将额外的,不可比较的类型添加到包装器类型,例如:

type myType struct {
    S string
    i int
}

type MyType struct {
    myType
    notComparable []int
}

func main() {
    p1, p2 := MyType{}, MyType{}
    fmt.Println(p1.myType == p2.myType)
}
Run Code Online (Sandbox Code Playgroud)

这样,您myType可以保持可比性但仍然阻止导出的包装MyType类型用作键类型.

  • 比我的回答更完整,像往常一样有启发性.+1 (2认同)