2016-06-20 47 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現在還不能用作放大器的關鍵!

相關問題