Ру

Руни у Go

3 вправи

Про концепцію Руни

Тип rune у Go є псевдонімом для int32. Оскільки rune має базовий тип int32, він зберігає знакове 32-бітне ціле значення. Однак, на відміну від типу int32, ціле значення, що зберігається в типі rune, представляє один символ Unicode.

Unicode і кодові точки Unicode

Unicode є надмножиною ASCII, яка представляє символи, призначаючи кожному символу унікальне число. Це унікальне число називається кодовою точкою Unicode. Unicode має на меті представити всі символи світу, включаючи різні алфавіти, числа, символи та навіть емодзі, як кодові точки Unicode.

У Go тип rune представляє одну кодову точку Unicode.

У наступній таблиці наведено приклади символів Unicode разом з їхніми кодовими точками Unicode та десятковими значеннями:

Символ Unicode Кодова точка Unicode Десяткове значення
0 U+0030 48
A U+0041 65
a U+0061 97
¿ U+00BF 191
π U+03C0 960
🧠 U+1F9E0 129504

UTF-8

UTF-8 є кодуванням символів зі змінною шириною, яке використовується для кодування кожної кодової точки Unicode як 1, 2, 3 або 4 байтів. Оскільки кодову точку Unicode можна закодувати щонайбільше 4 байтами, тип rune має вміщати до 4 байтів даних. Ось чому тип rune є псевдонімом для int32, оскільки тип int32 здатен вмістити до 4 байтів даних.

Файли з вихідним кодом Go кодуються за допомогою UTF-8.

Використання рун

Змінні типу rune оголошуються шляхом розміщення символу в одинарних лапках:

myRune := '¿'

Оскільки rune є лише псевдонімом для int32, виведення типу rune дасть int32:

myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32

Аналогічно, виведення значення руни дасть її ціле (десяткове) значення:

myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191

Щоб вивести символ Unicode, представлений руною, використовуйте дієслово форматування %c:

myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿

Щоб вивести кодову точку Unicode, представлену руною, використовуйте дієслово форматування %U:

myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF

Окрім визначення руни шляхом взяття символу в одинарні лапки, можна також вказати шістнадцяткове або десяткове число:

myRune := rune(0xbf)
myRune = 191
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿

Руни та рядки тексту (англ. string)

Рядки тексту в Go кодуються за допомогою UTF-8, що означає, що вони містять символи Unicode. Символи в рядках тексту зберігаються та кодуються як 1, 2, 3 або 4 байти залежно від символу Unicode, який вони представляють.

У Go для представлення послідовностей використовуються зрізи, і ці зрізи можна перебирати за допомогою range. Коли ми перебираємо рядок тексту, Go перетворює його на послідовність рун, кожна з яких займає 4 байти (памʼятаємо, тип rune є псевдонімом для int32!)

Хоча рядок тексту є лише зрізом байтів, ключове слово range перебирає руни рядка, а не його байти.

У цьому прикладі змінна index представляє початковий індекс байтової послідовності поточної руни, а змінна char представляє поточну руну:

myString := "❗hello"
for index, char := range myString {
  fmt.Printf("Index: %d\tCharacter: %c\t\tCode Point: %U\n", index, char, char)
}
// Output:
// Index: 0	Character: ❗		Code Point: U+2757
// Index: 3	Character: h		Code Point: U+0068
// Index: 4	Character: e		Code Point: U+0065
// Index: 5	Character: l		Code Point: U+006C
// Index: 6	Character: l		Code Point: U+006C
// Index: 7	Character: o		Code Point: U+006F

Оскільки руни можуть зберігатися як 1, 2, 3 або 4 байти, довжина рядка тексту не завжди може дорівнювати кількості символів у рядку. Використовуйте вбудовану функцію len, щоб отримати довжину рядка тексту в байтах, і функцію utf8.RuneCountInString, щоб отримати кількість рун у рядку тексту:

import "unicode/utf8"

myString := "❗hello"
stringLength := len(myString)
numberOfRunes := utf8.RuneCountInString(myString)

fmt.Printf("myString - Length: %d - Runes: %d\n", stringLength, numberOfRunes)
// Output: myString - Length: 8 - Runes: 6

Перетворення типів рун

Зріз рун можна перетворити на рядок тексту:

myRuneSlice := []rune{'e', 'x', 'e', 'r', 'c', 'i', 's', 'm'}
myString := string(myRuneSlice)
fmt.Println(myString)
// Output: exercism

Аналогічно, рядок тексту можна перетворити на зріз рун. Памʼятайте, без дієслів форматування виведення руни дає її ціле (десяткове) значення:

myString := "exercism"
myRuneSlice := []rune(myString)
fmt.Println(myRuneSlice)
// Output: [101 120 101 114 99 105 115 109]
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Руни

Практика заблокована

Розблокуйте ще 2 вправи, щоб практикувати концепцію Руни