Không. Spec quy định thứ tự lặp trên map là không xác định, và runtime còn cố tình ngẫu nhiên hoá điểm bắt đầu mỗi lần chạy để lập trình viên không lỡ phụ thuộc vào nó.
go
m := map[string]int{"a": 1, "b": 2, "c": 3}
for k, v := range m {
fmt.Println(k, v) // thứ tự khác nhau giữa các lần chạy
}Muốn ổn định thì sắp xếp khoá rồi duyệt:
go
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Println(k, m[k])
}Lưu ý:
- Test so sánh chuỗi output sinh từ map sẽ lúc pass lúc fail.
- Sinh câu SQL hay chữ ký request (HMAC) từ map mà không sắp khoá sẽ cho kết quả khác nhau mỗi lần.
- encoding/json là ngoại lệ: Marshal tự sắp xếp khoá map, nên JSON output vẫn ổn định.
Sửa map trong lúc range: khoá mới thêm có thể xuất hiện hoặc không; khoá vừa delete chắc chắn không được duyệt tới nữa. Xoá trong lúc duyệt là hợp lệ, còn thêm thì nên tránh.