Типы символов в Golang

GolangGolangBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В предыдущем разделе мы обсудили часто используемые числовые типы. В этом разделе мы узнаем о символьных типах в Go.

Основные понятия:

  • ASCII-кодировка
  • UTF-8 кодировка
  • Юникод (Unicode)
  • byte
  • rune

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/BasicsGroup(["Basics"]) go(("Golang")) -.-> go/DataTypesandStructuresGroup(["Data Types and Structures"]) go(("Golang")) -.-> go/FunctionsandControlFlowGroup(["Functions and Control Flow"]) go(("Golang")) -.-> go/AdvancedTopicsGroup(["Advanced Topics"]) go/BasicsGroup -.-> go/variables("Variables") go/DataTypesandStructuresGroup -.-> go/strings("Strings") go/FunctionsandControlFlowGroup -.-> go/functions("Functions") go/AdvancedTopicsGroup -.-> go/text_templates("Text Templates") go/AdvancedTopicsGroup -.-> go/base64_encoding("base64 Encoding") subgraph Lab Skills go/variables -.-> lab-149068{{"Типы символов в Golang"}} go/strings -.-> lab-149068{{"Типы символов в Golang"}} go/functions -.-> lab-149068{{"Типы символов в Golang"}} go/text_templates -.-> lab-149068{{"Типы символов в Golang"}} go/base64_encoding -.-> lab-149068{{"Типы символов в Golang"}} end

ASCII-кодировка

В первые дни развития компьютеров использовался формат кодировки ASCII (American Standard Code for Information Interchange). Он представлял символы с использованием 7 бит и мог представить 128 (2^7) символов. Символы с бита 0 по 31 и бит 127 представляли непечатаемые управляющие символы, в то время как символы с бита 32 по 126 представляли обычные заглавные и строчные буквы, цифры и знаки препинания. Подробности см. в таблице.

По мере развития компьютеров возникла необходимость поддержки разных языков. ASCII-кодировка для этого была недостаточной. В результате разные языки разработали свои собственные форматы кодировки, например, GB2312 для упрощенного китайского, EUC - KR для корейского и KOI8 - R для русского.

Однако, учитывая множество языковых семейств в мире, стало необходимо иметь единый формат кодировки, который мог бы объединить все языки. Для этого была создана система Юникод (Unicode).

Юникод (Unicode)

В 1991 году Консорциум Юникода (Unicode Consortium) выпустил первую версию набора символов Юникод. Его цель заключалась в объединении всех языков в единый формат кодировки, что позволило бы компьютерам по всему миру более легко отображать и обрабатывать текст, а также избегать проблем совместимости в многоязычных средах.

Однако Юникод был только набором символов; он определял коды символов, но не то, как они должны храниться. Это вызвало трудности с широким распространением в течение длительного времени, пока не пришел расцвет Интернета.

UTF-8 кодировка

С постоянным развитием Интернета популярностью пользуется UTF-8, кодировка реализации Юникода (Unicode). Это кодировка переменной длины, то есть разные символы могут иметь разную длину в байтах в UTF-8.

Например, английские буквы, которые входят в диапазон ASCII, представляются 1 байтом. Символ 'y' (Юникод-значение 121) занимает 1 байт.

В повседневной жизни большинство китайских символов занимает 3 байта. Например, символ '实' (Юникод-значение 23454) занимает 3 байта.

Однако есть некоторые китайские символы, которые занимают 4 байта. Это связано с тем, что существует более 100 000 китайских символов, но, как показано на диаграмме ниже, 3 байта могут представить только немного более 60 000 символов, поэтому небольшое количество китайских символов требует 4 байт для представления.

Еще одно преимущество UTF-8 кодировки заключается в том, что она обратно совместима с ASCII-кодировкой. Фактически, ASCII является подмножеством UTF-8. Первые 128 символов в UTF-8 соответствуют по одному символу ASCII. Это означает, что программное обеспечение, изначально использующее ASCII, может продолжать использоваться с минимальными или без изменений. Благодаря этим преимуществам UTF-8 постепенно стал предпочтительным форматом кодировки.

Создатели языка программирования Go, Роб Пайк (Rob Pike) и Кен Томпсон (Ken Thompson), также изобрели UTF-8, поэтому Go имеет особую привязанность к UTF-8. Go требует, чтобы файлы исходного кода сохранялись в UTF-8 кодировке. При работе с текстовыми символами UTF-8 кодировка является предпочтительным выбором. Более того, стандартная библиотека предоставляет множество функций, связанных с кодированием и декодированием UTF-8.

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, то можно увидеть, что ASCII-значение буквы 'A' равно 65. Когда мы используем заглушку для целых чисел %d для вывода значения, оно также равно 65.

Таким образом, очевидно, что byte в Go эквивалентен uint8 среди целочисленных типов. То же самое относится к rune, но он представляет другой диапазон целочисленных значений.

rune является псевдонимом для int32 и занимает четыре байта (32 бита). Он используется для представления составных символов, таких как эмодзи.

Обновите файл byte.go следующим кодом:

package main

import "fmt"

func main() {
    var a rune = '😊' // Smile emoji
    fmt.Printf("Value of a: %c\n", a)

    var b int32 = 9829 // Decimal representation of a Unicode character (Heart symbol)
    fmt.Printf("Value of b: %c\n", b)
    var c rune = 0x1F496 // Hexadecimal representation of a Unicode character (Sparkling heart emoji)
    fmt.Printf("Value of c: %c\n", c)

    var d rune = '\u0041' // Unicode character represented by its code point (Capital letter 'A')
    fmt.Printf("Value of d: %c\n", d)
    var e rune = '\U0001F609' // Unicode character represented by its code point (Winking face emoji)
    fmt.Printf("Value of e: %c\n", e)
}

После запуска программы будет выведено следующее:

go run byte.go

Примечание: Запускайте программу в терминале на рабочем столе или в WebIDE, но не в терминале, расположенном в верхней части виртуальной машины LabEx.

Value of a: 😊
Value of b: ♥
Value of c: 💖
Value of d: A
Value of e: 😉
  • Переменная a представляет эмодзи улыбающегося лица '😊'.
  • Переменная b инициализируется десятичным представлением символа Юникода (9829), которое соответствует символу сердца '♥'.
  • Переменная c инициализируется шестнадцатеричным представлением символа Юникода (0x1F496), которое соответствует эмодзи сверкающего сердца '💖'.
  • Переменная d представляет заглавную букву 'A' с использованием формата Юникода \u0041.
  • Переменная e представляет эмодзи подмигивающего лица '😉' с использованием формата \U с кодовой точкой 0001F609.

Примечание: В Go одинарные и двойные кавычки не эквивалентны. Одинарные кавычки используются для представления символов, в то время как двойные кавычки используются для объявления строк. Поэтому при объявлении типов byte и rune следует использовать одинарные кавычки, иначе возникнет ошибка.

Вопрос для самопроверки

Теперь давайте закрепим то, что мы узнали. Создайте новый файл с именем rune.go и введите следующий код. Завершите код так, чтобы шестнадцатеричное число 0x1F648 было присвоено переменной a, и программа корректно вывела его значение.

  • Требования: Файл rune.go должен быть расположен в директории ~/project.
  • Подсказка: Для длинных шестнадцатеричных чисел необходимо использовать определенный формат.
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 может быть использован для представления символов Юникода.
  • Тип данных byte может представлять символы ASCII, а тип данных rune может представлять символы Юникода.

В этом разделе мы сначала объяснили, что такое ASCII, UTF-8 и Юникод. Затем мы рассмотрели взаимосвязь между символьными типами данных byte и rune и целочисленными типами данных.