Golang结构类型转换
我试图弄清楚GO处理结构之间的类型转换。我读过的所有内容都告诉我,具有相同基础类型的类型被认为是兼容的,类型转换隐含地发生。如果是这样,为什么下面的代码不起作用? foo
和bar
实现fooi
接口,它们都添加了类型字符串的x
属性。但是,当我将类型bar
的结构传递给AcceptBarorfoo
,该期望类型foo
的结构时,我会得到类型的不匹配编译错误。
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
}
I'm trying to figure out how go handles type conversion between structs. Everything I have read tells me that types with the same underlying type are considered compatible and type conversion happens implicitly. If that is the case, why does the code below not work? Both Foo
and Bar
implement the FooI
interface, and they both add an x
property of type string. Yet, when I pass a struct of type Bar
to AcceptBarOrFoo
that expects a struct of type Foo
, I get a type mismatch compile error.
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
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
FOO的
X
与Bar的X
不同,因为在软件包边界之间,非出口标识符永远不会相等。修复导出 foo.foo.foo.foo.foo和bar.bar.bar.bar.bar.bar:使用foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo.foo或bar.bar作为参数值,foo.foo和bar.bar必须为可分配的参数类型。使用foo.foo作为参数类型是不起作用的,因为命名类型无法彼此分配。但是,当两种类型共享相同的基础类型时,命名类型可分配给未命名类型。将参数声明为未命名类型:
使用这些更改,以下代码编译:
在去操场
另一个选项是使用转换在以下代码中,foo.foo是通用类型,bar.bar被转换为foo.foo。
在Go Playground上运行示例。
注意:foo.foo和bar.bar必须具有上述工作的相同字段(字段名称已导出,以相同顺序为字段,字段,字段具有相同的类型)。
关于GO的一些注释:
Foo's
x
is different from Bar'sx
because non-exported identifiers are never equal across package boundaries. Fix by exporting the fields in foo.Foo and bar.Bar:To use a foo.Foo or bar.Bar as an argument value, a foo.Foo and bar.Bar must be assignable to the argument's type. It does not work to use foo.Foo as the argument type because named types are not assignable to each other. However, named types are assignable to unnamed types when the two types share the same underlying type. Declare the argument as an unnamed type:
With these changes, the following code compiles:
Run the example on the Go playground
Another option is to use a conversion to a common type. In the following code, foo.Foo is the common type and bar.Bar is converted to a foo.Foo.
Run the example on the Go playground.
Note: foo.Foo and bar.Bar must have the same fields for the above to work (field names are exported, fields in same order, fields have same types).
Some notes about Go:
您不能将一种混凝土类型转换为另一种混凝土类型。他们不一样。无法在GO中定义这种自动铸造。充其量,您可以定义一个接受
bar
的函数,并构建和返回新的foo
,其字段设置为与输入bar 。
那么您的来源是什么,但是 nothing 暗示了这一点,这根本不是真的。 Go做 no 隐含的转换,对任何事物。这是GO的大型,大声宣传的功能。给定
类型foo struct {a int}
和type bar struct {a int}
,您永远无法将类型bar
的对象分配给变量类型foo
。当该类型满足接口时,您 can can 从任何一个具体类型转换为接口类型。您的
AcceptBarorfoo
方法应接受接口类型(foo
和bar
满意),而不是混凝土类型。鉴于接口仅定义方法(不是成员),并且给定foo
或bar
具有任何方法,您的接口将是空接口,接口>接口{} < /代码>。传递的值将无目的,除非您以后将其转换回混凝土类型以访问其成员,但这并不是接口的目的。
You cannot convert one concrete type to another concrete type, ever. They are not the same. There is no way to define this type of automatic casting in Go. At best, you could define a function that accepts a
Bar
and builds and returns a newFoo
with its fields set to the same values as the inputBar
.It's unclear what your source for this is, but nothing would have ever stated or implied this, it's simply not true. Go does no implicit conversion, of anything. That's a big, loudly advertised feature of Go. Given
type Foo struct { a int }
andtype Bar struct { a int }
, you can never assign an object of typeBar
to a variable of typeFoo
.You can convert from either concrete type to an interface type, when the type satisfies the interface. Your
AcceptBarOrFoo
method should accept an interface type (which bothFoo
andBar
satisfy), not a concrete type. Given that interfaces only define methods (not members), and given neitherFoo
orBar
have any methods, your interface would be the empty interface,interface{}
. The value passed in would serve no purpose, except for you to later convert it back to a concrete type to access its members, but that's not really what interfaces are for.