Ответ
В Go строка (string
) — это неизменяемая последовательность байт. Это эффективно, но создает сложности при работе с языками, где символы могут занимать больше одного байта (например, кириллица, иероглифы, эмодзи).
Для корректной работы с такими символами в Go используется тип rune
.
Ключевые концепции:
rune
— это псевдоним (alias) для типаint32
. Он представляет собой один кодовый пункт (code point) Unicode.- Строка — это UTF-8 закодированная последовательность байт. Один символ может состоять из 1-4 байт.
Преобразование и итерация:
Чтобы работать со строкой как с последовательностью символов (рун), а не байт, ее нужно преобразовать в срез рун []rune
.
s := "Привет, мир! 👋"
// Преобразование строки в срез рун
runes := []rune(s)
// len() для строки вернет количество байт, а для среза рун - количество символов
fmt.Printf("Байт в строке: %dn", len(s)) // Выведет: 25
fmt.Printf("Рун (символов) в строке: %dn", len(runes)) // Выведет: 15
// Обратное преобразование
newS := string(runes)
fmt.Println(newS)
Правильная итерация по символам:
Использование range
для итерации по строке — это идиоматичный и правильный способ, так как range
автоматически декодирует UTF-8 символы в руны.
s := "Go-рулит"
// range возвращает индекс начала руны в байтах и саму руну
for i, r := range s {
fmt.Printf("Индекс байта: %d, Символ: %cn", i, r)
}
Вывод:
- Для получения количества символов используйте
utf8.RuneCountInString(s)
илиlen([]rune(s))
. - Для итерации по символам всегда используйте
for ... range
.