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

Что означает число, возвращаемое функцией len для строки?

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

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

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

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

Длина строки в Go: что возвращает len()?

Функция len() в Go для строки возвращает длина строки в байтах, а не количество символов (символьную длину). Это фундаментальное свойство языка, связанное с представлением строк в памяти. Строка в Go — это не последовательность символов (characters), а последовательность байтов (bytes), которые представляют кодированные символы UTF-8.

Принцип работы и пример

package main

import "fmt"

func main() {
    str := "Привет"
    fmt.Println("len(str):", len(str))  // Вывод: 12
    fmt.Println("Количество символов (примерно):", len([]rune(str))) // Вывод: 6
}

В примере выше:

  • Слово "Привет" состоит из 6 символов.
  • Однако len("Привет") возвращает 12 байтов.
  • Почему? Каждый русский символ в UTF-8 кодируется 2 байтами (в данном случае). Поэтому 6 символов * 2 байта = 12 байтов.

Ключевые детали и важные термины

  1. Строка как []byte: Внутренне строка в Go — это read-only slice of bytes. Функция len() для строки работает аналогично len() для среза байтов, возвращая количество элементов (байтов).

  2. UTF-8 и многобайтовые символы: Go использует UTF-8 как внутреннюю кодировку строк. В UTF-8:

    • ASCII-символы (английские буквы, цифры) занимают 1 байт.
    • Символы из других языков (русские, китайские, и т.д.) могут занимать 2, 3 или 4 байта.
  3. Символьная длина vs байтовая длина: Если вам нужна количество символов (символьная длина), необходимо использовать преобразование в срез рун ([]rune) или функцию из пакета unicode/utf8.

import "unicode/utf8"

str := "Hello, мир!"
byteLength := len(str)                     // 12 байтов
charLength := utf8.RuneCountInString(str)  // 9 символов
// или
charLength := len([]rune(str))             // 9 символов

Практическое значение и распространённые ошибки

Это поведение len() для строк имеет важные практические следствия:

  • Обработка текста: При индексировании строки (str[i]) вы получаете байт, а не символ. Это может привести к ошибкам или некорректной обработке многобайтовых символов.
  • Сравнение и манипуляции: Операции, предполагающие символьную длину (например, ограничение строки по длине), будут некорректны если использовать просто len().
str := "Привет"
// Некорректный подход — обрезаем по байтам, может повредить символы
truncated := str[:5]  // Берем первые 5 байтов из 12
fmt.Println(truncated) // Может вывести "Прив" с повреждённым последним символом

// Корректный подход — обрезаем по символам через руны
runes := []rune(str)
truncatedCorrect := string(runes[:5])  // Берем первые 5 символов
fmt.Println(truncatedCorrect)          // Вывод: "Приве"

Почему так реализовано в Go?

Причина этого дизайна — эффективность и семантическая ясность. Функция len() в Go всегда возвращает количество элементов в коллекции. Для массива — количество элементов массива, для среза — количество элементов среза, для строки — количество байтов (элементов последовательности байтов). Это единообразное поведение упрощает понимание. Кроме того, байтовая длина непосредственно соответствует количеству памяти, занимаемому строкой.

Итог

Таким образом, len() для строки в Go — это инструмент низкого уровня, возвращающий байтовую длину UTF-8 последовательности. Для работы с символами всегда необходимо использовать функции из пакета unicode/utf8 или преобразование в []rune. Это одна из особенностей языка, которую важно понимать, чтобы корректно работать с текстом, особенно в международных проектах.