🟡 Средний · 2 очк. Основы синтаксиса
Что выведет fmt.Println(len("Привет"))?
A 6
B 12
C 7
D Ошибку компиляции
Объяснение вопроса

В Go строка (string) - это неизменяемая последовательность байт, а не символов. Функция len() возвращает именно количество байт.

Кириллические символы в UTF-8 занимают по 2 байта каждый. Слово "Привет" состоит из 6 букв, но из 12 байт:

s := "Привет"
fmt.Println(len(s))    // 12 (байт, не символов)

// Побайтовый вывод:
for i := 0; i < len(s); i++ {
    fmt.Printf("%d: 0x%X\n", i, s[i])
}
// 0: 0xD0  1: 0x9F  (П)
// 2: 0xD1  3: 0x80  (р)
// ...

Как получить количество символов

Есть два способа подсчитать именно символы (руны):

fmt.Println(utf8.RuneCountInString(s)) // 6
fmt.Println(len([]rune(s)))            // 6

Первый способ эффективнее - он не создает новый слайс, а просто считает руны.

Цикл for range декодирует руны автоматически

for i, r := range "Привет" {
    fmt.Printf("байт %d: %c (U+%04X)\n", i, r, r)
}
// байт 0: П (U+041F)
// байт 2: р (U+0440)
// байт 4: и (U+0438)
// байт 6: в (U+0432)
// байт 8: е (U+0435)
// байт 10: т (U+0442)

Обратите внимание: индекс i увеличивается на 2 (не на 1), потому что каждая руна занимает 2 байта.

Сравнение len() для разных типов

  • len(string) - количество байт
  • len([]rune(string)) - количество символов (рун)
  • len([]byte{...}) - количество байт
  • len(slice) - количество элементов

Латинские буквы и цифры в UTF-8 занимают 1 байт, поэтому для ASCII-строк len() совпадает с количеством символов. Ловушка проявляется именно на многобайтовых символах: кириллица (2 байта), китайские иероглифы (3 байта), эмодзи (4 байта).

🧠Квиз 🏆Лидеры 🎯Собесед. 📖Вопросы 📚База зн.