Как определить количество символов для строки?go-19

Основные способы подсчета символов

В Go существует несколько способов определения длины строки, каждый из которых имеет свои особенности:

1. Функция len - подсчет байт

s := "Привет"
byteCount := len(s)  // 12 для строки "Привет"
  • Возвращает количество байт, а не символов
  • Для ASCII строк результат корректный (1 байт = 1 символ)
  • Для UTF-8 (кириллица, эмодзи и др.) результат не соответствует количеству символов

2. utf8.RuneCountInString - подсчет рун

s := "Привет"
runeCount := utf8.RuneCountInString(s)  // 6
  • Корректно работает с Unicode (UTF-8)
  • Подсчитывает количество рун (кодовых точек Unicode)
  • Для большинства случаев это и есть количество "символов"

3. Преобразование в []rune

s := "Привет"
runeCount := len([]rune(s))  // 6
  • Аналогичен utf8.RuneCountInString()
  • Менее эффективен, так как создает новый массив рун

Особые случаи

1. Комбинированные символы

s := "é"  // 'e' + combining acute accent
fmt.Println(utf8.RuneCountInString(s))  // 2 (но визуально 1 символ)
  • Некоторые "символы" состоят из нескольких рун
  • Для точного подсчета видимых символов нужны дополнительные библиотеки (например, golang.org/x/text/unicode/norm)

2. Эмодзи и специальные символы

s := "😊♂"  // смайлик + гендерный символ
fmt.Println(utf8.RuneCountInString(s))  // 2

3. Пустая строка

s := ""
fmt.Println(len(s))                    // 0
fmt.Println(utf8.RuneCountInString(s)) // 0

Производительность

  1. len() - мгновенная операция (строка хранит длину в байтах)
  2. utf8.RuneCountInString() - требует итерации по строке
  3. len([]rune(s)) - требует аллокации памяти и итерации

Бенчмарк для строки из 1000 кириллических символов:

BenchmarkLen-8                 1000000000   0.0000011 ns/op
BenchmarkRuneCountInString-8     5000000     325 ns/op
BenchmarkLenRune-8               3000000     498 ns/op

Резюмируем

  1. Для ASCII строк можно использовать len()
  2. Для Unicode (UTF-8) используйте utf8.RuneCountInString()
  3. len([]rune(s)) дает тот же результат, но менее эффективен
  4. Помните о разнице между байтами, рунами и видимыми символами
  5. Для комбинированных символов нужна дополнительная обработка
  6. len() работает за O(1), другие методы - за O(n)

Выбор метода зависит от конкретной задачи:

  • Только ASCII? Используйте len()
  • Unicode текст? Используйте utf8.RuneCountInString()
  • Точный подсчет видимых символов? Используйте специализированные библиотеки