Ответ
Неизменяемость (immutability) строк в Go означает, что после создания строки ее значение — последовательность байт — не может быть изменено.
Любая операция, которая выглядит как модификация строки (например, конкатенация или получение подстроки), на самом деле создает в памяти новую строку.
// Попытка изменить байт строки напрямую вызовет ошибку компиляции
s := "hello"
s[0] = 'H' // Error: cannot assign to s[0]
// Конкатенация создает новую строку
s2 := s + " world" // s осталась "hello", s2 стала "hello world"
Преимущества неизменяемости
-
Потокобезопасность (Thread Safety)
- Поскольку строки нельзя изменить, их можно безопасно передавать между горутинами без использования мьютексов или других примитивов синхронизации. Данные гарантированно не будут повреждены.
-
Эффективность и экономия памяти
- При создании подстроки (слайса строки), например
sub := s[1:4]
, Go не копирует данные. Новая строкаsub
будет указывать на тот же самый базовый массив байт в памяти, что и исходная строкаs
. Это очень быстро и экономно.
- При создании подстроки (слайса строки), например
-
Надежность и предсказуемость
- Неизменяемые строки можно безопасно использовать в качестве ключей в
map
. Если бы строки были изменяемыми, изменение значения ключа после его добавления в мапу нарушило бы ее внутреннюю структуру.
- Неизменяемые строки можно безопасно использовать в качестве ключей в
Как работать с изменяемыми строками?
Когда требуется многократно изменять строку (например, собирать ее в цикле), создавать каждый раз новую строку неэффективно. Для этого существуют специальные инструменты:
strings.Builder
: Самый эффективный и предпочтительный способ для построения строк. Он использует внутренний байтовый буфер, который растет по мере необходимости, избегая лишних аллокаций.var builder strings.Builder for i := 0; i < 10; i++ { builder.WriteString("a") // Эффективно } result := builder.String()
- Слайс байт (
[]byte
): Если нужно изменять отдельные байты, строку можно преобразовать в[]byte
, модифицировать и затем преобразовать обратно.s := "hello" b := []byte(s) b[0] = 'H' s = string(b) // s теперь "Hello"
- Слайс рун (
[]rune
): Для корректной работы с многобайтными Unicode-символами (например, кириллицей) следует использовать[]rune
.