Go語言map實(shí)現(xiàn)順序讀取
Go 語言中的 map 是一種非常強(qiáng)大的數(shù)據(jù)結(jié)構(gòu),它允許我們快速地存儲(chǔ)和檢索鍵值對(duì)。
然而,當(dāng)我們遍歷 map 時(shí),會(huì)有一個(gè)有趣的現(xiàn)象,那就是輸出的鍵值對(duì)順序是不確定的。
現(xiàn)象
先看一段代碼示例:
package main import "fmt" func main() { ? ? m := map[string]int{ ? ? ? ? "apple": ?1, ? ? ? ? "banana": 2, ? ? ? ? "orange": 3, ? ? } ? ? for k, v := range m { ? ? ? ? fmt.Printf("key=%s, value=%d\n", k, v) ? ? } }
當(dāng)我們多執(zhí)行幾次這段代碼時(shí),就會(huì)發(fā)現(xiàn),輸出的順序是不同的。
原因
首先,Go 語言 map 的底層實(shí)現(xiàn)是哈希表,在進(jìn)行插入時(shí),會(huì)對(duì) key 進(jìn)行 hash 運(yùn)算。這也就導(dǎo)致了數(shù)據(jù)不是按順序存儲(chǔ)的,和遍歷的順序也就會(huì)不一致。
第二,map 在擴(kuò)容后,會(huì)發(fā)生 key 的搬遷,原來落在同一個(gè) bucket 中的 key,搬遷后,有些 key 可能就到其他 bucket 了。
而遍歷的過程,就是按順序遍歷 bucket,同時(shí)按順序遍歷 bucket 中的 key。
搬遷后,key 的位置發(fā)生了重大的變化,有些 key 被搬走了,有些 key 則原地不動(dòng)。這樣,遍歷 map 的結(jié)果就不可能按原來的順序了。
最后,也是最有意思的一點(diǎn)。
那如果說我已經(jīng)初始化好了一個(gè) map,并且不對(duì)這個(gè) map 做任何操作,也就是不會(huì)發(fā)生擴(kuò)容,那遍歷順序是固定的嗎?
答:也不是。
Go 杜絕了這種做法,主要是擔(dān)心程序員會(huì)在開發(fā)過程中依賴穩(wěn)定的遍歷順序,因?yàn)檫@是不對(duì)的。
所以在遍歷 map 時(shí),并不是固定地從 0 號(hào) bucket 開始遍歷,每次都是從一個(gè)隨機(jī)值序號(hào)的 bucket 開始遍歷,并且是從這個(gè) bucket 的一個(gè)隨機(jī)序號(hào)的 cell 開始遍歷。
如何順序讀取
如果希望按照特定順序遍歷 map,可以先將鍵或值存儲(chǔ)到切片中,然后對(duì)切片進(jìn)行排序,最后再遍歷切片。
改造一下上面的代碼,讓它按順序輸出:
package main import ( ? ? "fmt" ? ? "sort" ) func main() { ? ? m := map[string]int{ ? ? ? ? "apple": ?1, ? ? ? ? "banana": 2, ? ? ? ? "orange": 3, ? ? } ? ? // 將 map 中的鍵存儲(chǔ)到切片中 ? ? keys := make([]string, 0, len(m)) ? ? for k := range m { ? ? ? ? keys = append(keys, k) ? ? } ? ? // 對(duì)切片進(jìn)行排序 ? ? sort.Strings(keys) ? ? // 按照排序后的順序遍歷 map ? ? for _, k := range keys { ? ? ? ? fmt.Printf("key=%s, value=%d\n", k, m[k]) ? ? } }
在上面的代碼中,首先將 map 中的鍵存儲(chǔ)到一個(gè)切片中,然后對(duì)切片進(jìn)行排序。
最后,按照排序后的順序遍歷 map。這樣就可以按照特定順序輸出鍵值對(duì)了。
參考文章:
https://golang.design/go-questions/map/unordered/
到此這篇關(guān)于Go語言map實(shí)現(xiàn)順序讀取的文章就介紹到這了,更多相關(guān)Go map順序讀取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang測(cè)試func?TestXX(t?*testing.T)的使用詳解
一般Golang中的測(cè)試代碼都以xxx_test.go的樣式,在命名測(cè)試函數(shù)的時(shí)候以Testxx開頭,下面給大家介紹Golang測(cè)試func?TestXX(t?*testing.T)的使用,感興趣的朋友跟隨小編一起看看吧2024-08-08go語言使用range來接收通道里面的數(shù)據(jù)
本文主要介紹了go語言使用range來接收通道里面的數(shù)據(jù),for ... range?循環(huán)會(huì)一直從通道中接收值,直到通道關(guān)閉并且所有值都被接收完畢,下面就來介紹一下,感興趣的可以了解一下2025-04-04Go語言遍歷map實(shí)現(xiàn)(訪問map中的每一個(gè)鍵值對(duì))
這篇文章主要介紹了Go語言遍歷map實(shí)現(xiàn)(訪問map中的每一個(gè)鍵值對(duì)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Go語言for-range函數(shù)使用技巧實(shí)例探究
這篇文章主要為大家介紹了Go語言for-range函數(shù)使用技巧實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01詳解Golang實(shí)現(xiàn)請(qǐng)求限流的幾種辦法
這篇文章主要介紹了詳解Golang實(shí)現(xiàn)請(qǐng)求限流的幾種辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Go語言基礎(chǔ)學(xué)習(xí)之?dāng)?shù)組的使用詳解
數(shù)組相必大家都很熟悉,各大語言也都有數(shù)組的身影。Go 語言也提供了數(shù)組類型的數(shù)據(jù)結(jié)構(gòu)。本文就來通過一些簡(jiǎn)單的示例帶大家了解一下Go語言中數(shù)組的使用,希望對(duì)大家有所幫助2022-12-12golang使用iconv報(bào)undefined:XXX的問題處理方案
這篇文章主要介紹了golang使用iconv報(bào)undefined:XXX的問題處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03GO中的時(shí)間操作總結(jié)(time&dateparse)
日常開發(fā)過程中,對(duì)于時(shí)間的操作可謂是無處不在,但是想實(shí)現(xiàn)時(shí)間自由還是不簡(jiǎn)單的,多種時(shí)間格式容易混淆,本文為大家整理了一下GO中的時(shí)間操作,有需要的可以參考下2023-09-09golang 實(shí)現(xiàn)比特幣內(nèi)核之處理橢圓曲線中的天文數(shù)字
比特幣密碼學(xué)中涉及到的大數(shù)運(yùn)算超出常規(guī)整數(shù)范圍,需使用golang的big包進(jìn)行處理,通過使用big.Int類型,能有效避免整數(shù)溢出,并保持邏輯正確性,測(cè)試展示了在不同質(zhì)數(shù)模下的運(yùn)算結(jié)果,驗(yàn)證了邏輯的準(zhǔn)確性,此外,探討了費(fèi)馬小定理在有限字段除法運(yùn)算中的應(yīng)用2024-11-11