Что такое `rune` в Go и в чем его отличие от `byte`?

Ответ

rune в Go — это псевдоним (алиас) для типа int32.

Он используется для представления Unicode Code Point (кодовой точки Юникода). В отличие от byte, который представляет один байт, rune может представлять любой символ, даже если для его кодирования в UTF-8 требуется несколько байт.

Ключевые отличия от byte:

  • Размер: byte (uint8) всегда 1 байт. rune (int32) — 4 байта.
  • Назначение: byte для работы с бинарными данными, rune — для работы с текстовыми символами.
  • Итерация по строке:
    • Стандартный for цикл по строке итерируется по байтам.
    • Цикл for ... range по строке итерируется по рунам (символам).

Пример, демонстрирующий разницу:

str := "Привет"

// 1. Итерация по байтам. Символы кириллицы в UTF-8 занимают 2 байта.
fmt.Printf("Длина в байтах: %dn", len(str)) // Вывод: Длина в байтах: 12

// 2. Итерация по рунам (символам).
runes := []rune(str)
fmt.Printf("Длина в рунах (символах): %dn", len(runes)) // Вывод: Длина в рунах (символах): 6

// Цикл for...range декодирует руны на лету
for i, r := range str {
    fmt.Printf("Индекс байта: %d, Символ: %cn", i, r)
}
// Вывод покажет, что индекс (i) скачет не на 1, а на 2 (размер символа в байтах)

Использование rune необходимо для корректной обработки многоязычного текста.

Ответ 18+ 🔞

Так, слушай, про rune в Go. Это ж, блядь, не просто так, это пиздец как важно, если с текстом работаешь.

Вот смотри, rune — это просто псевдоним для int32, типа. Но не думай, что это просто число. Это, сука, Unicode Code Point, кодовая точка, ёпта. По-простому — один целый символ, какой угодно. В отличие от этого убожества byte, который один байт — и нахер сдох, если символ больше байта.

Чем они, блядь, отличаются, эти два пидораса:

  • Размер: byte (uint8) — это один байт, коротышка. А rune (int32) — четыре байта, здоровый мужик, может вместить любого, даже самого ебучого иероглифа.
  • Для чего: byte — для бинарного дерьма, данных. rune — для нормальных человеческих букв и смайликов.
  • Итерация по строке — вот где пиздец:
    • Обычный for цикл по строке бежит по байтам. Полный отстой, если у тебя не ASCII.
    • А вот for ... range по строке — тот уже умный, он итерируется по рунам, то есть по нормальным символам.

Смотри пример, а то нихуя не понятно:

str := "Привет"

// 1. Считаем байты. Кириллица в UTF-8 — по 2 байта на букву.
fmt.Printf("Длина в байтах: %dn", len(str)) // Вывод: Длина в байтах: 12 (6 букв * 2 байта)

// 2. Считаем руны (символы). Вот это уже по-человечески.
runes := []rune(str)
fmt.Printf("Длина в рунах (символах): %dn", len(runes)) // Вывод: Длина в рунах (символах): 6

// Цикл for...range — он молодец, сам всё декодирует.
for i, r := range str {
    fmt.Printf("Индекс байта: %d, Символ: %cn", i, r)
}
// Смотри на индекс (i) — он будет прыгать не на 1, а на 2, потому что каждый символ — два байта. Вот и вся магия, блядь.

Короче, если хочешь работать с текстом и не обосраться — используй rune. Иначе потом будешь сидеть и думать, почему у тебя строка из трёх иероглифов длиной в 12 байт, и нихуя не сходится.