【问题标题】:Typecasting structs with same underlying types具有相同基础类型的类型转换结构
【发布时间】:2020-12-19 08:09:27
【问题描述】:

对于基本类型,如果它们的底层类型相同,我们可以轻松地转换类型。但是具有相同内存布局的结构内部的字段不能轻松地从一种类型转换为另一种类型。 这个问题有一个proposal,不幸的是它被拒绝了。经过一个小时的谷歌搜索但没有运气,我来到这里寻求专家的帮助。

看下面的例子 :

package main

import (
    "fmt"
)

type Int int

type A struct {
    name string
    age  Int
}
type B struct {
    name string
    age  int
}

func main() {
    var a A= A{"Foo",21}
    var b B= B{"Bar", 21}
    fmt.Println(a,b,(A)(b))  //Error here as expected
}

尽管结构 A 和 B 具有相同的基础类型 struct { string,int},为什么我不能相互转换,因为 Int 的基础类型是 int。 除非底层类型不同,否则是否可以递归转换?

【问题讨论】:

  • Go 中没有类型转换。您正在谈论类型转换,而这种类型的转换完全被禁止。
  • 很抱歉。我来自 oop​​s 背景,这会导致命名约定出现问题。
  • “类型转换”根本不是 OOP 概念。事实上,它比 OOP 早了几十年。这也不是命名约定的问题。这是功能问题。 “类型大小写”描述了 Go 不支持的非常具体的行为。

标签: go casting type-conversion


【解决方案1】:

您不能仅仅因为语言规范不允许这样做。关于结构,如果Spec: Conversion:

,您只能从一种类型转换为另一种类型

在以下任何一种情况下,非常量值 x 都可以转换为类型 T

如果您完全确定结构的内存布局是相同的,您可以使用不安全的转换(使用包unsafe),如下所示:

var a A = A{"Foo", 21}
var b B

b = *(*B)(unsafe.Pointer(&a))
fmt.Println(a, b)

这将输出(在Go Playground 上尝试):

{Foo 21} {Foo 21}

但将其用作最后的手段。使用unsafe 您将失去编译时类型安全性和可移植性保证。例如。如果稍后您只修改其中一个结构,则上述代码将继续编译,即使它可能不再正确,编译器将无法通知您。

【讨论】:

  • 两张与上述情况类似的地图呢?即map[int][string]map[Int][string]
  • @chellathurai 地图是 Go 中的指针。如何在其内部结构中散列和使用这些值是实现细节。不要试图利用这种不安全的转换。尽量避免。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-19
  • 1970-01-01
  • 1970-01-01
  • 2018-10-24
  • 2020-08-26
  • 2019-08-18
  • 1970-01-01
相关资源
最近更新 更多