GoFrame?gmap遍歷hashmap?listmap?treemap使用技巧
文章比較硬核,爆肝2千多字,除了hashmap、listmap、treemap使用技巧閱讀還有使用gmap的踩坑之旅,閱讀大約需要5~10分鐘。
先說結(jié)論
map類型
一圖勝千言:
實(shí)例化示例:
hashMap := gmap.New(true) listMap := gmap.NewListMap(true) treeMap := gmap.NewTreeMap(gutil.ComparatorInt, true)
使用技巧
當(dāng)我們對返回順序有要求時不能使用hashmap,因?yàn)閔ashmap返回的是無序列表;
當(dāng)需要按輸入順序返回結(jié)果時使用listmap;
當(dāng)需要讓返回結(jié)果自然升序排列時使用treemap
package main import ( "fmt" "github.com/gogf/gf/container/gmap" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/util/gutil" ) func main() { array := g.Slice{5, 1, 2, 7, 3, 9, 0} hashMap := gmap.New(true) listMap := gmap.NewListMap(true) treeMap := gmap.NewTreeMap(gutil.ComparatorInt, true) // 賦值 for _, v := range array { hashMap.Set(v, v) listMap.Set(v, v) treeMap.Set(v, v) } //打印結(jié)果 fmt.Println("hashMap.Keys() :", hashMap.Keys()) fmt.Println("hashMap.Values():", hashMap.Values()) //從打印結(jié)果可知hashmap的鍵列表和值列表返回值的順序沒有規(guī)律,隨機(jī)返回 fmt.Println("listMap.Keys() :", listMap.Keys()) fmt.Println("listMap.Values():", listMap.Values()) //listmap鍵列表和值列表有序返回,且順序和寫入順序一致 fmt.Println("treeMap.Keys() :", treeMap.Keys()) fmt.Println("treeMap.Values():", treeMap.Values()) //treemap鍵列表和值列表也有序返回,但是不和寫入順序一致,按自然數(shù)升序返回 }
打印結(jié)果
hashMap.Keys() : [5 1 2 7 3 9 0] hashMap.Values(): [2 7 3 9 0 5 1] listMap.Keys() : [5 1 2 7 3 9 0] listMap.Values(): [5 1 2 7 3 9 0] treeMap.Keys() : [0 1 2 3 5 7 9] treeMap.Values(): [0 1 2 3 5 7 9]
為了讓大家更好的理解gmap,下面介紹一下gmap的基礎(chǔ)使用和一些進(jìn)階技巧。
基礎(chǔ)概念
GoFrame框架(下文簡稱gf)提供的數(shù)據(jù)類型,比如:字典gmap、數(shù)組garray、集合gset、隊列g(shù)queue、樹形結(jié)構(gòu)gtree、鏈表glist都是支持設(shè)置并發(fā)安全開關(guān)的。
支持設(shè)置并發(fā)安全開關(guān)這也是gf提供的常用數(shù)據(jù)類型和原生數(shù)據(jù)類型非常重要的區(qū)別
今天和大家分享gf框架中g(shù)map相關(guān)知識點(diǎn)
對比sync.Map
go語言提供的原生map不是并發(fā)安全的map類型
go語言從1.9版本開始引入了并發(fā)安全的sync.Map,但gmap比較于標(biāo)準(zhǔn)庫的sync.Map性能更加優(yōu)異,并且功能更加豐富。
基礎(chǔ)使用
- gmap.New(true) 在初始化的時候開啟并發(fā)安全開關(guān)
- 通過 Set() 方法賦值,通過 Sets() 方法批量賦值
- 通過 Size() 方法獲取map大小
- 通過 Get() 根據(jù)key獲取value值
- ...
為了方便大家更好的查看效果,在下方代碼段中標(biāo)明了打印結(jié)果
package main import ( "fmt" "github.com/gogf/gf/container/gmap" ) func main() { m := gmap.New(true) // 設(shè)置鍵值對 for i := 0; i < 10; i++ { m.Set(i, i) } fmt.Println("查詢map大小:", m.Size()) //批量設(shè)置鍵值對 m.Sets(map[interface{}]interface{}{ 10: 10, 11: 11, }) // 目前map的值 fmt.Println("目前map的值:", m) fmt.Println("查詢是否存在鍵值對:", m.Contains(1)) fmt.Println("根據(jù)key獲得value:", m.Get(1)) fmt.Println("刪除數(shù)據(jù)", m.Remove(1)) //刪除多組數(shù)據(jù) fmt.Println("刪除前的map大小:", m.Size()) m.Removes([]interface{}{2, 3}) fmt.Println("刪除后的map大?。?, m.Size()) //當(dāng)前鍵名列表 fmt.Println("鍵名列表:", m.Keys()) //我們發(fā)現(xiàn)是無序列表 fmt.Println("鍵值列表:", m.Values()) //我們發(fā)現(xiàn)也是無序列表 //查詢鍵名,當(dāng)鍵值不存在時寫入默認(rèn)值 fmt.Println(m.GetOrSet(20, 20)) //返回值是20 fmt.Println(m.GetOrSet(20, "二十")) //返回值仍然是20,因?yàn)閗ey對應(yīng)的值存在 m.Remove(20) fmt.Println(m.GetOrSet(20, "二十")) //返回值是二十,因?yàn)閗ey對應(yīng)的值不存在 // 遍歷map m.Iterator(func(k interface{}, v interface{}) bool { fmt.Printf("%v:%v \n", k, v) return true }) //自定義寫鎖操作 m.LockFunc(func(m map[interface{}]interface{}) { m[88] = 88 }) // 自定義讀鎖操作 m.RLockFunc(func(m map[interface{}]interface{}) { fmt.Println("m[88]:", m[88]) }) // 清空map m.Clear() //判斷map是否為空 fmt.Println("m.IsEmpty():", m.IsEmpty()) }
運(yùn)行結(jié)果
上面介紹的基礎(chǔ)使用比較簡單,下面介紹進(jìn)階使用。
合并 merge
注意:Merge()的參數(shù)需要是map的引用類型,也就是傳map的取址符。
package main import ( "fmt" "github.com/gogf/gf/container/gmap" ) func main() { var m1, m2 gmap.Map m1.Set("k1", "v1") m2.Set("k2", "v2") m1.Merge(&m2) fmt.Println("m1.Map()", m1.Map()) //m1.Map() map[k1:v1 k2:v2] fmt.Println("m2.Map()", m2.Map()) //m2.Map() map[k2:v2] }
序列化
正如上一篇 GoFrame glist 基礎(chǔ)使用和自定義遍歷 介紹的,gf框架提供的數(shù)據(jù)類型不僅支持設(shè)置并發(fā)安全,也都支持序列化和反序列化。
json序列化和反序列化:序列化就是轉(zhuǎn)成json格式,反序列化就是json轉(zhuǎn)成其他格式類型(比如:map、數(shù)組、對象等)
package main import ( "encoding/json" "fmt" "github.com/gogf/gf/container/gmap" ) func main() { // 序列化 //var m gmap.Map m := gmap.New() //必須實(shí)例化 只是像上面聲明但是不進(jìn)行實(shí)例化,是無法序列化成功的 m.Sets(map[interface{}]interface{}{ "name": "王中陽", "age": 28, }) res, _ := json.Marshal(m) fmt.Println("序列化結(jié)果:", res) //打印結(jié)果:{"age":28,"name":"王中陽"} // 反序列化 m2 := gmap.New() s := []byte(`{"age":28,"name":"王中陽"}`) _ = json.Unmarshal(s, &m2) fmt.Println("反序列化結(jié)果:", m2.Map()) //反序列化結(jié)果: map[age:28 name:王中陽] }
踩坑
正如上面代碼段中注釋提到的:
在進(jìn)行序列化操作時,必須實(shí)例化map
m := gmap.New()
只是聲明map而不進(jìn)行實(shí)例化,是無法序列化成功的
var m gmap.Map
過濾空值
package main import ( "fmt" "github.com/gogf/gf/container/gmap" ) func main() { //首先明確:空值和nil是不一樣的,nil是未定義;而空值包括空字符串,false、0等 m1 := gmap.NewFrom(map[interface{}]interface{}{ "k1": "", "k2": nil, "k3": 0, "k4": false, "k5": 1, }) m2 := gmap.NewFrom(map[interface{}]interface{}{ "k1": "", "k2": nil, "k3": 0, "k4": false, "k5": 1, }) m1.FilterEmpty() m2.FilterNil() fmt.Println("m1.FilterEmpty():", m1) //預(yù)測結(jié)果: k5:1 fmt.Println("m2.FilterNil():", m2) //預(yù)測結(jié)果:除了k2,其他都返回 // 打印結(jié)果和預(yù)期的一致: //m1.FilterEmpty(): {"k5":1} //m2.FilterNil(): {"k1":"","k3":0,"k4":false,"k5":1} }
打印結(jié)果
m1.FilterEmpty(): {"k5":1} m2.FilterNil(): {"k1":"","k3":0,"k4":false,"k5":1}
鍵值對反轉(zhuǎn) Flip
package main import ( "github.com/gogf/gf/container/gmap" "github.com/gogf/gf/frame/g" ) func main() { // 鍵值對反轉(zhuǎn)flip var m gmap.Map m.Sets(map[interface{}]interface{}{ "k1": "v1", "k2": "v2", }) fmt.Println("反轉(zhuǎn)前:", m.Map()) m.Flip() fmt.Println("反轉(zhuǎn)后:", m.Map()) }
打印結(jié)果
反轉(zhuǎn)前:{ "k1": "v1", "k2": "v2" } 反轉(zhuǎn)后:{ "v1": "k1", "v2": "k2" }
出棧(隨機(jī)出棧)
package main import ( "fmt" "github.com/gogf/gf/container/gmap" ) func main() { //pop pops map出棧(彈棧) var m gmap.Map m.Sets(map[interface{}]interface{}{ 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, }) fmt.Println("m.Pop()之前:", m.Map()) key, value := m.Pop() fmt.Println("key:", key) fmt.Println("value:", value) fmt.Println("m.Pop()之后:", m.Map()) //多次測試后發(fā)現(xiàn)是隨機(jī)出棧,不能理所當(dāng)然的認(rèn)為按順序出棧 res := m.Pops(2) //參數(shù)是出棧個數(shù) fmt.Println("res:", res) fmt.Println("m.Pops之后:", m.Map()) //多次測試之后發(fā)現(xiàn)也是隨機(jī)出棧 }
運(yùn)行結(jié)果
踩坑
注意:多次測試后發(fā)現(xiàn)是隨機(jī)出棧,不能理所當(dāng)然的認(rèn)為按順序出棧
總結(jié)
通過這篇文章,我們了解到:
重點(diǎn)消化一下map遍歷時,不同map的特點(diǎn):
- 1.1 當(dāng)我們對返回順序有要求時不能使用hashmap,因?yàn)閔ashmap返回的是無序列表;
- 1.2 當(dāng)需要按輸入順序返回結(jié)果時使用listmap;
- 1.3 當(dāng)需要讓返回結(jié)果自然升序排列時使用treemap
gmap的基礎(chǔ)使用和進(jìn)階使用技巧:反轉(zhuǎn)map、序列化、合并map、出棧等。
gf框架提供的數(shù)據(jù)結(jié)構(gòu),比如:字典gmap、數(shù)組garray、集合gset、隊列g(shù)queue、樹形結(jié)構(gòu)gtree、鏈表glist 都是支持設(shè)置并發(fā)安全開關(guān)的;而且都支持序列化和反序列化,實(shí)現(xiàn)了標(biāo)準(zhǔn)庫json
數(shù)據(jù)格式的序列化/反序列化接口。
以上就是GoFrame gmap遍歷hashmap listmap treemap使用技巧的詳細(xì)內(nèi)容,更多關(guān)于GoFrame gmap遍歷的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
goframe重寫FastAdmin后端實(shí)現(xiàn)實(shí)例詳解
這篇文章主要為大家介紹了goframe重寫FastAdmin后端實(shí)現(xiàn)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法
這篇文章主要介紹了MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05Golang 模塊引入及表格讀寫業(yè)務(wù)快速實(shí)現(xiàn)示例
這篇文章主要為大家介紹了Golang模塊引入及表格讀寫業(yè)務(wù)的快速實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Go基礎(chǔ)教程系列之defer、panic和recover詳解
這篇文章主要介紹了Go基礎(chǔ)教程系列之defer、panic和recover,需要的朋友可以參考下2022-04-04