Строки и руны
Задача, которую необходимо решить в этом практическом занятии, - это понять, как работать со строками и рунами в Go. В частности, практическое занятие затронет такие вопросы, как получение длины строки, обращение к элементам строки по индексу, подсчет количества рун в строке и итерация по рунам в строке.
Для выполнения этого практического занятия вам понадобится:
- Базовое понимание синтаксиса Go
- Знание о строках и рунах в Go
- Стандартную библиотеку Go
$ go run strings-and-runes.go
Длина: 18
e0 b8 aa e0 b8 a7 e0 b8 b1 e0 b8 aa e0 b8 94 e0 b8 b5
Количество рун: 6
U+0E2A 'ส' начинается с 0
U+0E27 'ว' начинается с 3
U+0E31 'ั' начинается с 6
U+0E2A 'ส' начинается с 9
U+0E14 'ด' начинается с 12
U+0E35 'ี' начинается с 15
Использование DecodeRuneInString
U+0E2A 'ส' начинается с 0
найдено so sua
U+0E27 'ว' начинается с 3
U+0E31 'ั' начинается с 6
U+0E2A 'ส' начинается с 9
найдено so sua
U+0E14 'ด' начинается с 12
U+0E35 'ี' начинается с 15
Ниже представлен полный код:
// Строка в Go - это неизменяемый срез байтов. Язык
// и стандартная библиотека особым образом обрабатывают строки - как
// контейнеры для текста, закодированного в [UTF-8](https://en.wikipedia.org/wiki/UTF-8).
// В других языках строки состоят из "символов".
// В Go концепция символа называется `rune` - это
// целое число, представляющее кодовую точку Unicode.
// [Эта статья на блоге Go](https://go.dev/blog/strings) - хорошее
// введение в тему.
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
// `s` - это `string`, присвоенная литеральному значению,
// представляющему слово "hello" на тайском языке. Литералы строк в Go - это UTF-8
// закодированный текст.
const s = "สวัสดี"
// Поскольку строки эквивалентны `[]byte`, это
// выведет длину исходных байтов, хранящихся внутри.
fmt.Println("Длина:", len(s))
// Обращение к элементу строки по индексу возвращает исходные байтовые значения в
// каждом индексе. Этот цикл генерирует шестнадцатеричные значения всех
// байтов, составляющих кодовые точки в `s`.
for i := 0; i < len(s); i++ {
fmt.Printf("%x ", s[i])
}
fmt.Println()
// Чтобы подсчитать количество _рун_ в строке, мы можем использовать
// пакет `utf8`. Обратите внимание, что время выполнения
// `RuneCountInString` зависит от размера строки,
// потому что он должен последовательно декодировать каждую UTF-8 руну.
// Некоторые тайские символы представляются несколькими UTF-8
// кодовыми точками, поэтому результат этого подсчета может быть неожиданным.
fmt.Println("Количество рун:", utf8.RuneCountInString(s))
// Цикл `range` особым образом обрабатывает строки и декодирует
// каждую `руну` вместе с ее смещением в строке.
for idx, runeValue := range s {
fmt.Printf("%#U начинается с %d\n", runeValue, idx)
}
// Мы можем достичь той же итерации, используя явно
// функцию `utf8.DecodeRuneInString`.
fmt.Println("\nИспользование DecodeRuneInString")
for i, w := 0, 0; i < len(s); i += w {
runeValue, width := utf8.DecodeRuneInString(s[i:])
fmt.Printf("%#U начинается с %d\n", runeValue, i)
w = width
// Это демонстрирует передачу значения `руны` в функцию.
examineRune(runeValue)
}
}
func examineRune(r rune) {
// Значения, заключенные в одинарные кавычки, - это _литералы рун_. Мы
// можем напрямую сравнивать значение `руны` с литералом руны.
if r == 't' {
fmt.Println("найдено tee")
} else if r == 'ส' {
fmt.Println("найдено so sua")
}
}