Какая абстракция используется в Go для представления символа Unicode?

Ответ

В Go для представления символа Unicode используется тип rune.

rune — это псевдоним (alias) для типа int32. Он предназначен для хранения кодовой точки Unicode (Unicode code point). Это позволяет ему представлять абсолютно любой символ из стандарта Unicode, включая эмодзи и символы различных языков, которые могут занимать до 4 байт.

// Символ 'A' (ASCII) и 'Я' (Кириллица) - оба являются рунами
var r1 rune = 'A'
var r2 rune = 'Я'

fmt.Printf("Символ: %c, Тип: %T, Кодовая точка: %dn", r1, r1, r1)
// Вывод: Символ: A, Тип: int32, Кодовая точка: 65

fmt.Printf("Символ: %c, Тип: %T, Кодовая точка: %dn", r2, r2, r2)
// Вывод: Символ: Я, Тип: int32, Кодовая точка: 1071

Отличие rune от byte

Важно не путать rune с byte:

  • byte: псевдоним для uint8. Представляет один байт данных. Подходит для работы с ASCII-символами, так как они кодируются одним байтом.
  • rune: псевдоним для int32. Представляет кодовую точку Unicode, которая может состоять из нескольких байт в кодировке UTF-8.

Строка в Go (string) — это, по сути, срез байт ([]byte) в кодировке UTF-8. Когда вы итерируетесь по строке с помощью for ... range, Go автоматически декодирует последовательности байт в rune, что делает работу с Unicode-текстом удобной и безопасной.

str := "Go♥"

// Итерация по байтам
for i := 0; i < len(str); i++ {
    fmt.Printf("%d: %x n", i, str[i]) // Выведет 4 байта (G, o, e2, 99, a5)
}

// Итерация по рунам (символам)
for _, r := range str {
    fmt.Printf("%c ", r) // Выведет 3 символа: G o ♥
}