WHAT?
發現下面這段代碼,多次運行出的結果是不一樣的
mapper := make(map[int]string) mapper[1] = "1" mapper[2] = "2" mapper[3] = "3" mapper[4] = "4" mapper[5] = "5" mapper[6] = "6" mapper[7] = "7" for k, v := range mapper { fmt.Println(k, v) }
HOW?
從下面圖片中看到,range獲取迭代器是通過調用了mapiterinit()方法。(圖片來源:https://my.oschina.net/renhc/blog/2396058)
然后看到mapiterinit方法里,有取隨機數的部分。java語言每次都會按順序去遍歷桶,而go語言會提前取一個隨機數,把桶的遍歷順序隨機化。
(圖片來源:https://blog.csdn.net/u010853261/article/details/99699350)
(也可以直接看map源碼。mapiterinit在https://github.com/golang/go/blob/36f30ba289e31df033d100b2adb4eaf557f05a34/src/runtime/map.go 第797行。下圖的這段代碼在827行)
WHY?
遍歷map的時候,每次取隨機數,看起來是沒有意義的,為什么要這樣設計呢?(尋找答案的時候,看到有些博客說go的早期版本的map遍歷沒有取隨機數這個步驟)
(圖片來源:https://blog.csdn.net/slvher/article/details/44779081)
讀完上面的內容,我的理解就是:如果沒有設置這個隨機數,那么在大多數情況下,golang會表現出map的順序是固定的情況。但是golang底層並沒有保證這一點,或許(現在/以后)會有特殊情況出現順序不固定的情況。擔心開發者們誤解這一點,golang就特意去打亂了這個順序,讓開發者們知道golang底層不保證map每次遍歷都是同一個順序。