Как устроены строки в Go
Строки в Go — это неизменяемые последовательности байт, которые обычно интерпретируются как текст в кодировке UTF-8. Это означает, что после создания строки её содержимое нельзя изменить — любая операция, которая выглядит как изменение, на самом деле создаёт новую строку. Такая реализация обеспечивает безопасность при работе в многопоточных приложениях и эффективное использование памяти.
Как это работает
Внутренне строка в Go представляет собой структуру, состоящую из указателя на массив байт и длины. Байты хранятся в неизменяемом участке памяти, поэтому строки можно безопасно передавать между горутинами без дополнительной синхронизации. Индексация строки s[i] возвращает байт, а не символ, что часто приводит к путанице у новичков.
Кодировка UTF-8 является переменной длины: символы могут занимать от 1 до 4 байт. Например, латинские буквы и цифры занимают 1 байт, а большинство кириллических символов — 2 байта. Поэтому для корректной работы с текстом, содержащим не-ASCII символы, необходимо использовать тип rune (алиас для int32), который представляет один символ Unicode.
Пример
package main
import "fmt"
func main() {
s := "Привет, мир!"
// Доступ по индексу возвращает байт, а не символ
fmt.Println(s[0]) // 208 — первый байт первого символа 'П'
// Перебор строки по рунам (символам Unicode)
for _, r := range s {
fmt.Printf("%#U ", r)
}
// Вывод: U+041F U+0440 U+0438 U+0432 U+0435 U+0442 U+002C U+0020 U+043C U+0438 U+0440 U+0021
}В этом примере видно, что s[0] возвращает число 208 — это первый байт двухбайтового символа 'П'. Для получения символов используется цикл for range, который автоматически декодирует UTF-8 и возвращает руны.
Подводные камни
- Индексация по байтам:
s[i]возвращает байт, поэтому при работе с не-ASCII текстом нужно использоватьfor rangeили преобразование в[]rune. - Неизменяемость: Попытка изменить строку через
s[i] = ...вызовет ошибку компиляции. Для изменения строки нужно создавать новую, например, с помощьюstrings.Builderили конкатенации. - Конкатенация: Частая конкатенация строк через
+может быть неэффективной из-за создания новых строк. В циклах лучше использоватьstrings.Builder. - Преобразования: Преобразование
stringв[]byteи обратно копирует данные, что может быть затратно для больших строк.
Когда использовать
Строки в Go — основной тип для работы с текстом. Они подходят для хранения сообщений, обработки данных, работы с сетевыми протоколами и файлами. Благодаря встроенной поддержке UTF-8, Go хорошо подходит для интернациональных приложений. Однако для интенсивных манипуляций с текстом (например, построение больших строк) стоит использовать strings.Builder или bytes.Buffer.
Коротко
- Строка — неизменяемая последовательность байт, обычно в UTF-8.
- Индексация возвращает байт, а не символ; для символов используйте
for rangeили[]rune. - Строки безопасны для конкурентного доступа, но операции изменения создают новые строки.
- Для эффективной сборки строк используйте
strings.Builder.
Похожие вопросы
- Что такое SOLID16%
- Что такое утиная типизация16%
- Какие бывают типы в Go16%
- Что такое микросервисная архитектура16%
- Как завершить много горутин16%
- Насколько увеличивается слайс при append16%
- В чем разница между императивным и декларативным16%
- Возможны ли случаи, когда перебор по слайсу будет быстрее чем по map16%
