2016-06-20 24 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.

は、したがって、たとえば、型がスライスであるフィールドを追加すれば完了です:

m := map[MyType]int{} 

type MyType struct { 
    S    string 
    i    int 
    notComparable []int 
} 

をキーとして上記MyTypeを使用しようとすると、コンパイル時エラーが発生する:

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が同等ではないことを確認する:

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今アンペアキーとして使用することはできません。play.golang.orgを参照してください!

関連する問題