Ответ
Итерирование по map
в Go осуществляется с помощью конструкции for ... range
. Ключевая особенность заключается в том, что порядок итерации не гарантирован и является случайным.
Почему порядок случайный?
Это осознанное решение разработчиков языка. Внутренне map
реализована как хеш-таблица. Порядок элементов в ней зависит от их хешей и внутренней структуры бакетов. При изменении размера map
(добавлении элементов) может произойти перехеширование, и внутренний порядок элементов изменится. Чтобы разработчики не писали хрупкий код, который по ошибке зависит от порядка итерации, в Go намеренно рандомизируют стартовую точку обхода map
при каждом новом цикле for ... range
.
Пример итерации:
package main
import "fmt"
func main() {
m := map[string]int{
"alpha": 1,
"beta": 2,
"gamma": 3,
}
// При каждом запуске программы порядок вывода может быть разным
for key, value := range m {
fmt.Printf("Key: %s, Value: %dn", key, value)
}
}
Как получить отсортированный результат?
Если требуется детерминированный (стабильный) порядок обхода, необходимо сначала получить все ключи, отсортировать их, а затем итерироваться по отсортированному срезу ключей, получая значения из map
.
package main
import (
"fmt"
"sort"
)
func main() {
m := map[string]int{
"gamma": 3,
"alpha": 1,
"beta": 2,
}
// 1. Создаем срез для ключей
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
// 2. Сортируем ключи
sort.Strings(keys)
// 3. Итерируемся по отсортированным ключам
for _, k := range keys {
fmt.Printf("Key: %s, Value: %dn", k, m[k])
}
}