猿问

只有标签不同的相同结构类型之间的不安全转换

考虑两种结构相同但标签不同的类型:


type Foo struct {

  Id int64 `json:"-"`

}


type Bar struct {

  Id int64 `json:"id"`

}

不幸的是,当两种类型的标签不同并且有充分的理由时,Go 的习惯用法禁止在两种类型之间进行转换。但是我仍然需要能够控制序列化为 JSON 并且不想使用interface{}类型的数据。


我的问题是,使用 golangunsafe.Pointer在结构相同(但不是标签)的两种类型之间执行强制转换有多安全?就像是:


rf := &Foo{1}

rb := (*Bar)(unsafe.Pointer(rf))

是否有任何在所有的恐慌,也许随之而来的机会,因为内部各两种类型的数据被保持略有不同,由于标签的不同或即将标签每种类型的与实际的数据类型和数据分别举行的信息结构相同吗?


编辑


为了澄清起见,我应该提到,尽管上面提供的示例使用单字段结构,但问题实际上是关于包含多个字段的结构类型。


慕慕森
浏览 172回答 2
2回答

潇潇雨雨

严格来说,这并不安全。原因是规范的相关部分没有为结构体的内存布局提供任何指导。它不保证内存中的字段排序、打包或对齐。理论上,编译器可以根据优化信息,决定两个看似相同的结构体根据它们的使用情况以不同的方式表示。这甚至可能是一个 Heisenbug,其中违规优化不会在go test构建中发生。实际上,这在任何真正的编译器中都不太可能发生,您可能可以安全地做到这一点。对于像您提供的字段结构这样的字段结构尤其如此。不过,在执行此操作之前,您可能应该通过分析来确保复制是不够的。

元芳怎么了

不幸的是,当两种类型的标签不同并且有充分的理由时,Go 的习惯用法禁止在两种类型之间进行转换Go 1.8(目前处于测试阶段)的发行说明似乎表明此限制现已解除:语言的变化当将值从一种结构类型显式转换为另一种结构类型时,从 Go 1.8 开始,这些标记将被忽略。因此,两个仅标签不同的结构可以从一个转换为另一个:func example() {    type T1 struct {        X int `json:"foo"`    }    type T2 struct {        X int `json:"bar"`    }    var v1 T1    var v2 T2    v1 = T1(v2) // now legal}
随时随地看视频慕课网APP

相关分类

Go
我要回答