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

Что такое тип rune?

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

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

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

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

Что такое тип rune в Go?

rune — это встроенный целочисленный тип данных в языке Go, который представляет собой синоним для типа int32. Его ключевое предназначение — хранение одной кодовой точки Unicode (Unicode code point). Это фундаментальное отличие от типа byte (синоним uint8), который предназначен для хранения сырых байтов и может представлять только символы ASCII или часть многобайтовой последовательности.

Основные характеристики и назначение

  1. Представление Unicode: Каждому символу в стандарте Unicode присваивается уникальный числовой идентификатор — кодовая точка. Например, латинская буква 'A' имеет кодовую точку U+0041 (десятичное 65), а смайлик '😀' — U+1F600 (десятичное 128512). Тип rune может хранить любое из этих значений.

    var r1 rune = 'A'       // 65
    var r2 rune = '😀'      // 128512
    var r3 rune = '世'      // 19990
    
  2. Работа со строками: Строки в Go по своей сути являются неизменяемыми массивами байт ([]byte), но при итерации с помощью for range происходит автоматическое декодирование UTF-8, и каждая итерация возвращает именно rune (кодовую точку) и её стартовую позицию в байтах.

    s := "Hello, 世界!"
    for i, r := range s { // r имеет тип rune
        fmt.Printf("Позиция %d: символ %c (кодовая точка U+%04X)\n", i, r, r)
    }
    // Вывод:
    // Позиция 0: символ H (кодовая точка U+0048)
    // Позиция 7: символ 世 (кодовая точка U+4E16) // Обратите внимание на скачок индекса!
    
    Это самый корректный и безопасный способ перебора символов в строке, так как он гарантированно обрабатывает многобайтовые символы (например, кириллицу, иероглифы, эмодзи) как единое целое.

  1. Преобразование строк и срезов: Строку можно явно преобразовать в срез рун []rune. При этом происходит декодирование всей строки UTF-8 и создание среза, где каждый элемент — кодовая точка символа. Это удобно для операций, требующих индексирования по символам (а не по байтам), но создаёт копию данных и потребляет больше памяти (4 байта на символ против 1-4 байт в исходной строке UTF-8).
    str := "Привет"
    runeSlice := []rune(str) // []int32{1055, 1088, 1080, 1074, 1077, 1090}
    fmt.Println(string(runeSlice[0])) // "П" - прямое индексирование по символу
    

Почему rune, а не int32 или char?

  • Семантическая ясность: Имя rune явно указывает на намерение разработчика работать с символами Unicode, а не просто с 32-битными целыми числами. Это делает код самодокументируемым.
  • Отличие от C char: В языке C тип char — это и символ, и байт. В Go это разделено: byte (uint8) — для байтов, rune (int32) — для символов Unicode. Это помогает избежать путаницы при обработке текста в различных кодировках.
  • Поддержка литералов: Литералы рун записываются в одинарных кавычках и могут быть как одиночными символами ('a'), так и escape-последовательностями ('\n', '\u4E16', '\U0001F600').

Практическое применение

  • Корректный подсчёт символов: len(s) возвращает длину в байтах. Для подсчёта количества символов (графем) необходимо использовать utf8.RuneCountInString(s) или преобразование в []rune.
    s := "🎉🎊"
    fmt.Println(len(s))        // 8 байт (по 4 на каждый эмодзи)
    fmt.Println(len([]rune(s))) // 2 символа
    
  • Манипуляции со строками: Реализация функций, подобных strings.Reverse, требует работы с рунами, чтобы не разбивать многобайтовые символы.
  • Парсинг и валидация текста: При разборе сложного текста (логических, поисковых запросов) часто требуется анализ на уровне символов Unicode.

Итог: Тип rune — это не просто int32, а важная абстракция уровня языка для безопасной и корректной обработки текста в кодировке UTF-8. Его использование является идиоматическим способом работы с отдельными символами в Go и критически важно для написания кросс-культурных и устойчивых к сложному тексту приложений.