ПрограммированиеGo Backend разработчик

Как устроена инициализация переменных в Go и чем опасно использовать zero values (нулевые значения)?

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Go переменные, объявленные без явного инициализатора, автоматически получают так называемые нулевые значения (zero values), отличающиеся для разных типов:

  • int — 0
  • bool — false
  • string — ""
  • указатели, интерфейсы, срезы, карты, каналы, функции — nil

Это удобно (отсутствие мусора в памяти), но может быть опасно: для некоторых типов, например, срезов и карт, работа с nil-значением может привести к панике или багам.

Пример:

var m map[string]int m["key"] = 1 // panic: assignment to entry in nil map var s []int fmt.Println(s, s == nil) // [] true (можно добавлять элементы, но нельзя обращаться по индексу)

Вопрос с подвохом

Чем отличается nil-значение среза от nil-значения карты/канала, и к каким багам это приводит?

Правильный ответ: Срез с nil-значением можно передавать в функции, использовать в append и range — это безопасно, но работа с nil-картой приведет к панике при попытке записи (но чтение допускается и вернет zero value).

Пример:

var m map[string]int fmt.Println(m["no_key"]) // 0 — безопасно m["key"] = 1 // panic! var s []int s = append(s, 42) // ок

Примеры реальных ошибок из-за незнания тонкостей темы


История

Описание: В крупном проекте использовали неинициализированные мапы для агрегации данных. При первой записи приложение стабильно падало с panic. Проблема обнаружилась на проде, когда ввели новую статистику.


История

Описание: Сервис сериализовал неинициализированный срез, отправляя его как JSON в API-ответ. Вместо [] клиенты получали null — пришлось менять схему на фронте, чтобы обрабатывать оба варианта.


История

Описание: В модуле кеширования некорректно сравнивали nil map с пустым map и из-за этого некорректно определяли: есть ли элементы. Это приводило к лишним обращениям к базе данных, снижая производительность.