Перейти до основного вмісту
Модуль 4 · Урок 4 із 519/50 у курсі~12 min
Модульні уроки (4/5)

Рядки, байти та руни

У Go string — це незмінна послідовність байтів. Рядкові літерали закодовані в UTF-8. rune є псевдонімом для int32 та представляє одну кодову точку Unicode.

Важливо розуміти різницю між байтами та рунами уникайте помилок, коли рядок містить наголоси, емодзі, ідеограми тощо не-ASCII символ.

string = байти, а не символи

Go
s := "ciaò"
fmt.Println(len(s))   // 5 — not 4!
fmt.Println(s[0])     // 99 ('c' as a byte)
fmt.Println(s[3])     // 195 (first byte of 'ò' in UTF-8)

len(s) повертає кількість байтів, невидимих ​​символів. Індексація s[i] повертає i-й байт (uint8), а не символ.

for range повторює руни

for i, r := range s декодує UTF-8 на льоту: i є зміщенням байтів початку руни, r є руною (int32):

Go
s := "ciaò"
for i, r := range s {
    fmt.Printf("%d %c (U+%04X)\n", i, r, r)
}
// 0 c (U+0063)
// 1 i (U+0069)
// 2 a (U+0061)
// 3 ò (U+00F2)   <- starts at byte 3, takes 2 bytes

[]rune(s): посимвольне індексування

Явне перетворення: виділяє новий фрагмент рун. Дорого, але іноді необхідно:

Go
runes := []rune("ciaò")
fmt.Println(len(runes))    // 4
fmt.Println(string(runes[3])) // ò

string(runes) є зворотним перетворенням: приймає []rune і створює рядок UTF-8.

Рядки незмінні

Go
s := "ciao"
// s[0] = 'C'   // ERROR: cannot assign to s[0]

Щоб мутувати, конвертуйте в []byte або []rune, оперуйте, конвертуйте назад:

Go
b := []byte(s)
b[0] = 'C'
s = string(b)   // "Ciao"

Конкатенація

Оператор + працює, але для багатьох конкатенацій у циклі використовуйте strings.Builder (більш ефективний, уникає проміжного розподілу):

Go
var sb strings.Builder
for i := 0; i < 5; i++ {
    sb.WriteString("ab")
}
fmt.Println(sb.String())   // "ababababab"

Корисні пакети

  • strings: Contains, HasPrefix, Split, Join, ToUpper, Replace...
  • strconv: Atoi, Itoa, ParseFloat, FormatInt...
  • unicode: IsLetter, IsDigit, ToUpper...
  • unicode/utf8: RuneCountInString (альтернатива len([]rune(s))).

Спробуйте

вправи#go.m4.l4.e1
Спроби: 0Завантаження…

Ітерація рядка s з діапазоном і друкованим індексом і руною за допомогою %d %c.

Завантаження редактора…
Показати підказку

діапазон над рядком повертає байт-зміщення + руну.

Рішення доступне після 3 спроб

вправи#go.m4.l4.e2
Спроби: 0Завантаження…

Перетворіть s на []руну та виведіть її довжину в символах.

Завантаження редактора…
Показати підказку

Явне перетворення: `[]rune(s)`.

Рішення доступне після 3 спроб

Quiz#go.m4.l4.e3
Готовий

Що таке len("ciaò")?

Go
s := "ciaò"
fmt.Println(len(s))
Варіанти відповідей

Підведення підсумків

  • string = незмінна послідовність байтів, закодована UTF-8.
  • len(s) = байтів; s[i] = i-й байт (uint8).
  • for i, r := range s розшифровує руни; i — зміщення байтів.
  • []rune(s) для індексування за символами (коштовно, розподіляє).
  • Щоб змінити: пройдіть через []byte або []rune.
  • Для об’єднання в цикл: strings.Builder.
  • Ключові пакети: strings, strconv, unicode, unicode/utf8.