25 August 2014
上个礼拜比较忙,没有来得及更新。其中忙的一件事,就是改关于map迭代的bug。问题很简单,主要讲一下我的低级失误和Golang的map迭代策略。

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%。 出问题的概率还是很高,看来测试也有问题。。。

本文所涉及到的完整源码请参考


参考文献

原文链接:Golang的map迭代,转载请注明来源!

EOF