英文:
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{}}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论