Go 學習筆記(12) map

2021-09-12 01:34:31 字數 4627 閱讀 3305

map是乙個無序的key/value對的集合,其中key是唯一的。如果我們在向字典中放入乙個鍵值對的時候其中已經有相同的鍵的話,那麼與此鍵關聯的那個值會被新值替換。

map的字面量是map[k]t,其中

注意:鍵型別必須是支援==比較運算子的資料型別,否則會引起錯誤。即不能是陣列、切片、字典、結構體、函式型別,但是指標和介面型別可以。對於值的型別,沒有限制。

map可以通過測試key是否相等來判斷是否已經存在。雖然浮點數型別也是支援相等運算子比較的,但最好別使用將浮點數作為key,可能出現nan和任何浮點數都不相等。

含有陣列切片的結構體不能作為key,只包含內建型別的struct是可以作為key的。如果要用結構體作為key可以提供key()hash()方法,這樣可以通過結構體的域計算出唯一的數字或者字串的key

示例:

var m1 map[string]int

m1 = map[string]int

var m2 map[string]int = map[string]int{}

m2["a"] = 3

m2["b"] = 4

m3 := map[string]int

m4 := map[string]int{}

m4["a"] = 1

m4["b"] = 2

複製**

與切片型別相同,字典型別屬於引用型別。它的零值即為nil。(詳見零值問題)

map可以根據新增的key-value對動態的伸縮,不存在固定長度或者最大限制。但是你可以選擇標明map的初始容量capacity

m1 := make(map[string]int)

m1["a"] = 1

m1["b"] =2

m2 := make(map[string]int, 100)

複製**

不要使用new,永遠用make來構造map。如果你錯誤的使用new()分配了乙個引用物件,你會獲得乙個空引用的指標,相當於宣告了乙個未初始化的變數並且取了它的位址。

對於map來說,如果獲取不存在的 key,就以它的值型別的空值(或稱預設值)作為值結果。那麼,我們在不知道 map 確切的情況下,怎麼知道要取的 key 是否存在呢?

m1 := map[string]int

x := m1["a"] // 1

x, ok := m1["a"] // 1 true _, ok := m1["a"] 可以用來判斷 key 是否存在。

y := m1["c"] // 0

y, ok := m1["c"] // 0 false

複製**

map中的元素並不是乙個變數,因此我們不能對map的元素進行取址操作。禁止對map元素取址的原因是map可能隨著元素數量的增長而重新分配更大的記憶體空間,從而可能導致之前的位址無效:

&m1           // 沒問題

&m1["a"] // cannot take the address of m1["a"]

複製**

m1 := map[string]int

m1["a"] = 3

fmt.println(m1) // map[a:3 b:2]

m1["c"] = 4

fmt.println(m1) // map[c:4 a:3 b:2]

複製**

另外,x += yx++等簡短賦值語法也可以用在map

delete操作是安全的,有則刪除,無則不做。

m1 := map[string]int

delete(m1, "a") // 有則刪除

delete(m1, "c") // 無則不做

複製**

map的迭代順序是不確定的,並且不同的雜湊函式實現可能導致不同的遍歷順序。在實踐中,遍歷的順序是隨機的,每一次遍歷的順序都不相同。這是故意的,每次都使用隨機的遍歷順序可以強制要求程式不會依賴具體的雜湊函式實現。

for key, value := range map1 

// 如果只想獲取 key,你可以這麼使用:

for key := range map1

複製**

map是無序的,如果你想按順序遍歷map,需要將key(或者value)拷貝到乙個切片,再對切片排序(使用sort包):

package main

import (

"fmt"

"sort"

)var m = map[string]int

func

main()

keys := make(string, 0, len(m))

for key := range m

sort.strings(keys)

for _, key := range keys

}複製**

但是如果你想要乙個排序的列表,最好使用結構體切片,這樣會更有效:

type name struct 

複製**

切片的元素是map型別:

package main

import

"fmt"

func

main()

fmt.println(myslice) // [map[a:10 b:20 c:30] map[a:10 b:20 c:30] map[a:10 b:20 c:30]]

}複製**

當然,mapvalue也可以是切片型別:

var m1 map[string]int

複製**

slice一樣,map之間也不能進行相等比較,唯一的例外是和nil進行比較。要判斷兩個map是否包含相同的keyvalue,我們必須通過乙個迴圈實現:

func

equal

(x, y map[string]int)

bool

for k, xv := range x

}return

true

}複製**

map型別的零值是nil,也就是沒有引用任何雜湊表。map上的大部分操作,包括查詢、刪除、lenrange迴圈都可以安全工作在nil值的map上,它們的行為和乙個空的map類似。但是向乙個nil值的map存入元素將導致乙個panic異常。在向map存資料前必須先建立map

var m1 map[string]int

// nil

m2 := map[string]int{} // 空map

fmt.println(m1 == nil) // true 0

fmt.println(m2 == nil) // false 0

m1["a"] = 1

// panic: assignment to entry in nil map

m2["a"] = 1

// 正常

複製**

go語言中並沒有set型別,由於map中的key也是不相同的,可以將忽略valuemap當成set

go學習筆記(12)

在學習golang的websocket的時候,出現了這樣錯誤。這個錯誤產生了很大的疑惑。為什麼會出錯?由於前端作為測試使用,所以編寫乙個較為簡單的測試用例即可。但js裡面的websocket 傳送採取了二進位制去傳送。ws.binarytype arraybuffer 監聽了本地埠6336 由於是測...

GO學習筆記 對映 map

go語言中提供的對映關係容器為map,其內部使用雜湊表 hash 實現。go語言中 map的定義語法如下 map keytype valuetype 其中,map型別的變數預設初始值為nil,需要使用make 函式來分配記憶體。語法為 make map keytype valuetype,cap 其...

GO學習筆記之 map

map是 key value 資料結構,又稱為字段或者關聯陣列。類似其他程式語言的集合 在程式設計中經常使用。基本語法 map是無序的 var map變數名 map keytype valuetype key可以是什麼型別 golang中的 map,的 key可以是很多種型別,比如 bool 數字,...