【发布时间】:2016-01-05 17:55:30
【问题描述】:
考虑两种结构相同但标签不同的类型:
type Foo struct {
Id int64 `json:"-"`
}
type Bar struct {
Id int64 `json:"id"`
}
不幸的是,当两种类型的标签不同时,Go 的成语禁止在两种类型之间进行转换,这是有充分理由的。但是我仍然需要能够控制序列化为 JSON 的数据并且不想使用interface{} 类型。
我的问题是,使用 golang 的 unsafe.Pointer 在结构相同(但不是标签)的两种类型之间执行强制转换有多安全?比如:
rf := &Foo{1}
rb := (*Bar)(unsafe.Pointer(rf))
是否有任何可能引发恐慌,可能是因为在内部,由于标签不同,两种类型中的每一种的数据都略有不同或是与实际类型数据和每个类型中的数据分开保存的标签信息在结构上是否相同?
编辑
为了澄清,我应该提一下,尽管上面提供的示例使用了单字段结构,但问题实际上是关于包含多个字段的结构类型。
【问题讨论】:
-
为什么不手动(逐个字段)或通过反射字段将 struct Foo 复制到 struct Bar 中?标签不同的原因是什么?
-
@elithrar:我试图避免手动复制和使用 interface{} 或反射。标签不同,因为我正在处理的应用程序具有不同的用户类型,并且可能某些结构字段不应该对所有用户类型都可用。
-
@miguelg 如果它们真的相同,我想没关系,因为标签被保存为类型信息的一部分,而不是对象的数据。当然,它是不安全的 :)
-
如果某些结构字段不适用,请根据需要选择性地将第二个结构嵌入到您的用户结构中。使用 Marshal/Unmarshal 逻辑或
omitempty标签来选择在离开时如何省略该结构nil。 -
@Not_a_Golfer 我认为
unsafe的意思是“程序员保证安全”而不是“实际上不安全”。例如,通过 unsafe 将f64转换为uint64的位在任何合理的语言实现中实际上都不安全。这就是为什么math这样做的原因。当然,有时它实际上是不安全的,因为它依赖于短暂的操作系统或编译器细节,但这只是因为unsafe允许你做潜在的不安全事情,并不是说用 unsafe 做的任何事情本质上都是坏事。
标签: go