初始化後再使用
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...