go并发访问map的坑 fatal error: concurrent map read and map write

简介: go并发访问map的坑 fatal error: concurrent map read and map write

前言


go 并发访问map是不安全的, 会出现未定义的错误导致程序退出…坑总得踩一踩才会知道


例子


先写一个错误的

package main
import "fmt"
func test() map[string]interface{}{
  taskList := []string{"a", "b"}
  result := make(map[string]interface{})
  for _, task := range taskList {
    go func(task string) {
      switch task {
      case "a":
        result["a"] = "xiaofei"
      case "b":
        result["b"] = "ceshi"
      }
    }(task)
  }
  return result
}
func main() {
  for a := 0; a < 1000; a++ {
    fmt.Println(test())
  }
}

返回结果

image.png


上面代码有两个问题, 第一个是没有阻塞go程, 第二个就是并发访问map了


正确的写法

package main
import (
  "fmt"
  "sync"
)
// 使用读写锁 sync.RWMutex
type NewMap struct {
  lock *sync.RWMutex
  sm   map[interface{}]interface{}
}
func (m *NewMap) Set(k interface{}, v interface{}) bool {
  m.lock.Lock()
  defer m.lock.Unlock()
  m.sm[k] = v
  return true
}
func test() map[interface{}]interface{} {
  taskList := []string{"a", "b"}
  xf := &sync.WaitGroup{}
  result := NewMap{
    lock: new(sync.RWMutex),
    sm: make(map[interface{}]interface{}),
  }
  for _, task := range taskList {
    xf.Add(1)
    go func(task string) {
      defer xf.Done()
      switch task {
      case "a":
        result.Set("a", "xiaofei")
      case "b":
        result.Set("b", "ceshi")
      }
    }(task)
  }
  xf.Wait()
  return result.sm
}
func main() {
  for a := 0; a < 100; a++ {
    fmt.Println(test())
  }
}

建议把这个map做一个基类方法, 所有的方法封装一下直接用就ok了;

目录
相关文章
|
2月前
|
Go
Go 语言为什么不支持并发读写 map?
Go 语言为什么不支持并发读写 map?
|
2月前
|
测试技术 Shell Go
go 语言优雅地处理 error
go 语言优雅地处理 error
|
2月前
|
存储 安全 NoSQL
Go map 读写性能优化 - 分片 map
Go map 读写性能优化 - 分片 map
36 1
|
2月前
|
IDE Go 开发工具
Go Error module declares its path as but was required as解决方案
文章提供了一个解决方案,用于处理在Go工程中将依赖的仓库从A更换为B(即使它们完全相同)时遇到的路径声明错误,建议通过发布新版本来解决此问题。
49 0
|
2月前
|
存储 Go 容器
Go从入门到放弃之map(字典)
Go从入门到放弃之map(字典)
|
2月前
|
设计模式 安全 Java
Go - 使用 sync.Map 来解决 map 的并发操作问题
Go - 使用 sync.Map 来解决 map 的并发操作问题
27 1
|
2月前
|
缓存 安全 测试技术
深入理解 go sync.Map - 基本原理
深入理解 go sync.Map - 基本原理
26 0
|
3月前
|
存储 Go 索引
GO 集合 map 使用总结
GO 集合 map 使用总结
32 0
|
3月前
|
安全 Go
Go语言map并发安全,互斥锁和读写锁谁更优?
Go并发编程中,`sync.Mutex`提供独占访问,适合读写操作均衡或写操作频繁的场景;`sync.RWMutex`允许多个读取者并行,适用于读多写少的情况。明智选择锁可提升程序性能和稳定性。示例展示了如何在操作map时使用这两种锁。
49 0
|
12月前
|
Go
Go 语言学习之map
Go 语言学习之map
49 0