Что такое тип `rune` в Go и чем он отличается от `byte`?

Ответ

rune в Go — это псевдоним (alias) для типа int32. Он используется для представления кодовой точки Unicode (Unicode code point). В Go строки кодируются в UTF-8, где один символ может занимать от 1 до 4 байт.

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

  • rune (int32): Представляет один, возможно многобайтовый, символ. Например, 'A', 'ф' или '😊'.
  • byte (uint8): Представляет один байт данных. Для символов из набора ASCII byte и rune могут быть взаимозаменяемы, но для всего, что выходит за его пределы (кириллица, эмодзи), один символ будет состоять из нескольких байт.

Итерация по строке:

Разница становится очевидной при итерации по строке. Стандартный цикл for...range по строке итерируется именно по рунам, корректно декодируя UTF-8 символы.

package main

import "fmt"

func main() {
    s := "Привет, мир!"

    // Итерация по байтам (некорректно для многобайтовых символов)
    fmt.Println("Итерация по байтам:")
    for i := 0; i < len(s); i++ {
        fmt.Printf("%c ", s[i]) // Выведет некорректные символы для кириллицы
    }
    fmt.Println("nДлина в байтах:", len(s)) // len() возвращает количество байт

    // Итерация по рунам (правильный способ)
    fmt.Println("nИтерация по рунам:")
    for _, r := range s {
        fmt.Printf("%c ", r)
    }
    fmt.Println("nДлина в рунах:", len([]rune(s)))
}

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