嵌套结构的相反情况

huangapple go评论95阅读模式
英文:

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

很明显,类型BC嵌入在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?

https://play.golang.org/p/uM5JkO5EvE

答案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
}

但是,xyz可能代表的东西与之前不同,因此最好是你必须更改所有的字面量,以免得到某种悄悄损坏的数据。

这是一个有意的选择。语言规范中的措辞是:

提升的字段就像结构体的普通字段一样,只是不能在结构体的复合字面量中用作字段名。

因此,你可以像使用A的字段x一样使用字段B,除了复合字面量之外。

而类型

type A struct {
    B
    C
}

type A struct {
    x int
    y string
    z string
}

确实是两个不同的东西。前者包含两个字段BC,后者包含三个字段xyz。前者只是一些语法糖,用于使用简写访问字段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{}}

huangapple
  • 本文由 发表于 2017年7月11日 01:24:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/45018199.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定