В Go структура map всегда передаётся по значению, но это значение содержит указатель на внутренние структуры самого map (под капотом — хэш-таблица). Поэтому если вы передаёте map в функцию и внутри функции меняете содержимое (добавляете/удаляете элементы), изменения будут видны снаружи. Аналогично ведут себя и slice — копируется структура slice, но не сам массив-данные: slice содержит указатель на массив, длину и ёмкость. Если изменять значения по индексу внутри функции, исходный массив тоже изменится. Но если из функции вы присваиваете новый slice (например, reslice), исходная переменная не изменится.
func updateMap(m map[string]int) { m["key"] = 42 // Изменения видны снаружи! } func updateSlice(s []int) { s[0] = 99 // Изменяется исходный массив }
Почему при передачи map и slice в функцию их изменение внутри функции отражается на "оригинале"?
Ответ: Потому что копируется только структура указателя, а сами данные остаются общими — любые изменения затрагивают один и тот же блок памяти.
История
В fintech проекте передавали map с настройками конфигурации в разные сервисы, предполагая, что локальные изменения не повлияют на общий map. В результате один сервис изменил значения, и это вызвало баги в других модулях, которые получили неожиданно изменённую конфигурацию.
История
В микросервисе аналитики передавали slice, рассчитывая получить независимые копии. Но функция внутри изменила значения по индексу, что привело к искажённым данным в отчёте, так как исходный массив был неожиданно изменён.
История
В игровых серверах использовали map для хранения сессий пользователей и параллельно передавали этот map в несколько горутин. Предполагалось, что каждая горутина работает со своей копией, но фактически возникла гонка данных и частично потерянные сессии.