因為golang的map和列表切片都是引用類型,且非線程安全的,所以在多個go routine中進行讀寫操作的時候,會產生“map read and map write“的panic錯誤。
某一些類型的對象,會有這種類似的set方法來寫數據,或者get方法來返回一個map:
func (this *object) Set(name, val) {
this.Lock()
defer this.Unlock()
this.m[name] = val
}
func (this *object) Get() map[string]string {
this.Lock()
defer this.Unlock()
return this.m
}
如果會在多個go routine中通過該對象的Get()方法獲取到的map進行讀操作,並且在其他go routine中用Set()方法來寫操作,那么有可能會導致“map read and map write“的panic錯誤。
原因是Get方法獲取的map和Set方法操作的map是同一個map,如果讀寫線程在同一時刻操作這2個map,就會產生錯誤。
所以Get方法最好用這種方式返回map:
func (this *object) Get() map[string]string {
this.Lock()
defer this.Unlock()
newm := make(map[string]string)
for k, v := range this.m {
newm[k] = v
}
return newm
}
這樣每次Get獲取的map,其實是一個新的map,就可以不用考慮同時讀寫的問題了。
