为了账号安全,请及时绑定邮箱和手机立即绑定

Golang 结构类型转换

Golang 结构类型转换

Go
摇曳的蔷薇 2022-12-26 10:35:58
我试图弄清楚 go 如何处理结构之间的类型转换。我读过的所有内容都告诉我,具有相同底层类型的类型被认为是兼容的,并且类型转换是隐式发生的。如果是这样,为什么下面的代码不起作用?Foo和都Bar实现了FooI接口,并且都添加了一个x字符串类型的属性。然而,当我将一个类型结构传递给需要类型Bar结构AcceptBarOrFoo的结构时Foo,我得到了一个类型不匹配的编译错误。去游乐场package mainimport (    "play.ground/bar"    "play.ground/foo")func main() {    AcceptBarOrFoo(bar.Bar{})}func AcceptBarOrFoo(foo.Foo) interface{} {    return nil}// -- iface/iface.go --package ifacetype FooI interface {    a() string    b(int) int}// -- foo/foo.go --package fooimport (    "play.ground/iface")type Foo struct {    iface.FooI    x string}// -- bar/bar.go --package barimport (    "play.ground/iface")type Bar struct {    iface.FooI    x string}
查看完整描述

2 回答

?
狐的传说

TA贡献1804条经验 获得超3个赞

您永远无法将一种具体类型转换为另一种具体类型。它们不一样。在 Go 中无法定义这种类型的自动转换。充其量,您可以定义一个函数,该函数接受 aBar并构建并返回一个新Foo的,其字段设置为与输入相同的值Bar

我读过的所有内容都告诉我,如果底层类型相同,则高阶类型被认为是兼容的,类型转换会隐式发生

目前还不清楚你的来源是什么,但没有任何东西会说明或暗示这一点,这根本不是真的。Go 不进行任何隐式转换。这是 Go 的一个大声宣传的功能。鉴于type Foo struct { a int }and type Bar struct { a int },您永远不能将类型的对象分配给类型Bar的变量Foo

当类型满足接口时,您可以从任一具体类型转换为接口类型。您的AcceptBarOrFoo方法应该接受接口类型(两者都Foo满足Bar),而不是具体类型。鉴于接口只定义方法(不是成员),并且既没有方法FooBar没有任何方法,您的接口将是空接口,interface{}. 传入的值没有任何用处,除非您稍后将其转换回具体类型以访问其成员,但这并不是接口的真正用途。


查看完整回答
反对 回复 2022-12-26
?
慕斯王

TA贡献1864条经验 获得超2个赞

Foox与 Bar 不同,x因为非导出标识符在包边界之间永远不相等。通过导出foo.Foo 和 bar.Bar 中的字段来修复:


type Foo struct {

    iface.FooI

    X string // <-- start with capital letter to export

}

要使用 foo.Foo 或 bar.Bar 作为参数值,foo.Foo 和 bar.Bar 必须可分配给参数的类型。使用 foo.Foo 作为参数类型是行不通的,因为命名类型不能相互分配。但是,当两种类型共享相同的基础类型时,命名类型可分配给未命名类型。将参数声明为未命名类型:


func AcceptBarOrFoo(struct {

    iface.FooI

    X string

}) interface{} {

    return nil

}

通过这些更改,可以编译以下代码:


AcceptBarOrFoo(bar.Bar{})

AcceptBarOrFoo(foo.Foo{})

在 Go 操场上运行示例


另一种选择是使用到通用类型的转换。在下面的代码中,foo.Foo 是普通类型,bar.Bar 被转换为 foo.Foo。


func Accept(foo.Foo) interface{} {

    return nil

}


... 


Accept(foo.Foo{})

Accept(foo.Foo(bar.Bar{}))

在 Go playground 上运行示例。


注意:foo.Foo 和 bar.Bar 必须具有相同的字段才能使上述工作正常(导出字段名称,字段顺序相同,字段类型相同)。


关于 Go 的一些注意事项:


存在从一种具体类型到另一种具体类型的转换。

Go 以表达式中没有隐式转换而闻名,但在某些赋值场景中存在隐式转换。


查看完整回答
反对 回复 2022-12-26
  • 2 回答
  • 0 关注
  • 161 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号