0Pricing
Go Academy · Урок

Unicode и utf8

Обрабатывайте многобайтный текст

«Unicode и utf8» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Почему важен Unicode

Современные тексты содержат диакритические знаки, эмодзи и нелатинские письменности. Unicode присваивает каждому символу число, называемое кодовой точкой.

Go хранит строки в кодировке UTF-8 — кодировке переменной длины для этих кодовых точек.

package main

import "fmt"

func main() {
    s := "héllo 世界"
    fmt.Println(s)
}

Количество байтов на символ различается

В UTF-8 один символ занимает от 1 до 4 байтов:

  • Буквы ASCII: 1 байт.
  • Латиница с диакритическими знаками: обычно 2 байта.
  • Символы CJK: обычно 3 байта.
package main

import "fmt"

func main() {
    fmt.Println(len("a"))
    fmt.Println(len("é"))
    fmt.Println(len("世"))
}

Пакет unicode/utf8

Пакет unicode/utf8 распознаёт кодировку. utf8.RuneCountInString(s) правильно подсчитывает символы, в отличие от len.

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "héllo"
    fmt.Println(len(s))
    fmt.Println(utf8.RuneCountInString(s))
}

Проверка UTF-8

Используйте utf8.ValidString(s), чтобы перед обработкой убедиться, что строка содержит корректный UTF-8.

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    fmt.Println(utf8.ValidString("héllo"))
    fmt.Println(utf8.ValidString(string([]byte{0xff, 0xfe})))
}

Декодирование одной руны

utf8.DecodeRuneInString(s) возвращает первую руну и количество потреблённых ею байтов. Это позволяет вручную проходить по строке.

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    r, size := utf8.DecodeRuneInString("世界")
    fmt.Println(string(r), size)
}

Цикл range декодирует за Вас

Цикл for range уже выполняет декодирование UTF-8. На каждом шаге индекс увеличивается на размер руны в байтах.

package main

import "fmt"

func main() {
    for i, r := range "a世b" {
        fmt.Println(i, string(r))
    }
}

Пакет unicode

Пакет unicode классифицирует отдельные руны. Такие функции, как unicode.IsLetter и unicode.IsDigit, отвечают на вопросы о символе.

package main

import (
    "fmt"
    "unicode"
)

func main() {
    fmt.Println(unicode.IsLetter('A'))
    fmt.Println(unicode.IsDigit('7'))
    fmt.Println(unicode.IsSpace(' '))
}

Изменение регистра по руне

unicode.ToUpper и unicode.ToLower работают с отдельными рунами, включая многие буквы, не относящиеся к ASCII.

package main

import (
    "fmt"
    "unicode"
)

func main() {
    fmt.Println(string(unicode.ToUpper('a')))
    fmt.Println(string(unicode.ToLower('Z')))
}

Безопасный подсчёт букв

Объедините пакеты, чтобы подсчитывать только буквы в смешанном тексте, корректно обрабатывая каждую руну.

package main

import (
    "fmt"
    "unicode"
)

func main() {
    count := 0
    for _, r := range "a1 b2 世!" {
        if unicode.IsLetter(r) {
            count++
        }
    }
    fmt.Println(count)
}

Разворот текста по рунам

Чтобы безопасно развернуть текст, нужно разворачивать руны, а не байты, иначе многобайтовые символы распадутся.

package main

import "fmt"

func main() {
    runes := []rune("a世b")
    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
        runes[i], runes[j] = runes[j], runes[i]
    }
    fmt.Println(string(runes))
}

Собираем всё вместе

Инструмент для быстрого обзора: выведите длину в байтах, количество рун и информацию о том, является ли текст корректным UTF-8.

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "Go 世界!"
    fmt.Println("bytes:", len(s))
    fmt.Println("runes:", utf8.RuneCountInString(s))
    fmt.Println("valid:", utf8.ValidString(s))
}

Быстрая проверка

Выберите правильный способ подсчёта символов.

Итоги: Unicode и utf8

Теперь Вы уверенно работаете с многобайтовым текстом:

  • Строки Go используют UTF-8; символы занимают от 1 до 4 байтов.
  • unicode/utf8 подсчитывает, проверяет и декодирует руны.
  • unicode классифицирует отдельные руны и изменяет их регистр.
package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    s := "café 語"
    fmt.Println(utf8.RuneCountInString(s), "runes")
}

Часто задаваемые вопросы

Урок «Unicode и utf8» бесплатный?

Да — полный текст урока «Unicode и utf8» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Unicode и utf8»?

Обрабатывайте многобайтный текст Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Unicode и utf8»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Руны и байты
  2. Функции пакета strings
  3. strings.Builder
  4. Unicode и utf8
← Назад к Go Academy