2016-06-20 22 views
4

我有一个可以用作地图键的类型,但我想防止发生这种情况。我认为,如果该类型包含私人成员,则其他程序包将无法使用,但无论如何,这似乎都有效。使该类型不能用作地图键的最佳方式是什么?如何防止将某个类型用作映射键?

type MyType struct { 
    A *A 
    b b 

    preventUseAsKey ? 
} 
+0

我编辑了[我的答案](http://stackoverflow.com/a/37916798/6309):你实际上可以在你的结构中添加一种'preventUseAsKey'。 – VonC

回答

10

我没有看到禁止将某个类型用作关键字的好处。这只是一个选项,可能会或可能不会被使用,只是因为您禁止将它用作地图键,类型不会更好或更小或更快。

但是,如果你想这样做: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类型。

+2

比我的回答更完整,并且像往常一样富有启发性。 +1 – VonC

4

您的类型应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现在还不能用作放大器的关键!

相关问题