英文:
Embedded structs opposed situation
问题
我们有3种类型:
type A struct {
B
C
}
type B struct {
x int
y string
}
type C struct {
z string
}
由于匿名字段的字段和方法是提升的,我们可以像这样访问A
中匿名字段B
的字段:
var a A
a.x = 0
很明显,类型B
和C
嵌入在A
中,所以我们期望A
等价于:
type D struct {
x int
y string
z string
}
你期望看到什么?
我们期望可以像这样编写类型为A
的复合字面量:
a := A{x: 2}
你看到了什么?
这个编译错误:
unknown field 'x' in struct literal of type A
我们的问题
为什么不能像对类型D
那样以这种方式编写A
的复合字面量?
https://play.golang.org/p/uM5JkO5EvE
英文:
We have 3 types:
type A struct {
B
C
}
type B struct {
x int
y string
}
type C struct {
z string
}
because of how fields and methods of an anonymous field are promoted, we can access fields of the anonymous field B
in A
like
var a A
a.x = 0
It is very obvious that type B
& C
embed in A
, so we expect A
to be equivalent to:
type D struct {
x int
y string
z string
}
What did you expect to see?
We expect that we can write composite literals of type A
like that:
a := A{x: 2}
What did you see instead?
This compile error:
unknown field 'x' in struct literal of type A
Our Question
Why isn't it possible to write composite literals for A
in that way, as it would for the type D
?
答案1
得分: 2
Rob 'Commander' Pike在这里解释了这个问题(https://groups.google.com/d/msg/golang-nuts/LUF4LpXVU8g/likbOsXTXvwJ)。
他在那里写道:
可能有一天会这样,但目前来说,提供更多信息的要求对于数据类型的变化更具有鲁棒性。
如果我理解和解释正确的话,这基本上是为了你的安全考虑。如果结构体定义与复合字面量不匹配,编译器会报错。
在你的例子中,A
的定义可能会在以后的更改中(比如很久以后,比如几年后)变成:
type A struct {
x int
y string
z string
}
但是,x
、y
和z
可能代表的东西与之前不同,因此最好是你必须更改所有的字面量,以免得到某种悄悄损坏的数据。
这是一个有意的选择。语言规范中的措辞是:
提升的字段就像结构体的普通字段一样,只是不能在结构体的复合字面量中用作字段名。
因此,你可以像使用A
的字段x
一样使用字段B
,除了复合字面量之外。
而类型
type A struct {
B
C
}
和
type A struct {
x int
y string
z string
}
确实是两个不同的东西。前者包含两个字段B
和C
,后者包含三个字段x
、y
和z
。前者只是一些语法糖,用于使用简写访问字段B
的字段x
。因此,如果a
是前者类型A
的变量,a.x
是访问a.B.x
的语法糖。
英文:
Rob 'Commander' Pike explained it here.
He wrote there:
> It might one day, but as it stands the requirement to provide more
> information is more robust against changes in the data types.
If I understand and interpret that correctly, it is basically a safety measure for you. The compiler will yell at you, if the struct definition doesn't match the composite literal.
In your example, the definition of A
might change -- in a later change (as in much later, like years) -- to:
type A struct {
x int
y string
z string
}
later, but x
, y
and z
might represent different things than before and therefore it is better, that you have to change all your literals to
not get silently corrupt data of some kind.
That is a deliberate choice. The wording in the language specification is:
> Promoted fields act like ordinary fields of a struct except that they cannot be used as field names in composite literals of the struct.
So you can use the field x
of the field B
as if it was a field of A
except for composite literals.
And the types
type A struct {
B
C
}
and
type A struct {
x int
y string
z string
}
really are two different things. The former contains two fields B
and C
, and the latter three fields x
, y
and z
. The former just has some syntactic sugar to access the field x
of the field B
with a shorthand. So if a
is a variable of the former type A
, a.x
is syntactic sugar for a.B.x
.
答案2
得分: 1
你在初始化A
时需要明确使用B
(和C
):
a = A{B{x: 2}, C{}}
英文:
You need to explicitly use B
(and C
) when initializing A
:
a = A{B{x: 2}, C{}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论