Вопрос проверяет понимание разницы между доступом к строке по индексу и итерацией через range в контексте многобайтовых символов Unicode.
В Go строки хранятся как последовательности байтов в кодировке UTF-8. Это означает, что один символ Unicode (руна) может занимать от 1 до 4 байтов. При итерации по строке с помощью индекса вы получаете доступ к каждому байту по отдельности, что может привести к некорректной обработке многобайтовых символов. Например, символ 'Я' занимает 2 байта, и обращение по индексу вернет только первый байт, а не целый символ.
Итерация через range в Go специально спроектирована для работы с UTF-8. Она автоматически декодирует последовательность байтов в руны (тип rune, представляющий Unicode-символ). Это гарантирует, что вы получите каждый символ целиком, независимо от его длины в байтах.
package main
import "fmt"
func main() {
s := "Привет, мир!"
// Итерация по индексу (по байтам)
fmt.Println("Итерация по индексу:")
for i := 0; i < len(s); i++ {
fmt.Printf("Байт %d: %x\n", i, s[i])
}
// Итерация через range (по рунам)
fmt.Println("\nИтерация через range:")
for i, r := range s {
fmt.Printf("Позиция %d: руна %c (код %U)\n", i, r, r)
}
}В первом цикле выводятся отдельные байты, которые для многобайтовых символов будут разбиты на части. Во втором цикле каждая итерация возвращает полную руну, что позволяет корректно обрабатывать текст.
Итерация через range предпочтительна для работы с текстом, содержащим Unicode-символы, так как она обеспечивает корректное декодирование и избегает ошибок, связанных с многобайтовыми последовательностями. Используйте итерацию по индексу только если вам нужен доступ к сырым байтам строки, например, для низкоуровневой обработки данных.