Как я могу предотвратить использование типа в качестве ключа карты?

У меня есть тип, который можно использовать в качестве ключа карты, но я хочу, чтобы это не происходило. Я предположил, что если бы тип содержал закрытый член, это было бы невозможно из других пакетов, но это, похоже, работает в любом случае. Какой лучший способ сделать тип непригодным для использования в качестве ключа карты?

type MyType struct {
    A *A
    b b

    preventUseAsKey ?
}
 VonC04 мая 2017 г., 17:16
Я редактировалмой ответ ниже: вы на самом деле можете добавить видpreventUseAsKey в вашей структуре.

Ответы на вопрос(2)

Решение Вопроса

а. Это просто опция, которая может или не может быть использована, тип не будет лучше, меньше или быстрее только потому, что вы запрещаете использовать его в качестве ключа карты.

Но если вы хотите сделать это:Spec: Типы карт:

операторы сравнения == и! = должны быть полностью определены для операндов типа ключа; таким образом, тип ключа не должен быть функцией, картой или слайсом.

Так что, если вы можете нарушить условияоператоры сравненияВы безоговорочно получаете то, что хотите. У тебя есть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 тип для использования в качестве типа ключа.

 VonC20 июн. 2016 г., 15:04
Более полный, чем мой ответ, и поучительный, как обычно. +1

не быть сопоставимым для того, чтобы быть непригодным в качестве ключа карты.

Значения среза, карты и функции не сравнимы

УвидетьТип ключа:

В списке отсутствуют заметные фрагменты, карты и функции; эти типы нельзя сравнивать, используя==и не может использоваться в качестве ключей карты.

Поэтому, если ваш тип - это срез, карта или функция, вы должны получить то, что вам нужно.
Это может быть «псевдоним» (определение новогоименованный тип):

type StringSliceWrap []string
type MyFunc func(i int)

Этот псевдоним не будет использоваться в качестве ключа карты.

Обновление 2017:Брэд Фитцпатрик даст этот совет (добавив ломтик в ваш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 не может использоваться в качестве ключа усилителя сейчас!

Ваш ответ на вопрос