← Назад к вопросам
Что произойдёт если присвоить какой-нибудь символ элементу строки?
2.0 Middle🔥 181 комментариев
#Основы Go
Комментарии (1)
🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Ошибка компиляции: строки в Go неизменяемы
Если вы попытаетесь присвоить символ (байт или руну) элементу строки по индексу в Go, компилятор выдаст ошибку. Это происходит потому, что строки в Go являются неизменяемыми (immutable) последовательностями байт.
Пример ошибочного кода
package main
func main() {
str := "Hello"
str[0] = 'h' // ОШИБКА: невозможно присвоить str[0]
}
При попытке скомпилировать этот код вы получите ошибку:
cannot assign to str[0]
Почему строки неизменяемы?
- Безопасность и предсказуемость — неизменяемость предотвращает случайное изменение строк, которые могут использоваться в нескольких местах.
- Потокобезопасность — строки можно безопасно использовать в конкурентных программах без блокировок.
- Эффективность — строки могут копироваться по ссылке без глубокого копирования.
- Хешируемость — неизменяемость позволяет использовать строки как ключи в map.
Как правильно работать со строками в Go
1. Создание новой строки с изменениями
package main
import (
"fmt"
"strings"
)
func main() {
original := "Hello"
// Способ 1: через преобразование в слайс рун
runes := []rune(original)
runes[0] = 'h'
modified1 := string(runes)
fmt.Println(modified1) // "hello"
// Способ 2: с помощью функций пакета strings
modified2 := strings.Replace(original, "H", "h", 1)
fmt.Println(modified2) // "hello"
// Способ 3: конкатенация
modified3 := "h" + original[1:]
fmt.Println(modified3) // "hello"
}
2. Обработка многобайтовых символов (UTF-8)
Важно помнить, что Go использует кодировку UTF-8, где символы могут занимать от 1 до 4 байт:
package main
import "fmt"
func main() {
str := "Привет" // Кириллица - многобайтовые символы
// НЕПРАВИЛЬНО: работа с байтами может испортить символы
// bytes := []byte(str)
// bytes[0] = 'X' // Может сломать UTF-8 последовательность
// ПРАВИЛЬНО: преобразование в слайс рун
runes := []rune(str)
if len(runes) > 0 {
runes[0] = 'Х' // Заменяем первую букву
}
result := string(runes)
fmt.Println(result) // "Хривет"
}
3. Производительность преобразований
При работе с большими строками учитывайте производительность:
package main
import (
"fmt"
"strings"
"time"
)
func main() {
largeStr := strings.Repeat("Hello ", 10000)
start := time.Now()
// Медленно: создаёт копию всех данных
runes := []rune(largeStr)
if len(runes) > 0 {
runes[0] = 'h'
}
_ = string(runes)
fmt.Printf("Через []rune: %v\n", time.Since(start))
start = time.Now()
// Быстрее: использует Builder
var builder strings.Builder
builder.WriteString("h")
builder.WriteString(largeStr[1:])
_ = builder.String()
fmt.Printf("Через Builder: %v\n", time.Since(start))
}
Ключевые выводы
- Строки в Go неизменяемы — прямое изменение элементов невозможно.
- Для модификации строк необходимо создавать новые строки на основе существующих.
- Используйте
[]runeдля работы с Unicode-символами, особенно когда важна правильная обработка многобайтовых символов. - Для производительности при частых модификациях больших строк используйте
strings.Builderили[]byteс последующим преобразованием в строку. - Помните о UTF-8 — индексация по байтам (через
str[i]) возвращает байты, а не символы, что может привести к ошибкам с не-ASCII строками.
Неизменяемость строк — это фундаментальное свойство языка Go, которое обеспечивает безопасность, производительность и простоту работы с конкурентным кодом. Все стандартные библиотеки и идиоматичный код Go построены с учётом этого свойства.