Как называются типы объектов, которые при модификации возвращают копию, а не изменяют исходный объект
Что проверяют
Знаете ли вы термин и отличаете ли его от соседних: неизменяемые (immutable) типы, семантика значений, копирование при записи. Для Go важнее вторая часть: как язык без ключевого слова для неизменяемости даёт такое поведение. Следом часто спрашивают, почему append иногда меняет чужой срез.
Как отвечать
Такие типы называются неизменяемыми: после создания состояние объекта не меняется, а любая «модификация» возвращает новый объект. Рядом стоят близкие понятия:
- value object: объект из DDD без идентичности, сравнивается по значению и обычно неизменяем;
- персистентные структуры данных: при изменении возвращают новую версию, но делят с предыдущей неизменённые части, чтобы не копировать всё;
- copy-on-write: копия создаётся лениво, только в момент первой записи.
Что есть в Go:
string: неизменяема на уровне языка.strings.Replace,strings.ToUpperи конкатенация возвращают новую строку, аs[0] = 'a'не скомпилируется. Для сборки строки в цикле берутstrings.Builder;time.Time: хрестоматийный пример из стандартной библиотеки,t.Add(d)иt.Truncate(d)возвращают новое значение;- структуры по значению: присваивание и передача копируют структуру, а методы с получателем-значением работают с копией. Так пишут свои неизменяемые типы: неэкспортируемые поля, конструктор и методы вида
func (m Money) Add(o Money) Money.
Оговорка: копия поверхностная. Если внутри структуры срез, мапа или указатель, копия делит с оригиналом одни и те же данные, и для настоящей неизменяемости их надо копировать, например через slices.Clone и maps.Clone.
Где спотыкаются
Называют срезы неизменяемыми, раз append возвращает новый срез. Если ёмкости хватает, append пишет в тот же массив, и изменение увидят все срезы, которые на него смотрят.
Считают, что передача структуры по значению защищает данные. Защищает только поля-значения, а поля-срезы и мапы остаются общими.
Путают неизменяемость с const. В Go const бывает только у констант времени компиляции: чисел, строк, булевых значений. Сделать константным срез или структуру нельзя.