Введение
В предыдущем разделе мы рассмотрели наиболее часто используемые числовые типы. В этой части мы перейдем к изучению символьных типов данных в языке Go.
Основные темы:
- Кодировка ASCII
- Кодировка UTF-8
- Набор символов Unicode
- Тип
byte - Тип
rune
Кодировка ASCII
На заре компьютерной эры использовался формат кодирования ASCII (American Standard Code for Information Interchange). В нем для представления символа использовалось 7 бит, что позволяло закодировать 128 (2^7) различных знаков. Символы с кодами от 0 до 31, а также 127, являются управляющими и не отображаются на экране. Символы с кодами от 32 до 126 включают привычные нам латинские буквы (заглавные и строчные), цифры и знаки препинания. Подробности можно найти в таблице ASCII.
С развитием технологий возникла необходимость поддерживать разные языки мира. Кодировки ASCII для этих целей было недостаточно. В результате в разных странах появились свои стандарты, такие как GB2312 для упрощенного китайского, EUC-KR для корейского и KOI8-R для русского языка.
Однако наличие множества разрозненных кодировок создавало путаницу. Возникла потребность в едином стандарте, который мог бы объединить все языки мира. Так появился Unicode.
Набор символов Unicode
В 1991 году консорциум Unicode выпустил первую версию одноименного набора символов. Его целью было свести все мировые языки в единый формат кодирования, чтобы компьютеры по всему миру могли легко отображать и обрабатывать тексты, избегая проблем с совместимостью в многоязычных средах.
Важно понимать, что Unicode — это именно набор символов; он определяет уникальные коды для знаков, но не диктует способ их хранения в памяти. Из-за этого стандарт долгое время внедрялся с трудом, пока не начался бурный рост интернета.
Кодировка UTF-8
С развитием интернета широкое распространение получила кодировка UTF-8 — один из способов реализации Unicode. Это кодировка с переменной длиной символа: разные знаки в UTF-8 могут занимать разное количество байтов.
Например, латинские буквы, входящие в диапазон ASCII, занимают всего 1 байт. Символ 'y' (код Unicode 121) весит 1 байт.
Большинство часто используемых китайских иероглифов занимают 3 байта. Например, иероглиф '实' (код Unicode 23454) требует 3 байта.
Существуют и более редкие символы, которые занимают 4 байта. Это связано с тем, что в китайском языке более 100 000 иероглифов, а трехбайтовая схема позволяет закодировать чуть более 60 000 значений.
Еще одно преимущество UTF-8 — обратная совместимость с ASCII. По сути, ASCII является подмножеством UTF-8. Первые 128 символов UTF-8 полностью совпадают с ASCII. Это означает, что старое программное обеспечение может работать с текстами UTF-8 без серьезных доработок. Благодаря этим достоинствам UTF-8 стала стандартом де-факто.
Создатели языка Go, Роб Пайк и Кен Томпсон, также являются авторами UTF-8, поэтому в Go реализована нативная поддержка этой кодировки. Исходные файлы Go должны быть сохранены именно в UTF-8. При работе с текстом UTF-8 является приоритетным выбором, а стандартная библиотека Go предоставляет множество функций для кодирования и декодирования таких данных.
byte и rune
Тип byte является псевдонимом для uint8 и занимает один байт (8 бит). Он идеально подходит для представления всех символов таблицы ASCII. Однако, поскольку диапазон значений byte ограничен (256 значений или 2^8), для работы со сложными символами, такими как иероглифы или эмодзи, нам необходим тип rune.
Создайте новый файл с именем byte.go и введите следующий код:
cd ~/project
touch byte.go
package main
import "fmt"
func main() {
var a byte = 76
fmt.Printf("Value of a: %c\n", a)
var b uint8 = 76
fmt.Printf("Value of b: %c\n", b)
var c byte = 'L'
fmt.Printf("Value of c: %c\n", c)
}
После запуска программы вы увидите следующий результат:
go run byte.go
Value of a: L
Value of b: L
Value of c: L
Спецификатор %c используется для вывода символьного представления значения. Как видите, типы byte и uint8 ведут себя идентично при одинаковых значениях. Если заглянуть в таблицу ASCII, можно увидеть, что коду 76 соответствует буква 'L'. Если использовать спецификатор %d для вывода целого числа, мы получим то же самое числовое значение.
Таким образом, byte в Go — это то же самое, что и целое число uint8. Аналогичная логика применима и к rune, но этот тип охватывает гораздо больший диапазон значений.
Тип rune является псевдонимом для int32 и занимает четыре байта (32 бита). Он используется для представления сложных символов Unicode, включая эмодзи.
Обновите файл byte.go, используя следующий код:
package main
import "fmt"
func main() {
var a rune = '😊' // Смайлик
fmt.Printf("Value of a: %c\n", a)
var b int32 = 9829 // Десятичное представление символа Unicode (Сердце)
fmt.Printf("Value of b: %c\n", b)
var c rune = 0x1F496 // Шестнадцатеричное представление символа Unicode (Сияющее сердце)
fmt.Printf("Value of c: %c\n", c)
var d rune = '\u0041' // Символ Unicode через кодовую точку (Заглавная 'A')
fmt.Printf("Value of d: %c\n", d)
var e rune = '\U0001F609' // Символ Unicode через кодовую точку (Подмигивающий смайлик)
fmt.Printf("Value of e: %c\n", e)
}
Запустите программу, чтобы увидеть результат:
go run byte.go
Примечание: Запускайте программу в терминале Desktop или WebIDE. Избегайте запуска во вкладке Terminal, расположенной в верхней части виртуальной машины LabEx.
Value of a: 😊
Value of b: ♥
Value of c: 💖
Value of d: A
Value of e: 😉
- Переменная
aсодержит эмодзи '😊'. - Переменная
bинициализирована десятичным кодом Unicode (9829), что соответствует символу сердца '♥'. - Переменная
cинициализирована шестнадцатеричным кодом (0x1F496), соответствующим эмодзи '💖'. - Переменная
dпредставляет букву 'A' через формат Unicode\u0041. - Переменная
eпредставляет подмигивающий смайлик через формат\Uс кодовой точкой0001F609.
Важно: В языке Go одинарные и двойные кавычки имеют разное значение. Одинарные кавычки используются для отдельных символов (литералов), а двойные — для объявления строк. Поэтому при работе с типами byte и rune необходимо использовать только одинарные кавычки, иначе возникнет ошибка компиляции.
Проверка знаний
Теперь закрепим пройденный материал. Создайте файл rune.go и напишите код, в котором переменной a присваивается шестнадцатеричное значение 0x1F648, после чего программа должна корректно вывести этот символ.
- Требования: Файл
rune.goдолжен находиться в директории~/project. - Подсказка: Для длинных шестнадцатеричных кодов Unicode необходимо использовать специальный формат записи.
package main
import "fmt"
func main() {
var a rune = 0x1F648
fmt.Printf("The value of a is: %c\n", a)
}
Резюме
Давайте подведем итоги того, что мы изучили в этом разделе:
- Символы ASCII занимают один байт и включают 128 знаков.
- Кодировка UTF-8 — это реализация Unicode с переменной длиной символа. Количество байтов зависит от конкретного знака.
- Тип данных
byteиспользуется для работы с символами ASCII, в то время какruneпредназначен для полноценной поддержки Unicode. - Тип
byteтехнически идентиченuint8, аrune—int32.
В ходе этой лабораторной работы мы разобрали основы ASCII, UTF-8 и Unicode, а также выяснили, как символьные типы byte и rune соотносятся с целочисленными типами данных в Go.



