GO并发安全 Map
2020-02-28 本文已影响0人
peroLuo
场景1:一个请求同时进行2条数据库查询操作,然后把查询的数据,传给一个map,然后返回给客户端
问题代码
func GetHome(c *gin.Context) {
var wg sync.WaitGroup
res := make(map[string]interface{})
var g modle.Goods
wg.Add(2)
// 数据库查询1
go func() {
goods, _ := g.NewGoods(1, 5)
res["good"] = goods
wg.Done()
}()
// 数据库查询2
go func() {
good, _ := g.Search()
res["goods"] = good
wg.Done()
}()
wg.Wait()
response.ReSuccess(c, "", res)
}
进行多次访问后,会出现
fatal error: concurrent map writes
错误。
结论: Map数据写入操作线程不安全
解决方案一 Channel
func GetHome(c *gin.Context) {
var c1 = make(chan modle.Goods, 1)
var c2 = make(chan []modle.Goods, 1)
res := make(map[string]interface{})
var g modle.Goods
// 数据库查询1
go func() {
goods, _ := g.NewGoods(1, 5)
c2 <- goods
}()
// 数据库查询2
go func() {
good, _ := g.Search()
c1 <- good
}()
res["good"] = <-c1
res["goods"] = <-c2
response.ReSuccess(c, "", res)
}
解决方案2 sync.Map
func GetHome(c *gin.Context) {
var wg sync.WaitGroup
var m = sync.Map{}
var g modle.Goods
res := make(map[string]interface{})
wg.Add(2)
// 数据库查询1
go func() {
goods, _ := g.NewGoods(1, 5)
m.Store("goods", goods)
wg.Done()
}()
// 数据库查询2
go func() {
good, _ := g.Search()
m.Store("good", good)
wg.Done()
}()
wg.Wait()
good, _ := m.Load("good")
goods, _ := m.Load("goods")
res["good"] = good
res["good"] = goods
response.ReSuccess(c, "", res)
}