Golang不同于Java等常见的语言,字节在语言层面支持了map。map类似于Java当中的Set,是数学中集合的概念。集合当中不会出现重复元素,并且是无序的。与此相关的就是数组和队列,它们是有序的。
前几天要做一个接口调用,需要用到安全机制,将请求参数编码出一个签名,一并用来发送请求。相关的可以参考《接口安全机制》。这里会涉及到两次取请求URL的步骤,一次是用来拼请求,一次是用来计算签名。当时机制的我,为了方便写代码,就将参数放在了map当中,遍历两次map就能够实现了。一般情况下都能够正常访问。极少数情况下是会提示调用失败的,其实就是签名或者参数错误。因为概率极低,所以没有引起注意。
但是一直觉得代码有点bug,大概位置自己也知道,肯定是发送HTTP请求的模块。后来,就去review了一下自己的代码,又测了一下,发现了问题。
import (
"fmt"
)
func main() {
query := map[string]string{}
// 需要按照字典排序
query["test0"] = "0"
query["test1"] = "1"
query["test2"] = "2"
for i := 0; i < 100; i++ {
for _, v := range query {
fmt.Print(v)
}
fmt.Println()
}
}
map遍历100次,把结果grep了一下,里面有82个012
,9个120
,9个201
。
- 首先,map并不是完全随机,我执行了几次结果都一样;而之前也试过一次,同样也都是使用Go playground,结果全是
210
(结果不是很确定),可能随机还和时间有关; - 其次,结果也不是很平均,按理说,这三个数,打散应该是6种结果,而这里只有3种。而且数量也相差很大。
所以,由于遍历map随机得不是很彻底,我始终没有发现这个bug的问题。安装上面测试的结果,012
出现概率82%,其它概率是18%,那么,接口调用出错的概率就是82%×82%=67.24%。
出问题的概率还是很高,看来测试也有问题。。。
本文所涉及到的完整源码请参考。
######参考文献 + 【1】Map iteration - Go 1.3 Release Notes
原文链接:Golang的map迭代,转载请注明来源!
有疑问加站长微信联系(非本文作者)