Структуры в Go копируются по значению (deep copy первого уровня, вложенные структуры копируются по тому же правилу), а срезы — по значению, но копируется лишь структура, а не подлежащий массив данных: и оригинал, и копия среза указывают на один и тот же backing array, поэтому изменение через один срез отразится в другом, если не делать явную копию массива через copy().
Пример копирования среза:
s1 := []int{1,2,3} s2 := s1 // указатели на один буфер! s2[0] = 99 fmt.Println(s1) // [99 2 3] // Для копии массива: s3 := make([]int, len(s1)) copy(s3, s1) s3[0] = 42 fmt.Println(s1) // [99 2 3], s3 — независим
При копировании структур: если структура содержит поле-указатель, поле-срез, то копируются только ссылки, а не значения.
Какой способ "клонировать" срез так, чтобы его изменения не затрагивали оригинал?
Потенциально ошибочный ответ: Просто сделать b := a. Верно:
copy, создать новый срез нужной длины и скопировать данные:newS := make([]int, len(a)) copy(newS, a)
История
Описание: При генерации запросов к БД динамически меняли поля среза в структуре-запросе, не делая копии. При повторных запросах данные пересекались, выдавая некорректные результаты для пользователей.
История
Описание: При параллельной обработке данных создавали копию структуры через присваивание и расширяли срез в одной горутине, параллельно используя другой оригинальный срез. Данные "перетирались", приводя к непредсказуемым багам.
История
Описание: Использовали структуру-буфер, одновременное копирование через присваивание не учитывало вложенные срезы (shallow copy), изменения в одном месте затрагивали другой буфер — в итоге было сложно отследить источник изменения данных.