英文:
Why can't a struct be converted to an embedded type
问题
package main
type Inner struct {
x int
}
type Outer struct {
Inner
}
func main() {
x := Inner{1}
y := (Outer)(x) // 无法将类型为 Inner 的 x 转换为类型 Outer
}
Go 语言规范中的 转换 部分指出:
> 非常量值 x 可以在以下任何情况下转换为类型 T:
> ...
> 忽略结构体标签(见下文),x 的类型和 T 具有相同的基础类型。
> ...
而 类型标识 部分则说:
> 如果两个结构体类型具有相同的字段序列,并且相应的字段具有相同的名称、相同的类型和相同的标签,则它们是相同的。
据我理解,Inner
和 Outer
都有一个名为 x
的字段,类型为 int
。那么为什么我不能将 Outer
转换为 Inner
呢?
我最终弄清楚了可以使用 x.Inner
,但这花费了我一些时间,所以我很好奇为什么(在我看来)更明显的方法是不允许的。
英文:
package main
type Inner struct {
x int
}
type Outer struct {
Inner
}
func main() {
x := Inner{1}
y := (Outer)(x) // cannot convert x (type Inner) to type Outer
}
The go spec section on conversions claims that
> A non-constant value x can be converted to type T in any of these cases:
> ...
> Ignoring struct tags (see below), x's type and T have identical underlying types.
> ...
The section on type identity says:
> Two struct types are identical if they have the same sequence of fields, and if corresponding fields have the same names, and identical types, and identical tags.
It is my understanding that both Inner
and Outer
have a single field x
which is an int
. So why can't I convert an Outer
to an Inner
?
I eventually figured out that I can use x.Inner
, but it took me a while, so I'm curious why the (in my opinion) more obvious approach is disallowed.
答案1
得分: 8
Outer
没有字段x
。它有一个字段Inner
,Inner
有一个字段x
。当访问.x
时,选择器(.
)会自动从最浅的深度提升嵌入字段,直到找到x
为止。
请参阅Selectors的规范。
英文:
Outer
does not have a field x
. It has a field Inner
, which has a field x
. When accessing .x
, the selector (.
) will automatically promote an embedded field from the shallowest depth where there is such an x
.
See the spec on Selectors
答案2
得分: 1
以下代码片段用于支持JimB的答案 - Inner
和Outer
不共享相同的字段序列,因此不符合转换条件。
它将帮助您直观地看到Inner
和Outer
类型之间的区别:
package main
import "fmt"
type inner struct {
x int
}
type outer struct {
inner
}
func main() {
in := inner{x: 1}
fmt.Printf("inner: %+v\n", in)
fmt.Println()
out := outer{in}
fmt.Printf("outer: %+v\n", out)
}
英文:
The following code snippet is used to support JimB's answer - Inner
and Outer
doesn't share the same sequence of fields and therefore aren't eligible for conversion.
It will help you to literally see the difference between the Inner
and Outer
types:
package main
import "fmt"
type inner struct {
x int
}
type outer struct {
inner
}
func main() {
in := inner{x: 1}
fmt.Printf("inner: %+v\n", in)
fmt.Println()
out := outer{in}
fmt.Printf("outer: %+v\n", out)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论