Вопрос проверяет понимание разницы между байтами и рунами в Go, а также того, как строки хранятся в памяти.
В Go строка представляет собой неизменяемый срез байт ([]byte), который интерпретируется как текст в кодировке UTF-8. Это означает, что каждый символ (руна) может занимать от 1 до 4 байт. Например, латинская буква 'A' занимает 1 байт, а китайский иероглиф '中' — 3 байта.
Операция взятия индекса s[i] определена для строк как получение i-го байта, а не i-го символа. Это сделано для эффективности: доступ к байту по индексу — это операция O(1), в то время как доступ к руне потребовал бы декодирования UTF-8 последовательности, что медленнее. Кроме того, строки часто используются для работы с бинарными данными или протоколами, где важна побайтовая обработка.
Чтобы получить руны из строки, используйте цикл for range, который автоматически декодирует UTF-8:
s := "Привет"
for i, r := range s {
fmt.Printf("Индекс %d: руна %c\n", i, r)
}
// Вывод:
// Индекс 0: руна П
// Индекс 2: руна р
// Индекс 4: руна и
// Индекс 6: руна в
// Индекс 8: руна е
// Индекс 10: руна тТакже можно преобразовать строку в срез рун: runes := []rune(s), но это создаёт копию и требует O(n) памяти.
Индексация строк по байтам — это осознанный выбор разработчиков Go для производительности и гибкости. Если вам нужно работать с символами, используйте for range или преобразование в []rune, но помните о накладных расходах.