Nit*_*kin 17 mutex go protocol-buffers
在 Go 中工作和生成 protobuf 存根时,我偶然发现了这个有趣的问题。
每当我尝试按值复制消息的结构时,都会收到此警告:
调用 state.world.script.HandleEvent 复制锁值:王座/服务器/messages.PlayerDialogeStatus 包含 google.golang.org/protobuf/internal/impl.MessageState 包含 sync.Mutex copylocks
虽然我明白为什么按值复制互斥锁是错误的,但我开始想知道为什么他们甚至在那里。
因此我的问题是:为什么 go 生成的 protobuf 文件包含放置在消息结构上的互斥锁,特别是在MessageState结构上?
或者:MessageState在生成的 protobuf 消息结构上找到的结构中放置的互斥锁的目标是什么?
Mar*_*arc 12
所述impl.MessageState被嵌入在混凝土消息只,而不是在实现一种原消息所生成的结构。
它特别嵌入了三个编译指示:NoUnkeyedLiterals,DoNotCompare,和DoNotCopy。
最后一个,DoNotCopy是一个零大小的sync.Mutex. 唯一的目的是go vet大声抱怨浅拷贝,如评论中所述:
DoNotCopy 可以嵌入到结构中以帮助防止浅拷贝。这不依赖于 Go 语言功能,而是 vet checker 中的一个特殊情况。
:它的摘要中的所有impl.MessageState是不应该被复制和互斥体仅在那里捕捉复制。如果你这样做,那是因为你使用了错误的方法。
Eva*_*nes 12
据我所知,Go protobuf API 包含DoNotCopy互斥体有以下三个原因:
msg.Marshal()消息,然后使用*msg = MyMessage{...}混合原子和非原子访问来覆盖它。即使这适用于当前 x86 上的实现,也不能保证将来也适用于其他系统。(参见关于此的一个很长的 Go 问题)。ProtoReflect()消息,然后覆盖该消息,它将崩溃,因为 ProtoReflect() 结果依赖于内部反射指针(原始问题):d := &durationpb.Duration{Seconds: 1}
protoreflectMessage := d.ProtoReflect()
fmt.Printf("protoreflectMessage.Interface()=%v\n", protoreflectMessage.Interface())
*d = durationpb.Duration{Seconds: 2}
fmt.Printf("protoreflectMessage.Interface()=%v\n", protoreflectMessage.Interface())
Run Code Online (Sandbox Code Playgroud)
这会崩溃:
protoreflectMessage.Interface()=seconds:1
panic: invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct
Run Code Online (Sandbox Code Playgroud)