一、问题

不知道小伙伴有没有发现,Go 语言的 map 是无序遍历的,一开始我不知道,啪,测试给我指回来一个 bug,就是多次请求,发现多次请求返回的数据顺序不一致。经过排查,我才知道 Go 语言的 map 原来是无序的。

二、解决思路

1、方法一

借助一个 slice 来保存 map 的 key ,通过遍历排序后的 slice 来达到根据 keys 遍历 map 的效果

原来的代码:

1
2
3
4
5
6
7
var (
arr []string
)
for key, value := range map {
arr = append(arr, ip)
}
fmt.Println(arr)

添加有序遍历后的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
// map根据key排序
sortedKeys := make([]string, 0)
for k, _ := range map {
sortedKeys = append(sortedKeys, k)
}
// slice排序
sort.Strings(sortedKeys)
// 遍历slice,实现有序遍历map
for _, key := range sortedKeys {
// key是map的key,value可通过map[value]获取
arr = append(arr, ip)
}
fmt.Println(arr)

这样就实现了map的有序遍历。

2、方法二

开源实现:已经有人实现了有序 map ,下载地址:这是一个链接 elliotchance/orderedmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"github.com/elliotchance/orderedmap"
)

func main() {
//新建一个order map
m := orderedmap.NewOrderedMap()
m.Set("a", 1)
m.Set("b", 2)
m.Set("d", 3)
m.Set("c", 4)
//遍历一下
for _, key := range m.Keys() {
value, _ := m.Get(key)
fmt.Printf("%v=%v\n", key, value)
}
}

三、总结

我觉得第一种方式就挺好,目前项目中也是这样用的。第二种虽然方便,但用法不是很熟悉,就后续再说吧,当做一个备选方案。