Карты (map
) часто используются для хранения данных, связанных с уникальными ключами. Частый пример — хранение структур (например, пользователей, заказов, товаров), где ключ — это уникальный идентификатор (ID).
Базовый пример
Предположим, у нас есть структура User
:
type User struct {
Name string
Email string
}
Создадим карту, где ключ — целое число (ID), а значение — структура User
:
users := map[int]User{
1: {Name: "Alice", Email: "alice@example.com"},
2: {Name: "Bob", Email: "bob@example.com"},
}
fmt.Println(users[1]) // => {Alice alice@example.com}
Проблема копий
При получении элемента из карты возвращается копия значения, а не ссылка на оригинал:
user := users[1]
user.Name = "Alicia"
fmt.Println(users[1].Name) // => Alice — оригинал не изменился
Чтобы изменить данные в карте, нужно явно присвоить изменённую структуру обратно:
user := users[1]
user.Name = "Alicia"
users[1] = user
fmt.Println(users[1].Name) // => Alicia
Использование указателей
Если нужно часто изменять данные, удобнее хранить в карте указатели на структуры:
users := map[int]*User{
1: {Name: "Alice", Email: "alice@example.com"},
2: {Name: "Bob", Email: "bob@example.com"},
}
users[1].Name = "Alicia"
fmt.Println(users[1].Name) // Alicia — оригинал изменился
В этом случае карта хранит ссылки на объекты, и изменения применяются напрямую.
Перебор карты со структурами
Перебор элементов ничем не отличается от обычных карт:
type User struct {
Name string
Email string
}
users := map[int]*User{
1: {Name: "Alice", Email: "alice@example.com"},
2: {Name: "Bob", Email: "bob@example.com"},
}
for id, user := range users {
fmt.Printf("ID=%d, Name=%s\n", id, user.Name)
}
// => ID=1, Name=Alice
// => ID=2, Name=Bob
Если карта хранит указатели, цикл будет работать аналогично, только user
уже будет указателем.