Что выведут a == b и m[b] для двух равных структур point и почему?
Прочитайте фрагмент ниже. Две структуры point a и b построены из одинаковых значений полей, и b используется для поиска в map с ключом a.
Определите, что выведут a == b и m[b], и объясните почему — включая то, что изменилось бы, будь у point поле-срез.
type point struct{ x, y int }
func main() {
a := point{1, 2}
b := point{1, 2}
fmt.Println(a == b)
m := map[point]string{a: "p"}
fmt.Println(m[b])
}
Определите вывод.
Выведет true и p. Структуры сравнимы через ==, когда каждое поле сравнимо, сравнение идёт поле за полем. Поскольку a == b, они хешируются в один ключ map, поэтому m[b] находит значение под a. Поле-срез сделало бы и ==, и ключ map некомпилируемыми.
- ✗Думать, что
==для структур сравнивает идентичность, а не значения полей - ✗Считать, что структура с полем-срезом или map всё ещё сравнима — она не компилируется
- ✗Забывать, что две равные структуры хешируются в один ключ map
- →Какие типы полей делают структуру несравнимой и какая будет ошибка компиляции?
- →Как всё же использовать структуру с полем-срезом в качестве ключа map?
Что выведет код?
type point struct{ x, y int }
func main() {
a := point{1, 2}
b := point{1, 2}
fmt.Println(a == b) // ?
m := map[point]string{a: "p"}
fmt.Println(m[b]) // ?
}
Вывод
true
p
Почему
Структура сравнима оператором ==, если каждое её поле сравнимо. У point оба поля — int, поэтому == сравнивает их поле за полем по значению: a.x == b.x && a.y == b.y → true. Идентичность переменных или адреса роли не играют.
Из сравнимости следует, что тип годится как ключ map. Поскольку a == b, они хешируются в одно и то же место, и m[b] находит значение, положенное под a → p.
⚠️ Ловушка: если добавить в структуру несравнимое поле, ломается и ==, и ключ map — на этапе компиляции:
type point struct{ x, y int; tags []string } // срез несравним
// invalid operation: a == b (struct containing []string cannot be compared)
// invalid map key type point
Обойти можно, вынеся сравнимую часть в отдельный ключ или сравнивая через reflect.DeepEqual (но он не годится в ключи map).