GO語言中的Map使用方法詳解
Map簡述
Go語言中的map(映射、字典)是一種內(nèi)置的數(shù)據(jù)結(jié)構(gòu),它是一個(gè)無序的key-value對的集合,比如以身份證號作為唯一鍵來標(biāo)識一個(gè)人的信息。Go語言中并沒有提供一個(gè)set類型,但是map中的key也是不相同的,可以用map實(shí)現(xiàn)類似set的功能。
map格式為:
map[keyType]valueType
在一個(gè)map里所有的鍵都是唯一的,而且必須是支持==和!=操作符的類型,切片、函數(shù)以及包含切片的結(jié)構(gòu)類型這些類型由于具有引用語義,不能作為映射的鍵,使用這些類型會造成編譯錯(cuò)誤:
dict := map[ []string ]int{} //err, invalid map key type []string
map值可以是任意類型,沒有限制。map里所有鍵的數(shù)據(jù)類型必須是相同的,值也必須如此,但鍵和值的數(shù)據(jù)類型可以不相同。
注意:map是無序的,我們無法決定它的返回順序,所以,每次打印結(jié)果的順利有可能不同。
創(chuàng)建及初始化Map
創(chuàng)建Map
fmt.Println(m1 == nil) //true //m1[1] = "Luffy" //nil的map不能使用err, panic: assignment to entry in nil map m2 := map[int]string{} //m2, m3的創(chuàng)建方法是等價(jià)的 m3 := make(map[int]string) fmt.Println(m2, m3) //map[] map[] m4 := make(map[int]string, 10) //第2個(gè)參數(shù)指定容量 fmt.Println(m4) //map[]
創(chuàng)建m4的方法指定了map的初始創(chuàng)建容量。 與slice類似,后期在使用過程中,map可以自動(dòng)擴(kuò)容。只不過map更方便一些,不用借助類似append的函數(shù),直接賦值即可。如,m1[17] = "Nami"。賦值過程中,key如果與已有map中key重復(fù),會將原有map中key對應(yīng)的value覆蓋。
但是!對于map而言,可以使用len()函數(shù),但不能使用cap()函數(shù)。
初始化Map
也可以直接指定初值,要保證key不重復(fù)。
//1、定義同時(shí)初始化 var m1 map[int]string = map[int]string{1: "Luffy", 2: "Sanji"} fmt.Println(m1) //map[1:Luffy 2:Sanji] //2、自動(dòng)推導(dǎo)類型 := m2 := map[int]string{1: "Luffy", 2: "Sanji"} fmt.Println(m2)
常用操作
賦值
m1 := map[int]string{1: "Luffy", 2: "Sanji"} m1[1] = "Nami" //修改 m1[3] = "Zoro" //追加, go底層會自動(dòng)為map分配空間 fmt.Println(m1) //map[1:Nami 2:Sanji 3:Zoro] m2 := make(map[int]string, 10) //創(chuàng)建map m2[0] = "aaa" m2[1] = "bbb" fmt.Println(m2) //map[0:aaa 1:bbb] fmt.Println(m2[0], m2[1]) //aaa bbb
遍歷
Map的迭代順序是不確定的,并且不同的哈希函數(shù)實(shí)現(xiàn)可能導(dǎo)致不同的遍歷順序。在實(shí)踐中,遍歷的順序是隨機(jī)的,每一次遍歷的順序都不相同。這是故意的,每次都使用隨機(jī)的遍歷順序可以強(qiáng)制要求程序不會依賴具體的哈希函數(shù)實(shí)現(xiàn)。
m1 := map[int]string{1: "Luffy", 2: "Sanji"} //遍歷1,第一個(gè)返回值是key,第二個(gè)返回值是value for k, v := range m1 { fmt.Printf("%d ----> %s\n", k, v) //1 ----> Luffy //2 ----> yoyo } //遍歷2,第一個(gè)返回值是key,第二個(gè)返回值是value(可省略) for k := range m1 { fmt.Printf("%d ----> %s\n", k, m1[k]) //1 ----> Luffy //2 ----> Sanji }
有時(shí)候可能需要知道對應(yīng)的元素是否真的是在map之中??梢允褂孟聵?biāo)語法判斷某個(gè)key是否存在。map的下標(biāo)語法將產(chǎn)生兩個(gè)值,其中第二個(gè)是一個(gè)布爾值,用于報(bào)告元素是否真的存在。
如果key存在,第一個(gè)返回值返回value的值。第二個(gè)返回值為 true。
value, ok := m1[1] fmt.Println("value = ", value, ", ok = ", ok) //value = mike , ok = true
如果key不存在,第一個(gè)返回值為空,第二個(gè)返回值為false。
value2, has := m1[3] fmt.Println("value2 = ", value2, ", has = ", has) //value2 = , has = false
刪除
使用delete()函數(shù),指定key值可以方便的刪除map中的k-v映射。
m1 := map[int]string{1: "Luffy", 2: "Sanji", 3: "Zoro"} for k, v := range m1 { //遍歷,第一個(gè)返回值是key,第二個(gè)返回值是value fmt.Printf("%d ----> %s\n", k, v) } //1 ----> Sanji //2 ----> Sanji //3 ----> Zoro delete(m1, 2) //刪除key值為2的map for k, v := range m1 { fmt.Printf("%d ----> %s\n", k, v) } //1 ----> Luffy //3 ----> Zoro
delete()操作是安全的,即使元素不在map中也沒有關(guān)系;如果查找刪除失敗將返回value類型對應(yīng)的零值。如:
delete(m1, 5) //刪除key值為5的map for k, v := range m1 { fmt.Printf("%d ----> %s\n", k, v) } //1 ----> Luffy //3 ----> Zoro
Map輸出結(jié)果依然是原來的樣子,且不會有任何錯(cuò)誤提示。
Map做函數(shù)參數(shù)
與slice 相似,在函數(shù)間傳遞映射并不會制造出該映射的一個(gè)副本,不是值傳遞,而是引用傳遞:
func DeleteMap(m map[int]string, key int) { delete(m, key) //刪除key值為2的map for k, v := range m { fmt.Printf("len(m)=%d, %d ----> %s\n", len(m), k, v) } //len(m)=2, 1 ----> Luffy //len(m)=2, 3 ----> Zoro } func main() { m := map[int]string{1: "Luffy", 2: "Sanji", 3: "Zoro"} DeleteMap(m, 2) //刪除key值為2的map for k, v := range m { fmt.Printf("len(m)=%d, %d ----> %s\n", len(m), k, v) } //len(m)=2, 1 ----> Luffy //len(m)=2, 3 ----> Zoro }
Map做函數(shù)返回值
返回的依然是引用:
func test() map[int]string { // m1 := map[int]string{1: "Luffy", 2: "Sanji", 3: "Zoro"} m1 := make(map[int]string, 1) // 創(chuàng)建一個(gè)初創(chuàng)容量為1的map m1[1] = "Luffy" m1[2] = "Sanji" // 自動(dòng)擴(kuò)容 m1[67] = "Zoro" m1[2] = "Nami" // 覆蓋 key值為2 的map fmt.Println("m1 = ", m1) return m1 } func main() { m2 := test() // 返回值 —— 傳引用 fmt.Println("m2 = ", m2) }
輸出:
m1 = map[1:Luffy 2:Nami 67:Zoro]
m2 = map[2:Nami 67:Zoro 1:Luffy]
附:判斷兩個(gè)map中是否有相同的key和value
通過下標(biāo)訪問map中的元素總會有返回值。如果k在map中,就返回對應(yīng)的v。**如果不在就返回v類型的零值。**所以通過下標(biāo)訪問元素時(shí),需要辨別是否真的不存在還是這個(gè)v是0。
v, ok := ages["jack"] if !ok { ...... } // 這兩句話可以合并 v, ok := ages["jack"]; !ok {......}
通過下標(biāo)訪問map元素會有兩個(gè)返回值,第二個(gè)返回值是一個(gè)布爾類型,來報(bào)告元素是否存在,一般用ok表示。
// 判斷兩個(gè)map是否有相同的k和v func equal(x, y map[string]int) bool { if len(x) != len(y) { return false } for k, xv := range x { /** 用!ok 來區(qū)分元素不存在,元素存在但是值為0的情況,如果只使用 xv != y[k] 在下面這個(gè)情況就是出錯(cuò) equals(map[string]int{"A":0}, map[string]int{"B":0}) 因?yàn)槿绻檎业膋在map中不存在,會返回v類型的零值,當(dāng)在第二個(gè)map中查找是否有A時(shí),會返回0,如果只依靠返回值來比較是無法判斷A是不存在還是A對應(yīng)的v 就是 0 */ if yv, ok := y[k]; !ok || yv != xv { return false } } return true }
總結(jié)
到此這篇關(guān)于GO語言中的Map使用方法詳解的文章就介紹到這了,更多相關(guān)GO語言Map使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go并發(fā)編程sync.Cond使用場景及實(shí)現(xiàn)原理
這篇文章主要為大家介紹了go并發(fā)編程sync.Cond使用場景及實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08go語言中空結(jié)構(gòu)體的實(shí)現(xiàn)
本文主要介紹了go語言中空結(jié)構(gòu)體的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-04-04Go map底層實(shí)現(xiàn)與擴(kuò)容規(guī)則和特性分類詳細(xì)講解
這篇文章主要介紹了Go map底層實(shí)現(xiàn)與擴(kuò)容規(guī)則和特性,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-03-03golang實(shí)現(xiàn)讀取excel數(shù)據(jù)并導(dǎo)入數(shù)據(jù)庫
Go 語言是一門適合用于編寫高效且并發(fā)的 Web 應(yīng)用程序的編程語言,同時(shí)也可以使用它進(jìn)行數(shù)據(jù)處理和分析,本文主要介紹了如何通過go語言實(shí)現(xiàn)讀取excel數(shù)據(jù)并導(dǎo)入數(shù)據(jù)庫,感興趣的小伙伴可以了解下2025-04-04golang封裝一個(gè)執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)示例代碼
在?Go?語言中,您可以使用?os/exec?包來執(zhí)行外部命令,不通過調(diào)用?shell,并且能夠獲得進(jìn)程的退出碼、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出,下面給大家分享golang封裝一個(gè)執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)的方法,感興趣的朋友跟隨小編一起看看吧2024-06-06一文詳解Golang?定時(shí)任務(wù)庫?gron?設(shè)計(jì)和原理
這篇文章主要介紹了一文詳解Golang?定時(shí)任務(wù)庫?gron?設(shè)計(jì)和原理,gron是一個(gè)比較小巧、靈活的定時(shí)任務(wù)庫,可以執(zhí)行定時(shí)的、周期性的任務(wù)。gron提供簡潔的、并發(fā)安全的接口2022-08-08一文搞懂Golang文件操作增刪改查功能(基礎(chǔ)篇)
這篇文章主要介紹了一文搞懂Golang文件操作增刪改查功能(基礎(chǔ)篇),Golang 可以認(rèn)為是服務(wù)器開發(fā)語言發(fā)展的趨勢之一,特別是在流媒體服務(wù)器開發(fā)中,已經(jīng)占有一席之地,今天我們不聊特別深?yuàn)W的機(jī)制和內(nèi)容,就來聊一聊 Golang 對于文件的基本操作2021-04-04