我试图弄清楚go如何处理结构之间的类型转换。我所读到的一切都告诉我,具有相同基础类型的类型被认为是兼容的,并且类型转换是隐式的。如果是这样的话,为什么下面的代码不起作用?Foo和Bar都实现了FooI接口,它们都添加了一个string类型的x属性。然而,当我将Bar类型的结构传递给期望类型为Foo的结构的AcceptBarOrFoo时,我会得到一个类型不匹配的编译错误。
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
}发布于 2022-06-21 19:01:57
Foo的x不同于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{})另一种选择是对公共类型使用转换。在下面的代码中,foo.Foo是常见类型,bar.Bar被转换为foo.Foo。
func Accept(foo.Foo) interface{} {
return nil
}
...
Accept(foo.Foo{})
Accept(foo.Foo(bar.Bar{}))注意: foo.Foo和bar.Bar必须有相同的字段才能工作(字段名导出,字段按相同的顺序,字段具有相同的类型)。
关于Go的一些注释:
发布于 2022-06-21 18:45:37
您永远不能将一种具体类型转换为另一种具体类型。他们不一样。在Go中无法定义这种类型的自动浇铸。充其量,您可以定义一个函数,该函数接受Bar并构建和返回一个新的Foo,其字段设置为与输入Bar相同的值。
我所读到的一切都告诉我,如果底层类型是相同的,那么高阶类型被认为是兼容的,并且类型转换是隐式发生的。
目前还不清楚你的消息来源是什么,但没有人会说或暗示这一点,这根本不是真的。Go不做任何的隐式转换。这是一个巨大的,大声宣传的特点的围棋。给定type Foo struct { a int }和type Bar struct { a int },您永远不能将类型为Bar的对象分配给类型为Foo的变量。
当类型满足接口时,可以将任何具体类型转换为接口类型。您的AcceptBarOrFoo方法应该接受一个接口类型( Foo和Bar都满足它),而不是具体类型。如果接口只定义方法(而不是成员),并且Foo或Bar都没有任何方法,那么您的接口将是空接口interface{}。传入的值没有任何用途,只是稍后将其转换回一个具体类型以访问其成员,但这并不是接口的真正目的。
https://stackoverflow.com/questions/72705723
复制相似问题