这个错误是因为在并发环境下同时读写同一个切片导致的。切片在Go中不是并发安全的数据结构,当多个goroutine同时修改同一个切片时,会触发数据竞争检测。
错误信息显示:
concurrent slice writes:并发切片写入
fatal error: concurrent map writes:并发map写入(如果代码中还有map操作)
解决方案:使用互斥锁保护切片操作
package main
import (
"fmt"
"sync"
)
type SafeSlice struct {
mu sync.RWMutex
items []int
}
func (s *SafeSlice) Append(item int) {
s.mu.Lock()
defer s.mu.Unlock()
s.items = append(s.items, item)
}
func (s *SafeSlice) Get(index int) int {
s.mu.RLock()
defer s.mu.RUnlock()
return s.items[index]
}
func main() {
var wg sync.WaitGroup
safeSlice := &SafeSlice{}
// 启动多个goroutine并发写入
for i := 0; i < 10; i++ {
wg.Add(1)
go func(val int) {
defer wg.Done()
safeSlice.Append(val)
}(i)
}
wg.Wait()
fmt.Println("Slice length:", len(safeSlice.items))
}
如果还需要并发安全的map,使用sync.Map:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
var m sync.Map
// 并发写入map
for i := 0; i < 10; i++ {
wg.Add(1)
go func(key int) {
defer wg.Done()
m.Store(key, fmt.Sprintf("value%d", key))
}(i)
}
wg.Wait()
// 读取map
m.Range(func(key, value interface{}) bool {
fmt.Printf("Key: %v, Value: %v\n", key, value)
return true
})
}
如果只需要简单的切片保护,可以直接使用sync.Mutex:
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
var slice []int
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(val int) {
defer wg.Done()
mu.Lock()
slice = append(slice, val)
mu.Unlock()
}(i)
}
wg.Wait()
fmt.Println("Final slice:", slice)
}
选择哪种方案取决于具体需求:
- 如果只有切片操作,使用
sync.Mutex或封装成结构体
- 如果同时有map操作,使用
sync.Map替代普通map
- 如果读写比例高,考虑使用
sync.RWMutex提高读取性能