微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么Go生成的protobuf文件包含互斥锁?

如何解决为什么Go生成的protobuf文件包含互斥锁?

在工作和生成protobuf存根的过程中,我偶然发现了这个有趣的问题。

每当我尝试按值复制消息的结构时,都会收到此警告:

调用state.world.script.HandleEvent复制锁值:王位/服务器/消息。PlayerDialogeStatus包含google.golang.org/protobuf/internal/impl.MessageState包含sync.Mutex复制锁

虽然我理解为什么按值复制互斥锁是错误,但我开始想知道为什么它们甚至都放在那儿。

因此,我的问题是:为什么go生成的protobuf文件包含放在消息结构上,尤其是在MessageState结构上的互斥锁?

或者:在生成的protobuf消息结构上找到的MessageState结构中放置互斥锁的目的是什么?

解决方法

impl.MessageState仅嵌入具体消息中,而不嵌入生成的实现原始消息的结构中。

它专门嵌入了三个pragmas)({}); /** added this: */ if ( typeof define === "function" && define.amd ) { define( "idb",[],function() { return { openDB:idb.openDB,deleteDB:idb.deleteDB,wrap:idb.wrap,unwrap:idb.unwrap} }); } NoUnkeyedLiteralsDoNotCompare

最后一个DoNotCopyDoNotCopy的零大小数组。唯一的目的是让sync.Mutex大声抱怨浅拷贝,如评论中所述:

DoNotCopy可以嵌入到结构中,以防止浅拷贝。 这不依赖于Go语言功能,而是一种特殊情况 在兽医检查器中。

所有摘要:go vet不应被复制,并且互斥锁仅用于复制。如果这样做,是因为您使用了错误的方式。

,

据我所知,Go protobuf API 包含 DoNotCopy 互斥锁的原因有以下三个:

  1. 维护者可能希望在未来以一种不适用于浅拷贝的方式更改内部表示。
  2. 将原子访问和非原子访问混合到同一内存理论上是不安全的。 protobuf 结构包含一个内部字段,通常使用原子访问读取和写入。对消息调用 msg.Marshal(),然后用 *msg = MyMessage{...} 覆盖它会混合原子访问和非原子访问。即使这适用于今天在 x86 上的实现,也不能保证这将适用于未来的其他系统。 (见a long Go issue about this)。
  3. 如果您对消息调用 ProtoReflect(),然后覆盖该消息,它将崩溃,因为 ProtoReflect() 结果依赖于内部反射指针 (original issue):
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())

这会崩溃:

protoreflectMessage.Interface()=seconds:1
panic: invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。