在go語言中 map 是很重要的數據結構。Map 是一種無序的鍵值對的集合。Map 最重要的一點是經過 key 來快速檢索數據,key 相似於索引,指向數據的值。問題來了,這麼安逸的 數據結構,它不是協程安全的 !當多個 協程同時對一個map 進行 讀寫時,會拋出致命錯誤。總結一下 想要 作到 協程安全 map 一共有如下三種方法。安全
這是最多見的一種操做,當要對 map操做的時候就加鎖,其餘的 協程就等待。下面是代碼示例:數據結構
package util import "sync" type SafeMap struct { Data map[string]interface{} Lock sync.RWMutex } func (this *SafeMap) Get(k string) interface{} { this.Lock.RLock() defer this.Lock.RUnlock() if v, exit := this.Data[k]; exit { return v } return nil } func (this *SafeMap) Set(k string, v interface{}) { this.Lock.Lock() defer this.Lock.Unlock() if this.Data == nil { this.Data = make(map[string]interface{}) } this.Data[k] = v }
這個是go 最近版本新推出來的 協程安全 map == 多是官方也以爲 蠻有必要的吧 。下面的代碼 主要寫一下使用方法。具體原理我就不介紹了。這裏要注意一下 sync.map 不須要 初始化socket
var test sync.Map //設置元素 func set (k,v interface{}){ test.Store(k,v) } //得到元素 func get (k interface{}) interface{}{ tem ,exit := test.Load(k) if exit { return tem } return nil } //傳入一個 函數 ,sync.map 會內部迭代 ,運行這個函數 func ranggfunc (funcs func(key, value interface{}) bool) { test.Range(funcs) } //刪除元素 func del(key interface{}){ test.Delete(key) }
這個思路有點 騷,就是一直由一個協程 操做map ,其餘協程 經過 channle 告訴這個協程應該 怎麼操做。其實這樣子 性能不是很好,由於 channle 底層 也是鎖 ,並且 map 存數據 是要 計算hash的 ,以前是 多個協程本身算本身的hash ,如今變成了一個協程計算了。可是這個思路仍是能夠,不單單是 在 map上能夠這麼操做。socket 通訊啊, 全局 惟一對象的調用啊,均可以用此思路。下面給你們看一下我是實現的代碼:函數
package main import ( "fmt" //"time" ) var ( ADD interface{} = 1 DEL interface{} = 2 GET interface{} = 3 ) type safeMap struct { Msq chan *[3] interface{} //['type','id','value',channle] data map[interface{}]interface{} chanl chan interface{} } func NewSafeMap() *safeMap { tem := &safeMap{} tem.init() return tem } func (this *safeMap) init() { this.Msq = make(chan *[3]interface{},10) this.data = make(map[interface{}]interface{}) this.chanl = make(chan interface{},0) go this.run() } func (this *safeMap) run() { for { select { case msg := <- this.Msq : switch msg[0] { case ADD : this.dataAdd(msg[1],msg[2]) case DEL : this.dataDel(msg[1]) case GET : this.dataGet(msg[1]) } } } } func (this *safeMap) msqChan (typ,id,val interface{}) *[3]interface{}{ return &[...]interface{}{typ,id,val} } //保存 或者更新元素 func (this *safeMap) dataAdd (id , value interface{}) { this.data[id] = value } //刪除元素 func (this *safeMap) dataDel (id interface{}) { delete(this.data,id) } //得到元素 func (this *safeMap) dataGet (id interface{}) { if val ,exit := this.data[id] ;exit { this.chanl <- val return } this.chanl <- nil } //----------------------------------------------------對外接口-------------------------------- func (this *safeMap) Add (id ,value interface{}) { this.Msq <- this.msqChan(ADD,id,value) } func (this *safeMap) Del (id interface{}) { this.Msq <- this.msqChan(DEL,id ,nil) } func (this *safeMap) Get (id interface{}) interface{} { this.Msq <- this.msqChan(GET,id,nil) res := <- this.chanl return res } //得到 長度 func (this *safeMap) GetLength() uint32{ return uint32(len(this.data)) } func main() { sa := NewSafeMap() // sa.Add(1,1) sa.Add(2,3) fmt.Println(2,sa.Get(2)) sa.Del(2) fmt.Println(2,sa.Get(2)) }