golang 如何獲取map所有key的方式
最佳方式:根據map的長度,新建一個數組,遍歷map逐個壓入
方法1(效率很高):
func getKeys1(m map[int]int) []int { // 數組默認長度為map長度,后面append時,不需要重新申請內存和拷貝,效率很高 j := 0 keys := make([]int, len(m)) for k := range m { keys[j] = k j++ } return keys }
方法2(效率很高):
func getKeys2(m map[int]int) []int { // 數組默認長度為map長度,后面append時,不需要重新申請內存和拷貝,效率很高 keys := make([]int, 0, len(m)) for k := range m { keys = append(keys, k) } return keys }
其他方式:
方法3(效率較低):
func getKeys3(m map[int]int) []int { // 注意:由于數組默認長度為0,后面append時,需要重新申請內存和拷貝,所以效率較低 keys := []int{} for k := range m { keys = append(keys, k) } return keys }
方法4(效率極低):
func getKeys4(m map[int]int) int { // 注意:雖然此寫法簡潔,但MapKeys函數內部操作復雜,效率極低 keys := reflect.ValueOf(m).MapKeys() return len(keys) }
實驗結果如圖(可以看到方法1和方法2效率最高,內存操作也最少):
完整代碼如下:
package test import ( "reflect" "testing" ) // 初始化map func initMap() map[int]int { m := map[int]int{} for i := 0; i < 10000; i++ { m[i] = i } return m } func getKeys1(m map[int]int) []int { // 數組默認長度為map長度,后面append時,不需要重新申請內存和拷貝,效率較高 j := 0 keys := make([]int, len(m)) for k := range m { keys[j] = k j++ } return keys } func getKeys2(m map[int]int) []int { // 數組默認長度為map長度,后面append時,不需要重新申請內存和拷貝,效率較高 keys := make([]int, 0, len(m)) for k := range m { keys = append(keys, k) } return keys } // 初始化默認 func getKeys3(m map[int]int) []int { // 注意:由于數組默認長度為0,后面append時,需要重新申請內存和拷貝,所以效率較低 keys := []int{} for k := range m { keys = append(keys, k) } return keys } // 使用反射 func getKeys4(m map[int]int) int { // 注意:雖然此寫法簡潔,但MapKeys函數內部操作復雜,效率極低 keys := reflect.ValueOf(m).MapKeys() return len(keys) } func BenchmarkMapkeys1(b *testing.B) { // 初始化map m := initMap() b.ResetTimer() for i := 0; i < b.N; i++ { getKeys1(m) } } func BenchmarkMapkeys2(b *testing.B) { // 初始化map m := initMap() b.ResetTimer() for i := 0; i < b.N; i++ { getKeys2(m) } } func BenchmarkMapkeys3(b *testing.B) { // 初始化map m := initMap() b.ResetTimer() for i := 0; i < b.N; i++ { getKeys3(m) } } func BenchmarkMapkeys4(b *testing.B) { // 初始化map m := initMap() b.ResetTimer() for i := 0; i < b.N; i++ { getKeys4(m) } }
補充:Golang踩坑——判斷map中是否有key
最近在實習,下班回去十點多了,再加上比較懶,快有兩個月沒寫東西了。
今天在開發(fā)一個模塊的時候是接著上一個人的寫的,好不容易各種配置寫好了開始跑,發(fā)現(xiàn)他踩了一個很容易踩的坑。
把bug抽出來單獨寫了個文件
package main import ( "log" ) type agent struct { id int str string } var m map[int]*agent func main() { m = make(map[int]*agent) a := &agent{ id: 1, str: "hello", } log.Println(a) var ok bool if a, ok = m[1]; ok { log.Println("ok") } m[1] = a log.Println(a) log.Println(a.str) }
運行一下
可以看到報了無效指針的問題(invalid memory address or nil pointer dereference)。
從上面的兩個log可以看到,最開始指針是有值的,第二個卻沒了,原因就出現(xiàn)在那個if判斷那里。
if判斷是想通過查看map知道agent是否已經存在,這個地方的錯誤是a,ok = map; 我們想通過ok判斷是否存在,但是在這里還有個a,這會導致有一個對a賦值的操作,也就是說如果map里有這個值,那沒事,如果沒有的話a就被賦值成了nil了。
在下面打印的時候也就成了nil,取它的屬性的時候會告訴我們找了個空指針的屬性,這肯定找不到。
我們把a換成_,再來看結果:
ok了。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關文章
Golang Gorm 更新字段save、update、updates
在gorm中,批量更新操作可以通過使用Update方法來實現(xiàn),本文主要介紹了Golang Gorm 更新字段save、update、updates,具有一定的參考價值,感興趣的可以了解一下2023-12-12使用docker構建golang線上部署環(huán)境的步驟詳解
這篇文章主要介紹了使用docker構建golang線上部署環(huán)境的步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。2017-11-11