go二維map Golang使用Map的正確姿勢

2021-10-13 11:42:31 字數 1709 閱讀 6082

初始化後再使用

golang中,map是引用型別,如切片一樣,通過下面的**宣告後指向的是nil,所以千萬別直接宣告後就使用,新手可能經常會犯如下錯誤:

var m map[string]string

m["result"] = "result"

由於字典是引用型別,所以當我們僅宣告而不初始化乙個字典型別的變數的時候,他的值是nil。對值為nil的字段除新增鍵值對外其他操作都不會引發錯誤。上面的第一行**對其進行寫入操作,就是對空指標的引用,這將會造成乙個painc。所以,得記得用 make函式對其進行分配記憶體和初始化:

m := make(map[string]string)

併發安全

併發安全也叫執行緒安全,在併發**現了資料的丟失,稱為併發不安全我們都知道非原子操作的都不是併發安全的,在golang中map,其讀寫操作並不保證併發安全。如下面的操作

c := make(map[string]string)

wg := sync.waitgroup{}

for i := 0; i < 10; i++ (i)

wg.wait()

fmt.println(c)

執行則會出現下面的錯誤

fatal error: concurrent map writes

你可以通過執行go run --race來對程式進行競態檢測

那麼如何解決這個問題呢?

通過鎖機制解決併發問題

下面介紹幾種常見的併發安全的操作map的方法

sync.mutex

c := make(map[string]string)

wg := sync.waitgroup{}

var lock sync.mutex

for i := 0; i < 10; i++ (i)

wg.wait()

fmt.println(c)

當然這裡也可以使用讀寫鎖sync.rwmutex,這樣併發讀多的場景下效能要好。

sync.map

sync.map 是官方出品的併發安全的map,他在內部使用了大量的原子操作來訪問鍵和值,並使用了read和dirty二個原生map作為儲存介質,具體實現流程可閱讀相關原始碼。

var m sync.map

//寫m.store("foo", "hello world")

m.store("slice", int)

m.store("int", 123)

//讀m.load("foo")

m.load("slice")

m.load("int")

//刪m.delete("int")

第三方map包

m := cmap.new()

//寫m.set("foo", "hello world")

m.set("slice", int)

m.set("int", 1)

//讀m.get("foo")

m.get("slice")

m.get("int")

m := concurrent.newconcurrentmap()

m.put("foo", "hello world")

m.put("slice", int)

m.put("int", 1)

//讀m.get("foo")

m.get("slice")

m.get("int")

延伸閱讀

image

go二維map Golang 中使用多維 map

golang 中使用多維 map golang 的 xml json 解析庫乍看使用起來很方便,只要構造一樣結構的 struct 就可以一下子匯入到變數中去了.其實手工構造 struct 非常容易出現結構偏差,而且最要命的是 unmarshal 執行的時候不是嚴格匯入所以沒有任何報錯.於是這兩天寫了...

c 二維陣列賦值及二維指標使用

include void main int tmp 2 test printf value d n tmp 0 printf value d n tmp 0 printf value d n tmp 1 printf value d n tmp 1 printf value d n tmp 0 1 ...

二維vector可以轉二維陣列使用嗎?

由於vector過載了下標運算子,且vector所儲存的資料是連續儲存,因此我們可以將vector引數直接當作一維陣列來使用,但二維vector能否直接轉換成二維陣列來使用呢?不可以。using std vector template t vector2array vector v 再來看看vect...