這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
先看一段代碼:
func main() { m := make(map[int]string) m[1] = "a" m[2] = "b" m[3] = "c" for k, v := range m { fmt.Println(k, v) } fmt.Println("-----------------") mm := make(map[int]string) mm[1] = "a" mm[2] = "b" mm[3] = "c" for k, v := range mm { fmt.Println(k, v) } fmt.Println("-----------------") mmm := make(map[int]string) mmm[1] = "a" mmm[2] = "b" mmm[3] = "c" for k, v := range mmm { fmt.Println(k, v) }}
我起初以為三次的輸出中,元素的輸出順序都是相同的,可惜,得到的結果如下:
[cobbliu@xxx map]$ go run range.go1 a2 b3 c-----------------1 a2 b3 c-----------------3 c1 a2 b
對,Go中map的一個很重要的特性就是:當您多次通過range迴圈來迭代訪問map中元素時,儘管您訪問的是同一個map,但是訪問元素的順序在前後兩次range中是不會完全相同的。當然也不是完全隨機的。從Go1開始,Go在range遍曆Map中元素的時候,從隨機的一個位置開始迭代。
為什麼要這樣做?因為Go的設計者們認為會有一些程式員對同一個map中元素的遍曆順序假設定成相同,在這個假設的前提下,會做一些事情(今天的我就是這樣,在這個假設的前提下,碼了很多字母),他們認為不應該對一個map中的元素的遍曆順序有假設,所以從Go1.0開始,隨機化了range map的起始位置。
儘管掉坑裡了,但是卻使我對Go又多了一層好感,Go設計者在每個細節上都深思熟慮,他們盡量保持了語言的嚴謹性,創造了完整的協助工具輔助,對於一些模稜兩可的特性,強加了約束,只有這樣,才會防止在應用程式層代碼出現詭異的bug,讓Go語言使用者們能放心使用它。
儘管現在的Go少了泛型,但是這個特性真的有那麼必要嗎?Go說,至少目前,沒有那麼必要!