我有一个可以用作地图键的类型,但我想防止发生这种情况。我认为,如果该类型包含私人成员,则其他程序包将无法使用,但无论如何,这似乎都有效。使该类型不能用作地图键的最佳方式是什么?如何防止将某个类型用作映射键?
type MyType struct {
A *A
b b
preventUseAsKey ?
}
我有一个可以用作地图键的类型,但我想防止发生这种情况。我认为,如果该类型包含私人成员,则其他程序包将无法使用,但无论如何,这似乎都有效。使该类型不能用作地图键的最佳方式是什么?如何防止将某个类型用作映射键?
type MyType struct {
A *A
b b
preventUseAsKey ?
}
我没有看到禁止将某个类型用作关键字的好处。这只是一个选项,可能会或可能不会被使用,只是因为您禁止将它用作地图键,类型不会更好或更小或更快。
但是,如果你想这样做:Spec: Map types:
The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice.
所以,如果你违反了comparison operators的条款,你含蓄地得到你想要的。你必须为struct
类型的一个struct
,条款:如果所有的领域是相当
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non- blank fields are equal.
所以struct
值只可比的(因此只能在地图中使用的密钥)。 只需添加一个类型不可比的字段。
Slice, map, and function values are not comparable.
因此,例如,增加一个字段类型为切片,就大功告成了:
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
类型。
比我的回答更完整,并且像往常一样富有启发性。 +1 – VonC
您的类型应not be comparable为了不适合作为地图的关键。
Slice, map, and function values are not comparable
见Key Type:
Notably absent from the list are slices, maps, and functions; these types cannot be compared using
==
, and may not be used as map keys.
所以,如果你的类型片,映射或函数,你应该得到你所需要的。
这可能是一个“别名”(定义新named type):
type StringSliceWrap []string
type MyFunc func(i int)
该别名将不会被用来作为地图的关键。
更新2017年:Brad Fitzpatrick give this tip(在你的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
现在还不能用作放大器的关键!
我编辑了[我的答案](http://stackoverflow.com/a/37916798/6309):你实际上可以在你的结构中添加一种'preventUseAsKey'。 – VonC