0

Доступ к полям структуры в значении карты (без копирования)

17

Проблема с доступом к полям структуры в мапе Go

Предположим, что у нас есть следующий код:

type User struct {
    name string
}

users := make(map[int]User)

users[5] = User{"Steve"}

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

users[5].name = "Mark"

Я получаю ошибку: cannot assign to users[5].name.

Может кто-то объяснить, почему это не сработало? Как я могу корректно получить доступ к структуре, сохраненной в мапе, или какая логика стоит за тем, что это невозможно?

Примечания

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

Также я в курсе, что можно использовать указатели на структуры в мапе, но мне не хочется делать это.

2 ответ(ов)

0

Основная проблема заключается в том, что нельзя получить адрес элемента внутри карты. Вы могли бы подумать, что компилятор преобразует users[5].name = "Mark" в следующее

(&users[5]).name = "Mark"

Однако это не компилируется и выдает ошибку

cannot take the address of users[5]

Это позволяет картам использовать свою свободу для реорганизации элементов по своему усмотрению для эффективного использования памяти.

Единственный способ явно изменить что-то в карте — это присвоить значение, т.е.

t := users[5]
t.name = "Mark"
users[5] = t

Таким образом, вам придется либо смириться с копированием выше, либо использовать указатели в вашей карте. Хранение указателей имеет недостаток в том, что оно требует больше памяти и больше выделений памяти, что может перевесить преимущества копирования, — это уже зависит от вас и вашего приложения.

Третий вариант — использовать срез. Ваша исходная запись будет работать идеально, если вы измените users := make(map[int]User) на users := make([]User, 10).

0
  1. Карты обычно представляют собой разреженные хеш-таблицы, которые перераспределяются, когда превышается заданный порог. Перераспределение может вызвать проблемы, если кто-то удерживает указатели на значения в этих таблицах.

  2. Если вы стремитесь избежать создания копии объекта, вы можете хранить указатель на сам объект в качестве значения.

  3. Когда мы обращаемся к элементу карты, возвращаемое значение передается "по значению", если использовать терминологию, применяемую к параметрам функции. Таким образом, редактирование возвращенной структуры не влияет на содержимое карты.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь