解決Golang map range遍歷結(jié)果不穩(wěn)定問題
閑言少敘,本文主要是想介紹一個Golang開發(fā)常見的一個問題。然而,此問題對于初學(xué)者來說卻經(jīng)常容易陷入坑中。
問題
我在寫一段代碼時,使用了Golang的map數(shù)據(jù)結(jié)構(gòu),目的是想用map緩存計數(shù)結(jié)果。簡單來說map的鍵也是整型的,且以遞增順序存儲。我的最初想法是,在統(tǒng)計結(jié)束后,按照map中存儲的鍵有序輸出值??墒?,當(dāng)我運行程序時,結(jié)果并不是我想要的,而且有一定概率運行結(jié)果不同。
問題代碼
func sortByBits(arr []int) []int { var bitmap = make(map[int][]int, 0) // map緩存 for i := 0; i < len(arr); i++ { bits := calBits(arr[i]) if _, ok := bitmap[bits]; !ok { tmp := make([]int, 0) tmp = append(tmp, arr[i]) bitmap[bits] = tmp } else { bitmap[bits] = append(bitmap[bits], arr[i]) for j := len(bitmap[bits]) - 1;j > 0; j-- { if bitmap[bits][j] < bitmap[bits][j - 1] { bitmap[bits][j], bitmap[bits][j - 1] = bitmap[bits][j - 1], bitmap[bits][j] } } } } // 輸出 var res []int for _, value := range bitmap { res = append(res, value...) } return res } func calBits(n int) int { sum := 0 for n > 0 { if n & 1 == 1 { sum++ } n = n >> 1 } return sum }
當(dāng)發(fā)現(xiàn)這個問題后,我使用二維數(shù)組替換map,改造代碼如下:
改造代碼
func sortByBits(arr []int) []int { var bitmap = make([][]int, 0, 10000) // map緩存 for i := 0; i < len(arr); i++ { bits := calBits(arr[i]) if len(bitmap) <= bits { length := bits - len(bitmap) + 1 for j := 0; j < length; j++ { tmp := make([]int, 0) bitmap = append(bitmap, tmp) } } if len(bitmap[bits]) == 0 { bitmap[bits] = append(bitmap[bits], arr[i]) } else { bitmap[bits] = append(bitmap[bits], arr[i]) for j := len(bitmap[bits]) - 1;j > 0; j-- { if bitmap[bits][j] < bitmap[bits][j - 1] { bitmap[bits][j], bitmap[bits][j - 1] = bitmap[bits][j - 1], bitmap[bits][j] } } } } // 輸出 var res []int for _, value := range bitmap { res = append(res, value...) } return res } func calBits(n int) int { sum := 0 for n > 0 { if n & 1 == 1 { sum++ } n = n >> 1 } return sum }
代碼很簡單,問題也很簡單。原理就是Golang的map按鍵輸出結(jié)果是隨機的,這是語言本身的一個特性,或者說是"坑"。作為開發(fā)者,要熟練掌握語言最基本特性,才能開發(fā)出最穩(wěn)健的程序。
補充:golang if _,ok:=range map; ok判斷key是否在map中
由于golang沒有提供item是否在array當(dāng)中的判斷方法,如果程序里面頻繁用到了這種判斷,可以將array轉(zhuǎn)化為以array當(dāng)中的成員為key的map再用上面的方法進(jìn)行判斷,這樣會提高判斷的效率。
判斷方法示例代碼
if _, ok := map[key]; ok { //存在 }
如果每次都for循環(huán),會影響性能!
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Go語言并發(fā)之context標(biāo)準(zhǔn)庫的使用詳解
Context的出現(xiàn)是為了解決在大型應(yīng)用程序中的并發(fā)環(huán)境下,協(xié)調(diào)和管理多個goroutine之間的通信、超時和取消操作的問題,本文就來和大家簡單聊聊它的具體用法,希望對大家有所幫助2023-06-06Golang中文字符串截取函數(shù)實現(xiàn)原理
在golang中可以通過切片截取一個數(shù)組或字符串,但是當(dāng)截取的字符串是中文時,可能會出現(xiàn)問題,下面我們來自定義個函數(shù)解決Golang中文字符串截取問題2018-03-03golang?metrics各個指標(biāo)含義講解說明
這篇文章主要為大家介紹了golang?metrics各個指標(biāo)含義講解說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05