Гарантирован ли порядок итерации по элементам map в Go?

Ответ

Нет, порядок итерации по map в Go не гарантирован и не должен использоваться в логике программы.

Более того, начиная с Go 1.0, порядок итерации намеренно рандомизируется при каждом новом запуске программы. Это сделано для того, чтобы разработчики не полагались на случайный, но стабильный порядок, который может зависеть от реализации хеш-функции и внутренней структуры map. Такое поведение помогает выявлять ошибки на ранних стадиях.

В некоторых версиях Go (например, после 1.12) поведение могло казаться более стабильным для малых карт в целях упрощения отладки, но это деталь реализации, на которую категорически нельзя полагаться.

Как итерироваться в определенном порядке?

Если требуется стабильный порядок обхода, необходимо:

  1. Получить все ключи из map и поместить их в слайс.
  2. Отсортировать этот слайс.
  3. Итерироваться по отсортированному слайсу, получая значения из map по ключу.

Пример:

m := map[string]int{"c_key": 3, "a_key": 1, "b_key": 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("Ключ: %s, Значение: %dn", k, m[k])
}
// Вывод всегда будет отсортирован по ключу:
// Ключ: a_key, Значение: 1
// Ключ: b_key, Значение: 2
// Ключ: c_key, Значение: 3