Ответ
Индексирование в Go — это способ доступа к элементам коллекции (массива, среза, строки или карты) по индексу или ключу. Синтаксис — collection[index].
1. Индексация массивов и срезов (Arrays/Slices)
Доступ к элементу осуществляется по его целочисленному индексу, нумерация начинается с 0. Выход за пределы среза или массива вызывает панику.
numbers := []int{10, 20, 30}
fmt.Println(numbers[1]) // Выведет: 20
// numbers[3] // вызовет панику: runtime error: index out of range
2. Индексация карт (Maps)
Доступ к значению осуществляется по ключу. Если ключ не найден, возвращается нулевое значение для типа данных значения. Чтобы отличить отсутствующий ключ от ключа с нулевым значением, используется вторая переменная ok.
ages := map[string]int{"Alice": 25, "Bob": 0}
// Получение значения
fmt.Println(ages["Alice"]) // Выведет: 25
// Проверка наличия ключа
age, ok := ages["Bob"]
fmt.Printf("Bob's age: %d, exists: %tn", age, ok) // Выведет: Bob's age: 0, exists: true
age, ok = ages["Charlie"]
fmt.Printf("Charlie's age: %d, exists: %tn", age, ok) // Выведет: Charlie's age: 0, exists: false
3. Индексация строк (Strings)
Это важный и коварный момент в Go. Строка в Go — это неизменяемая последовательность байт. При индексации строки вы получаете байт по указанному индексу, а не символ (руну).
str := "Привет"
// Неправильный способ доступа к символам в многобайтовой кодировке
fmt.Println(str[0]) // Выведет: 208 (первый байт буквы 'П')
fmt.Println(str[1]) // Выведет: 159 (второй байт буквы 'П')
// Правильный способ — преобразовать строку в срез рун
runes := []rune(str)
fmt.Printf("%cn", runes[0]) // Выведет: П
fmt.Printf("%cn", runes[1]) // Выведет: р
Для безопасной и корректной итерации по символам строки всегда следует использовать цикл for ... range или предварительное преобразование в []rune.
Ответ 18+ 🔞
А, индексирование в Go, говоришь? Ну это ж классика, блядь! Сидишь такой, думаешь — ну что тут может быть сложного, collection[index] и всё дела. Ан нет, ёпта, тут такие подводные камни, что мама не горюй!
Вот смотри, с массивами и срезами вроде всё просто — как в нормальных языках. Нумерация с нуля, хуле тут.
numbers := []int{10, 20, 30}
fmt.Println(numbers[1]) // Выведет: 20
Но попробуй вылезти за пределы — получишь пизды от рантайма: index out of range, и привет, программа накрылась медным тазом. Так что смотри в оба, блядь!
А вот с картами уже интереснее, ёбана! Ты думаешь — взял ключ, получил значение? Ага, щас! Если ключа нет — тебе вернётся нулевое значение типа. И как отличить, что ключа нет, от ситуации, где там реально ноль лежит? А вот так:
ages := map[string]int{"Alice": 25, "Bob": 0}
age, ok := ages["Bob"]
fmt.Printf("Bob's age: %d, exists: %tn", age, ok) // Выведет: Bob's age: 0, exists: true
age, ok = ages["Charlie"]
fmt.Printf("Charlie's age: %d, exists: %tn", age, ok) // Выведет: Charlie's age: 0, exists: false
Видишь? Вторая переменная ok тебе говорит — есть ключ или нет. Без этого — нихуя не понятно, честно говоря!
Но самое, блядь, интересное — это строки! Вот тут-то и начинается цирк, ёпта! Строка в Go — это последовательность байтов, а не символов. И когда ты пишешь str[0] для строки "Привет" — ты получаешь не букву "П", а первый байт этой буквы в UTF-8!
str := "Привет"
fmt.Println(str[0]) // Выведет: 208 (первый байт буквы 'П')
fmt.Println(str[1]) // Выведет: 159 (второй байт буквы 'П')
Вот это пиздец, да? Ты думал символ получишь, а тебе какая-то хуйня в виде числа прилетает! И так для каждой русской буквы, блядь, потому что они многобайтовые!
Правильный способ — либо в срез рун преобразовать:
runes := []rune(str)
fmt.Printf("%cn", runes[0]) // Выведет: П
Либо через for ... range итерироваться, он за тебя всё разберёт. А если будешь по-простому индексировать — получишь ебанину полную, в рот меня чих-пых!
Вот так вот, казалось бы — элементарная операция, а столько нюансов! Go не прощает распиздяйства, блядь. Либо делай правильно, либо получай панику в ебало!