golang.org/x/sync/syncmap 被 struct 裹挟时 使用前为什么必须为每个键初始化 不然取值得到 nil

18 小时 17 分钟前
 zhouyin
package main

import (
	"fmt"
    syncmap "golang.org/x/sync/syncmap"
    
)
type Mark struct{
    Values syncmap.Map
}
var chanA chan int = make(chan int , 1)
 
func (m Mark)funa(){
 
    go func(){
        m.Values.Store("a",1)
        chanA<-1
    }()
    
    <-chanA
    
}
func main() {
var mk = new (Mark)
mk.Values.Store("a",0)
mk.funa()
va, p := mk.Values.Load("a")
fmt.Printf("%v:%v\n",va,p)
}

没有这行 mk.Values.Store("a",0) 永远取不到值 va 等于 nil p 等于 false

604 次点击
所在节点    Go 编程语言
7 条回复
zhouyin
18 小时 5 分钟前
需要把函数 funa 定义成指针接收者 就不需要初始化
```golang
func (m *Mark)funa(){

go func(){
m.Values.Store("a",1)
chanA<-1
}()

<-chanA
}
```
道理上想不通 值接收者如果设计到变量拷贝 那么在函数里赋值也没用
buffzty
17 小时 31 分钟前
加个*号
iseki
8 小时 9 分钟前
> A Map must not be copied after first use.
SGL
7 小时 19 分钟前
原文档内容:The zero Map is empty and ready for use. A Map must not be copied after first use.

Map 的定义如下:
```
type Map struct {
_ noCopy // 这个在源码中设置

m isync.HashTrieMap[any, any]
}
```

noCopy 类型的说明:
noCopy may be added to structs which must not be copied
after the first use.

See https://golang.org/issues/8005#issuecomment-190753527
for details.

Note that it must not be embedded, due to the Lock and Unlock methods.

如果你想问,进一步为什么 Map 是“noCopy"的,需要进一步研究 HashTrieMap 的结构:

```go
type HashTrieMap[K comparable, V any] struct {
inited atomic.Uint32
initMu Mutex
root atomic.Pointer[indirect[K, V]]
keyHash hashFunc
valEqual equalFunc
seed uintptr
}
```
可以看到里面封装了 Mutex ,先不管其他变量,至少 Mutex 是肯定不可拷贝的, 内部维护锁的状态( locked/unlocked )以及等待队列这些资源。
Ketteiron
6 小时 2 分钟前
值接收者会强制复制值,这应该知道吧。
简单来说,sync.Map, sync.Mutex 不能被复制,在你这个用例中,读和写是不同的 map 实例。
zhouyin
5 小时 28 分钟前
@SGL
对 struct 被拷贝导致 iniMutex 被拷贝了 具体业务代码里 多个 go routine 总共有好几次 Store 就只有一次 Store 的 Key 取出来是 nil 其他 Store 的 key 都有值 说明一开始有两个 goroutine 竞争初始化 导致第一个 goroutine 没 Store 完毕 被第二个 goroutine 初始化整个 map 了
zhouyin
5 小时 24 分钟前
@Ketteiron
原因是竞争初始化 Mutex 操作的是同一个 map 因为所有 struct 实例持有的都是 map 的指针地址

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1167432

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX