对于基本类型,如果它们的底层类型相同,我们可以轻松地转换类型。但是具有相同内存布局的结构体内部的字段不能轻松地从一种类型转换为另一种类型。 对于这个问题有一个提案,不幸的是它被拒绝了。经过一个小时的谷歌搜索但没有运气,我来到这里寻求专家的帮助。
看下面的例子 :
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
}
尽管 struct A 和 B 具有相同的底层类型
struct { string,int}
,为什么我不能相互转换,因为 Int
的底层类型是 int
。
除非底层类型不同,否则是否可以递归转换?
你不能这样做,只是因为语言规范不允许。关于结构,您只能从一种类型转换为另一种类型,如果 Spec: Conversion:
在以下任何情况下,非常量值
都可以转换为类型x
:T
- ...
- 忽略结构标签(见下文),
的类型和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
你会失去编译时类型安全性和可移植性保证。例如。如果稍后您只修改其中一个结构体,则上述代码将继续编译,即使它可能不再正确,并且编译器将无法通知您这一点。
你的程序中不允许这种转换的原因:
type A B // this isn't a type alias
在此示例中,A 与 B 具有相同的二进制结构。 然而 A 根本不继承与 B 相关的任何方法!
我们假设这段代码:
func (b B) method()
以下内容有效
var b B
b.method()
这是无效的
var a A
a.method() // for type A no method of name 'method' exists
规范假设 A 和 B 确实可能非常不同。所以不允许类型转换。
您可以使用这样的类型别名:
type Int = int
这是一个 Playground 链接。