2 回答
TA贡献1900条经验 获得超5个赞
我认为不允许将类型用作键没有任何好处。它只是一个可能会或可能不会使用的选项,类型不会因为您禁止将其用作映射键而变得更好或更小或更快。
但如果你想这样做:规范:地图类型:
比较运算符== 和 != 必须为键类型的操作数完全定义;因此键类型不能是函数、映射或切片。
因此,如果您可以违反比较运算符的条款,您就会隐含地得到您想要的。您有struct以下类型的 , 术语struct:
如果结构值的所有字段都是可比较的,则结构值是可比较的。如果它们对应的非空白字段相等,则两个结构值相等。
所以struct值只有在它们的所有字段都是可比较的情况下才具有可比性(因此只能用作映射中的键)。只需添加一个类型不可比较的字段。
切片、映射和函数值不可比较。
因此,例如添加一个类型为切片的字段,您就完成了:
type MyType struct {
S string
i int
notComparable []int
}
尝试将上述MyType内容用作密钥:
m := map[MyType]int{}
你得到一个编译时错误:
invalid map key type MyType
笔记:
我写了关于禁止类型作为键没有任何好处的文章。不仅如此:从现在开始,您将无法再对您的类型的值使用比较运算符(因为额外的、不可比较的字段),因此例如您失去了比较这些值的选项:
p1, p2 := MyType{}, MyType{}
fmt.Println(p1 == p2)
编译时错误:
invalid operation: p1 == p2 (struct containing []int cannot be compared)
请注意,通过一个小技巧,您仍然可以保留您的类型的可比较性质,例如,通过不导出您的类型而是嵌入原始类型的包装器类型;并将额外的、不可比较的类型添加到包装器类型中,例如:
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)
}
这样,您myType可以保持可比性,但仍会阻止导出的包装器MyType类型用作键类型。
TA贡献1843条经验 获得超7个赞
您的类型不应具有可比性,以免不适合作为映射键。
切片、映射和函数值不可比较
请参阅密钥类型:
列表中明显没有切片、映射和函数。这些类型不能使用 比较==,也不能用作映射键。
所以如果你的类型是切片、映射或函数,你应该得到你需要的。
它可能是一个“别名”(定义一个新的命名类型):
type StringSliceWrap []string
type MyFunc func(i int)
该别名不会用作映射键。
2017 年更新:Brad Fitzpatrick 提供此提示(在您的 中添加一个切片struct)以确保您的类型struct不可比较:请参阅play.golang.org:
package main
// disallowEqual is an uncomparable type.
// If you place it first in your struct, you prevent == from
// working on your struct without growing its size. (Don't put it
// at the end; that grows the size of the struct)
type disallowEqual [0]func()
type T struct {
_ disallowEqual
Foo string
Bar int
}
func main() {
var t1 T
var t2 T
println(t1 == t2)
}
T 现在不能用作amp键!
- 2 回答
- 0 关注
- 151 浏览
添加回答
举报