首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Golang结构型转换

Golang结构型转换
EN

Stack Overflow用户
提问于 2022-06-21 18:43:06
回答 2查看 337关注 0票数 -2

我试图弄清楚go如何处理结构之间的类型转换。我所读到的一切都告诉我,具有相同基础类型的类型被认为是兼容的,并且类型转换是隐式的。如果是这样的话,为什么下面的代码不起作用?FooBar都实现了FooI接口,它们都添加了一个string类型的x属性。然而,当我将Bar类型的结构传递给期望类型为Foo的结构的AcceptBarOrFoo时,我会得到一个类型不匹配的编译错误。

围棋游乐场

代码语言:javascript
复制
package main

import (
    "play.ground/bar"
    "play.ground/foo"
)

func main() {
    AcceptBarOrFoo(bar.Bar{})
}

func AcceptBarOrFoo(foo.Foo) interface{} {
    return nil
}

// -- iface/iface.go --

package iface

type FooI interface {
    a() string
    b(int) int
}
// -- foo/foo.go --
package foo

import (
    "play.ground/iface"
)

type Foo struct {
    iface.FooI
    x string
}
// -- bar/bar.go --
package bar

import (
    "play.ground/iface"
)

type Bar struct {
    iface.FooI
    x string
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-06-21 19:01:57

Foo的x不同于Bar的x,因为非导出标识符在跨包边界时永远不会相等。通过出口修复foo.Foo和bar.Bar中的字段:

代码语言:javascript
复制
type Foo struct {
    iface.FooI
    X string // <-- start with capital letter to export
}

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

代码语言:javascript
复制
func AcceptBarOrFoo(struct {
    iface.FooI
    X string
}) interface{} {
    return nil
}

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

代码语言:javascript
复制
AcceptBarOrFoo(bar.Bar{})
AcceptBarOrFoo(foo.Foo{})

在围棋操场上运行示例

另一种选择是对公共类型使用转换。在下面的代码中,foo.Foo是常见类型,bar.Bar被转换为foo.Foo。

代码语言:javascript
复制
func Accept(foo.Foo) interface{} {
    return nil
}

... 

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

在围棋操场上运行示例

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

关于Go的一些注释:

  • 从一种具体类型到另一种具体类型都有转换
  • Go因表达式中没有隐式转换而闻名,但在某些分配场景中存在隐式转换。
票数 3
EN

Stack Overflow用户

发布于 2022-06-21 18:45:37

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

我所读到的一切都告诉我,如果底层类型是相同的,那么高阶类型被认为是兼容的,并且类型转换是隐式发生的。

目前还不清楚你的消息来源是什么,但没有人会说或暗示这一点,这根本不是真的。Go不做任何隐式转换。这是一个巨大的,大声宣传的特点的围棋。给定type Foo struct { a int }type Bar struct { a int },您永远不能将类型为Bar的对象分配给类型为Foo的变量。

当类型满足接口时,可以将任何具体类型转换为接口类型。您的AcceptBarOrFoo方法应该接受一个接口类型( FooBar都满足它),而不是具体类型。如果接口只定义方法(而不是成员),并且FooBar都没有任何方法,那么您的接口将是空接口interface{}。传入的值没有任何用途,只是稍后将其转换回一个具体类型以访问其成员,但这并不是接口的真正目的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72705723

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档