Почему ключи отсутствуют на карте - PullRequest
0 голосов
/ 26 октября 2018

Я создал карту:

l := make(map[*A]string)

, где A:

type A struct{}

Затем добавил значения ключа в нее:

a1 := &A{}
a2 := &A{}
a3 := &A{}

l[a1] = "a1"
l[a2] = "a2"
l[a3] = "a3"

Я ожидалувидеть все значения («a1», «a2», «a3»), делая range

for k, v := range l{
    fmt.Println(k, v)
}

Но я вижу только последнее.

Почему это происходит?https://play.golang.org/p/GSdUWzExxLK

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Это потому, что A - пустая структура.Поскольку это не может измениться, go всегда присваивает ему один и тот же адрес памяти.Если вы добавите поле к A, оно начнет работать:

type A struct{a string}

func main() {
    a1 := A{}
    a2 := A{}

    l := make(map[*A]string)
    l[&a1] = "a1"
    l[&a2] = "a2"

    for i, v := range l{
        i := i
        fmt.Println(&i, v)
    }
}

Отпечатки:

0x40e138 a1
0x40e150 a2

https://play.golang.org/p/hYzU73kbVPV

Дейв Чейни углубится в эту тему:

https://dave.cheney.net/2014/03/25/the-empty-struct

0 голосов
/ 26 октября 2018

Поскольку в вашей структуре нет полей, Go оптимизирует все указатели на один и тот же адрес, поэтому вы каждый раз используете один и тот же ключ.Дайте структуре поле (даже если вы никогда не вводите в него значение), и вы получите ожидаемое поведение.

Детская площадка: https://play.golang.org/p/n-WUZ9wqpGJ

Вы можете прочитать больше о пустых структурах (включая это поведение указателя) в блоге Дэйва Чейни .

Это кратко упомянуто в спецификации под Размеры и выравнивания , и фактически является самым последним предложением вspec:

Тип структуры или массива имеет нулевой размер, если он не содержит полей (или элементов, соответственно), размер которых больше нуля.Две разные переменные нулевого размера могут иметь один и тот же адрес в памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...