【问题标题】:convert TypeA to TypeB where the underlying field types are the same将 Type 转换为 Type B,其中基础字段类型相同
【发布时间】:2016-12-19 19:25:21
【问题描述】:

在我的游乐场代码中,有 2 种类型共享非常相似的字段定义,就像这样,

type Int64 int64

type TA struct {
    A Int64
    B string
}

type TB struct {
    A int64
    B string
}

如何以最少的代码和性能成本在两者之间进行转换?

https://play.golang.org/p/VFERyT-RgK

附言经测试,仅当 TA.A 与 TB.A 的类型完全相同时,TA(some_tb_value) 与上述情况类似。但是,使基础类型 (Int64->int64) 完全相同并不适合我需要的用例。

附言使用某些协议 (json) 序列化 some_tb_value 并反序列化回 TA 类型的指针是可能的,但对于关键路径的使用来说它可能太重了

【问题讨论】:

  • Assign struct with another struct的相关/可能重复
  • @icza 感谢您的指出。反映是可能的解决方案。我正在寻找其他用于大量使用的高性能方法。

标签: go casting converter


【解决方案1】:

由于它们是不同的结构类型,所以不能转换它们。

一种解决方案是使用反射(reflect 包)来复制字段。

由于它们具有相同的内存布局,另一个解决方案是使用包unsafe

func main() {
    var a TA = TA{1, "I'm TA"}
    var b TB = TB{2, "I'm TB"}
    fmt.Println(TA2TB(&a), TB2TA(&b))
}

func TA2TB(a *TA) *TB {
    return (*TB)(unsafe.Pointer(a))
}
func TB2TA(b *TB) *TA {
    return (*TA)(unsafe.Pointer(b))
}

输出(在Go Playground 上试试):

&{1 I'm TA} &{2 I'm TB}

但要知道,使用unsafe 会丢失所有类型安全检查。如果将来类型被修改,代码将继续编译,但在运行时可能会出现神秘错误(如果幸运的话,运行时会出现恐慌,在最坏的情况下会出现无声的行为不端,在最坏的情况下会完全崩溃)。

最好是重构你的代码并使用相同的底层类型,这样你就可以简单地做一个类型conversion

【讨论】:

  • 同意重构。其背后的真实案例是我试图将原生 Go 类型(使用许多方法)适合类型只是原始类型的 go-swagger,我可能真的需要这种类型来转换。 (仅提供背景)
  • 嗨@icza,为了使这个解决方案完整,知道如何系统地验证两种类型共享完全相同的内存布局吗?在任何严肃的部署中使用这个强大的演员之前,人们可能可以离线/在操场上运行它以验证正确性。
猜你喜欢
  • 2015-09-24
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
  • 2016-10-29
  • 1970-01-01
  • 2020-07-05
相关资源
最近更新 更多