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了;

目录
相关文章
|
18天前
|
Go
go语言中遍历映射(map)
go语言中遍历映射(map)
37 8
|
10天前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
24 12
|
14天前
|
存储 Go
go语言 遍历映射(map)
go语言 遍历映射(map)
27 2
|
21天前
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
29 1
|
27天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
2月前
|
Java 大数据 Go
Go语言:高效并发的编程新星
【10月更文挑战第21】Go语言:高效并发的编程新星
51 7
|
1月前
|
并行计算 安全 Go
Go语言的并发特性
【10月更文挑战第26天】Go语言的并发特性
16 1
|
2月前
|
存储 安全 Java
Map的并发处理,助你提升编程效率,代码更优雅高效。
【10月更文挑战第19天】Map使用技巧大公开:从选择合适的Map实现(如HashMap、TreeMap、LinkedHashMap)到利用Map的初始化、使用Map.Entry遍历、运用computeIfAbsent和computeIfPresent方法,再到Map的并发处理,助你提升编程效率,代码更优雅高效。
32 2
|
2月前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
2月前
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。