← Назад к вопросам

Как превратить строку в руны?

1.3 Junior🔥 251 комментариев
#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Преобразование строки в руны (срезы rune) в Go

В Go строка (string) по своей сути является неизменяемой последовательностью байт, представляющей текст в кодировке UTF-8. Руна (rune) — это псевдоним для типа int32, который представляет собой Unicode code point (кодовую точку Юникода). Для корректной работы с символами Unicode (особенно многобайтовыми, как смайлики или иероглифы) необходимо преобразовывать строку в руны.

Основные способы преобразования

1. Использование приведения типа []rune(str)

Это самый простой и распространённый способ, который создает новый срез рун.

package main

import "fmt"

func main() {
    str := "Привет, мир! 🚀"
    
    // Преобразование строки в срез рун
    runes := []rune(str)
    
    fmt.Printf("Исходная строка: %s\n", str)
    fmt.Printf("Срез рун: %v\n", runes)
    fmt.Printf("Количество рун: %d\n", len(runes))
    fmt.Printf("Количество байт: %d\n", len(str))
    
    // Итерация по рунам
    for i, r := range runes {
        fmt.Printf("Руна %d: %c (код: %U)\n", i, r, r)
    }
}

2. Итерация с помощью range над строкой

При итерации с помощью range по строке, Go автоматически декодирует UTF-8 последовательности в руны.

func iterateWithRange(str string) {
    fmt.Println("Итерация с range:")
    for i, r := range str {
        fmt.Printf("Позиция %d: руна %c (код: %d)\n", i, r, r)
    }
}

3. Использование utf8.DecodeRuneInString

Для посимвольного декодирования без создания полного среза рун.

import "unicode/utf8"

func decodeManually(str string) {
    fmt.Println("Ручное декодирование:")
    for i := 0; i < len(str); {
        r, size := utf8.DecodeRuneInString(str[i:])
        fmt.Printf("Руна %c занимает %d байт\n", r, size)
        i += size
    }
}

Ключевые отличия и важные моменты

  1. Размер в памяти:
    []rune(str) создает новый срез в памяти, где каждая руна занимает 4 байта (тип int32). Исходная строка хранится как байты UTF-8 (от 1 до 4 байт на символ).

  2. Производительность:
    Преобразование []rune(str) требует O(n) времени и дополнительной памяти. Если нужно просто итерироваться по символам — лучше использовать range над строкой.

  3. Изменяемость:
    Строки в Go неизменяемы, а срез рун изменяем. После преобразования вы можете модифицировать отдельные руны:

str := "hello"
runes := []rune(str)
runes[0] = 'H' // Замена первой руны
modifiedStr := string(runes) // Обратное преобразование
fmt.Println(modifiedStr) // "Hello"
  1. Индексация:
    Прямая индексация строки (str[i]) возвращает байт, а не символ! Для получения символов нужно преобразование в руны.
str := "Эйяфьядлайёкюдль"
fmt.Printf("str[0] = %d (байт)\n", str[0]) // 208
runes := []rune(str)
fmt.Printf("runes[0] = %c (руна)\n", runes[0]) // 'Э'
  1. Обратное преобразование:
    Чтобы преобразовать срез рун обратно в строку, используйте string(runes):
runes := []rune{'П', 'р', 'и', 'в', 'е', 'т'}
str := string(runes)
fmt.Println(str) // "Привет"

Практический пример: обращение строки

func reverseString(s string) string {
    runes := []rune(s)
    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
        runes[i], runes[j] = runes[j], runes[i]
    }
    return string(runes)
}

func main() {
    fmt.Println(reverseString("Hello")) // "olleH"
    fmt.Println(reverseString("Привет")) // "тевирП"
    fmt.Println(reverseString("🐘🏀")) // "🏀🐘"
}

Когда использовать преобразование в руны?

  • Манипуляции с символами: замена, удаление, перестановка символов
  • Подсчёт символов (не байтов): utf8.RuneCountInString(str) или len([]rune(str))
  • Работа с конкретными символами Unicode по их индексу
  • Создание алгоритмов, чувствительных к Unicode (обращение строк, палиндромы)

Заключение

Преобразование строки в руны через []rune(str) — фундаментальная операция для корректной работы с Unicode в Go. Она позволяет обрабатывать текст на уровне символов, а не байтов, что критически важно для поддержки международных символов. Однако для простой итерации достаточно использовать range над строкой, чтобы избежать лишних аллокаций памяти. Всегда помните о разнице между байтами и рунами при работе со строками в Go!

Как превратить строку в руны? | PrepBro