> Как называются типы объектов, которые при модификации возвращают копию, а не изменяют исходный объект (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Лига Цифровой Экономики

Стек: Go

> Пример ответа

Короткий ответ

В Go такие типы называются иммутабельными (immutable) или value-типами. При операциях, которые выглядят как модификация, создаётся новая копия значения, а исходный объект остаётся неизменным. Классические примеры - строки (string), массивы ([N]T), структуры (struct), передаваемые по значению. Слайсы и мапы - ссылочные типы, они мутабельны, но при определённых операциях (например, append без переиспользования capacity) тоже возвращают новую копию.

Подробное объяснение

В Go нет ключевого слова immutable, как в некоторых языках. Иммутабельность достигается соглашениями и особенностями типов:

  • Value-типы (строки, числа, булевы, массивы, структуры) - при присваивании или передаче в функцию копируются целиком. Любая операция, которая выглядит как изменение, на самом деле создаёт новое значение.
  • Строки - особый случай: они иммутабельны на уровне рантайма. Нельзя изменить отдельный байт строки s[0] = 'x' - это ошибка компиляции. Конкатенация или strings.Replace возвращают новую строку.
  • Массивы - при присваивании копируются полностью. Изменение копии не влияет на оригинал.
  • Структуры - если передаются по значению, то копируются. Методы с value-receiver не могут изменить исходную структуру.
  • Слайсы и мапы - ссылочные, но при операциях вроде append с превышением capacity возвращают новый слайс. Это не иммутабельность, а особенность аллокации.

Термин "persistent data structures" (персистентные структуры) в Go не применяется нативно - для этого нужны сторонние библиотеки.

На практике

В реальном Go-коде иммутабельность используется для:

  • Безопасности конкурентного доступа - иммутабельные данные можно читать из нескольких горутин без мьютексов.
  • Предсказуемости - функции, которые не меняют входные данные, проще тестировать и отлаживать.
  • Кэширования - иммутабельные объекты безопасно использовать как ключи мап.
  • Value-ресиверы методов - если метод не должен менять состояние, используют func (s SomeStruct) Method() вместо func (s *SomeStruct) Method().

На практике часто применяют паттерн: структура с приватными полями и методами-геттерами, которые возвращают копии. Либо используют copy() для слайсов перед модификацией.

Пример кода

GO
package main
import "fmt"
type User struct {
Name string
Age int
}
// Метод с value-receiver - не меняет исходный объект
func (u User) WithAge(newAge int) User {
u.Age = newAge // меняем копию
return u
}
func main() {
original := User{Name: "Alice", Age: 30}
// Строки иммутабельны
s := "hello"
s2 := s + " world" // новая строка, s не изменилась
// Массивы копируются при присваивании
arr := [3]int{1, 2, 3}
arrCopy := arr
arrCopy[0] = 99 // arr остался [1,2,3]
// Метод возвращает копию
updated := original.WithAge(31)
fmt.Println(original.Age) // 30 - не изменился
fmt.Println(updated.Age) // 31
// Слайс - ссылочный, но append может вернуть новую копию
slice := []int{1, 2, 3}
newSlice := append(slice, 4) // может быть новая аллокация
fmt.Println(slice, newSlice)
}

Как отвечать на собеседовании

Начните с прямого ответа: "иммутабельные типы, или value-типы". Затем кратко перечислите: строки, массивы, структуры по значению. Упомяните, что в Go нет встроенной иммутабельности как языковой конструкции - это достигается копированием. Если спросят про слайсы - объясните разницу между ссылочной природой и копированием при append. Приведите пример с value-receiver. Не углубляйтесь в персистентные структуры, если не спросят - это редкая тема для Go.

Что проверяет интервьюер

  • Понимание разницы между value-типами и ссылочными типами в Go.
  • Знание особенностей строк (иммутабельность на уровне рантайма).
  • Понимание поведения append и capacity слайсов.
  • Умение объяснить, как иммутабельность помогает в конкурентном программировании.
  • Владение паттернами: value-receiver, методы-копировальщики.

Типичные ошибки

  • Называть слайсы иммутабельными - это неверно, они ссылочные.
  • Говорить, что append всегда возвращает копию - на самом деле при достаточном capacity он мутирует исходный массив.
  • Путать иммутабельность с неизменяемостью указателей - *T всегда мутабелен.
  • Утверждать, что структуры всегда иммутабельны - если структура содержит слайс или мапу, копирование поверхностное, и внутренние данные остаются общими.
  • Забывать, что передача структуры по указателю (*User) делает её мутабельной даже с value-receiver методами.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью