Преобразование строк: []rune и []byte

1. Преобразование в []rune

Синтаксис

text := "Привет"
runes := []rune(text)

Результат: Срез рун, где каждый элемент — один Unicode-символ.


Полный пример

text := "Привет"
runes := []rune(text)

fmt.Printf("text: %s\n", text)
fmt.Printf("len(text) = %d байт\n", len(text))
fmt.Printf("[]rune(text): %v\n", runes)
fmt.Printf("len(runes) = %d символов\n", len(runes))

Вывод:

text: Привет
len(text) = 12 байт
[]rune(text): [1055 1088 1080 1074 1077 1090]
len(runes) = 6 символов

Объяснение:

  • "Привет" = 12 байт (6 символов × 2 байта)
  • []rune = 6 элементов (каждый — код символа)

2. Доступ к символам через []rune

text := "Привет"
runes := []rune(text)

for i, r := range runes {
    fmt.Printf("[%d] = %c (код: %d)\n", i, r, r)
}

Вывод:

[0] = П (код: 1055)
[1] = р (код: 1088)
[2] = и (код: 1080)
[3] = в (код: 1074)
[4] = е (код: 1077)
[5] = т (код: 1090)

Теперь можно работать как с обычным срезом.


3. Изменение символов через []rune

text := "Привет"
runes := []rune(text)

// Меняем первый символ
runes[0] = 'Ч'

// Конвертируем обратно в строку
newText := string(runes)

fmt.Println(text)     // "Привет" — оригинал не изменён
fmt.Println(newText)  // "Чривет"

Механизм: Строки иммутабельны, изменяем через срез рун.


4. Преобразование в []byte

Синтаксис

simple := "Go"
bytes := []byte(simple)

Результат: Срез байтов (UTF-8 представление).


Пример с ASCII

simple := "Go"
bytes := []byte(simple)

fmt.Printf("simple: %s\n", simple)
fmt.Printf("[]byte: %v\n", bytes)

Вывод:

simple: Go
[]byte: [71 111]

ASCII символы: 1 символ = 1 байт.


Пример с кириллицей

text := "Привет"
bytes := []byte(text)

fmt.Printf("text: %s\n", text)
fmt.Printf("[]byte: %v\n", bytes)
fmt.Printf("Длина: %d байт\n", len(bytes))

Вывод:

text: Привет
[]byte: [208 159 209 128 208 184 208 178 208 181 209 130]
Длина: 12 байт

Кириллица: 1 символ = 2 байта в UTF-8.


5. Обратное преобразование

Из []byte в string

bytes := []byte{71, 111}
text := string(bytes)

fmt.Println(text)  // "Go"

Из []rune в string

runes := []rune{1055, 1088, 1080, 1074, 1077, 1090}
text := string(runes)

fmt.Println(text)  // "Привет"

Обратная конвертация всегда через string().


6. Сравнение []rune vs []byte

Критерий []rune []byte
Элемент Unicode символ (code point) Байт (UTF-8)
Тип элемента rune (int32) byte (uint8)
Размер элемента 4 байта 1 байт
Длина для “Привет” 6 12
Применение Работа с символами Работа с байтами (сеть, файлы)

7. Когда использовать что

[]rune — работа с символами

text := "Привет, мир!"
runes := []rune(text)

// Получить первый символ
firstChar := runes[0]  // 'П'

// Заменить символ
runes[7] = '❤'
result := string(runes)  // "Привет,❤мир!"

// Подсчёт символов
count := len(runes)  // 12

Используйте для: Манипуляции с текстом, подсчёт символов.


[]byte — работа с данными

text := "Hello"
bytes := []byte(text)

// Передача по сети
conn.Write(bytes)

// Запись в файл
file.Write(bytes)

// XOR шифрование
bytes[0] ^= 0xFF

// Обратно в строку
encrypted := string(bytes)

Используйте для: I/O операции, криптография, низкоуровневая работа.


8. Практические примеры

Подсчёт гласных

text := "Привет"
runes := []rune(text)
vowels := "аеёиоуыэюяАЕЁИОУЫЭЮЯ"

count := 0
for _, r := range runes {
    if strings.ContainsRune(vowels, r) {
        count++
    }
}

fmt.Printf("Гласных: %d\n", count)  // 2 (и, е)

Реверс строки

text := "Привет"
runes := []rune(text)

// Разворот среза рун
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
    runes[i], runes[j] = runes[j], runes[i]
}

reversed := string(runes)
fmt.Println(reversed)  // "тевирП"

Замена символа

text := "Hello, World!"
runes := []rune(text)

// Заменить все 'o' на '0'
for i, r := range runes {
    if r == 'o' {
        runes[i] = '0'
    }
}

result := string(runes)
fmt.Println(result)  // "Hell0, W0rld!"

9. Производительность

Копирование данных

text := "Привет"

// Преобразование КОПИРУЕТ данные
runes := []rune(text)  // Выделяет новую память
bytes := []byte(text)  // Выделяет новую память

Важно: Преобразования не бесплатны — создаётся новый срез.


Оптимизация

// ❌ Плохо: много преобразований
for i := 0; i < 1000; i++ {
    runes := []rune(text)
    // работа с runes
}

// ✅ Хорошо: одно преобразование
runes := []rune(text)
for i := 0; i < 1000; i++ {
    // работа с runes
}

10. Итоги

[]rune(s) — преобразование в срез Unicode-символов
[]byte(s) — преобразование в срез байтов (UTF-8)
string([]rune) — обратное преобразование из рун
string([]byte) — обратное преобразование из байтов
[]rune позволяет корректно работать с символами
[]byte нужен для I/O операций и байтовой обработки
✅ Преобразования копируют данные — не бесплатны
✅ После преобразования можно изменять элементы как в обычном срезе

Ключевые паттерны:

// Работа с символами
runes := []rune(text)
runes[i] = 'X'
result := string(runes)

// Работа с байтами
bytes := []byte(text)
bytes[i] = 0xFF
result := string(bytes)

// Итерация (без преобразования)
for _, r := range text {  // r — rune
    fmt.Printf("%c", r)
}

Практическое правило:

Нужны символы (текст) → []rune
Нужны байты (данные)  → []byte
Только чтение         → for range (без преобразования)