← Назад к вопросам

Как узнать количество букв в строке на кириллице?

1.0 Junior🔥 101 комментариев
#Основы Go

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Определение длины строки в Go

Важное предупреждение: В Go стандартная функция len() возвращает количество байт, а не символов (рун), что критично для Unicode-строк, включая кириллицу.

Почему len() не подходит для кириллицы

package main

import "fmt"

func main() {
    str := "Привет мир"
    fmt.Println("Длина через len():", len(str)) // 19 байтов, а не 11 символов!
    fmt.Println("Реальные символы:", []rune(str)) // [1055 1088 1080 1074 1077 1090 32 1084 1080 1088]
}

В Go строки хранятся как последовательность байтов в кодировке UTF-8, где кириллические символы занимают по 2 байта каждый. Функция len() подсчитывает именно байты.

Правильные способы подсчета символов

1. Использование utf8.RuneCountInString() (рекомендуемый способ)

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    str := "Привет мир 🇷🇺"
    
    // Правильный подсчет символов
    charCount := utf8.RuneCountInString(str)
    fmt.Printf("Символов: %d\n", charCount) // 13 символов
    fmt.Printf("Байтов: %d\n", len(str))    // 21 байт
    
    // Демонстрация разницы
    complexStr := "Go🚀и🇷🇺"
    fmt.Printf("\nСтрока: %s\n", complexStr)
    fmt.Printf("RuneCount: %d\n", utf8.RuneCountInString(complexStr)) // 6 символов
    fmt.Printf("len(): %d\n", len(complexStr))                         // 13 байтов
}

2. Конвертация в срез рун []rune

func countRunes(str string) int {
    runes := []rune(str)
    return len(runes) // Здесь len() уже работает с рунами, а не с байтами
}

func main() {
    str := "Программирование на Go"
    fmt.Println("Количество символов:", countRunes(str)) // 22 символа
    
    // Или в одну строку
    fmt.Println("Количество символов:", len([]rune(str)))
}

Сравнение методов

МетодПреимуществаНедостатки
utf8.RuneCountInString()Самый эффективный, не создает новых аллокацийТребует импорта пакета
len([]rune(str))Более интуитивно понятенСоздает новый срез рун (аллокация памяти)
len(str)Мгновенное выполнениеСчитает байты, а не символы

Расширенный пример с обработкой графем

Важное уточнение: Некоторые "символы" на самом деле являются последовательностями Unicode (эмодзи, флаги, комбинируемые символы):

package main

import (
    "fmt"
    "unicode/utf8"
    "github.com/rivo/uniseg" // Для подсчета графемных кластеров
)

func main() {
    // Сложный случай: флаг России - это 2 руны (🇷 и 🇺)
    str := "Россия🇷🇺"
    
    fmt.Println("Байты:", len(str))                    // 16 байтов
    fmt.Println("Руны:", utf8.RuneCountInString(str)) // 8 рун
    fmt.Println("Графемные кластеры:", uniseg.GraphemeClusterCount(str)) // 7 "видимых" символов
}

Практические рекомендации

  1. Всегда используйте utf8.RuneCountInString() для подсчета символов в пользовательском интерфейсе, валидации длины полей ввода, ограничении текста.

  2. Для итерации по строке используйте for range, который автоматически работает с рунами:

func processString(str string) {
    // Правильная итерация
    for i, r := range str {
        fmt.Printf("Позиция %d: символ %c (код %U)\n", i, r, r)
    }
    
    // НЕПРАВИЛЬНО (байтовые позиции)
    for i := 0; i < len(str); i++ {
        // Работает с байтами, а не символами!
    }
}
  1. Для ограничения длины строки с учетом Unicode:
func truncateString(str string, maxLen int) string {
    if utf8.RuneCountInString(str) <= maxLen {
        return str
    }
    
    runes := []rune(str)
    return string(runes[:maxLen]) + "..."
}

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

Для больших строк utf8.RuneCountInString() работает в O(n), но обычно это не является проблемой. Если требуется максимальная производительность и точный подсчет графем, рассмотрите специализированные библиотеки типа uniseg.

Вывод: Для подсчета количества букв (символов) в строке с кириллицей всегда используйте utf8.RuneCountInString() или преобразование в []rune, но никогда не полагайтесь на стандартную функцию len().

Как узнать количество букв в строке на кириллице? | PrepBro