Go:关于结构体数组初始化的困惑

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

Go: Confusion about initialization of struct array

问题

我的困惑在以下代码片段中显示:

type Ex struct{
    A,B int
}

a := []Ex{Ex{1, 2}, Ex{3, 4}}     //这个我理解
b := []*Ex{&Ex{1, 2}, &Ex{3, 4}}   //这个我理解
c := []Ex{{1, 2}, {3, 4}}   //这个我不理解
d := []*Ex{{1, 2}, {3, 4}}   //这个我不理解
e := []*Ex{{1, 2}, &Ex{3, 4}}   //这个我不理解

最让我困惑的是c := []Ex{{1, 2}, {3, 4}}d := []*Ex{{1, 2}, {3, 4}}都可以正常工作。为什么{1, 2}既可以用来初始化对象,又可以用来初始化指针?

我在同样的问题上找到了答案:

> 如果<type>是一个指针,比如Ex或Track,它也会自动正确初始化:

但我希望有一个更深入的解释。是否有关于这个问题的官方文档?

我在C/C++方面有一定的基础,但对于Golang来说还是个新手。期待您的答案,提前感谢您。

英文:

My Confusion is shown in the following code snippet:

type Ex struct{
    A,B int
}

a := []Ex{Ex{1, 2}, Ex{3, 4}}     //it works, and I understand it
b := []*Ex{&amp;Ex{1, 2}, &amp;Ex{3, 4}}   //it works, and I understand it
c := []Ex{{1, 2}, {3, 4}}   //it works, and I don&#39;t understand it
d := []*Ex{{1, 2}, {3, 4}}   //it works, and I don&#39;t understand it
e := []*Ex{{1, 2}, &amp;Ex{3, 4}}   //it works, and I don&#39;t understand it

What puzzles me most is that both c := []Ex{{1, 2}, {3, 4}} and d := []*Ex{{1, 2}, {3, 4}} can work well. Why can{1, 2} be used to initialize both an object and a pointer?

I found the same question and someone answered:

> If <type> is a pointer like *Ex or *Track, it also automatically initializes correctly:

But I expect a deeper explanation. Is there any official documentation on this question?

I have a good C/C++ foundation, but a Golang novice. Looking forward to your answers, and I thank you in advance.

答案1

得分: 3

规范:复合字面量:

> 在数组、切片或映射类型 T 的复合字面量中,如果元素或映射键本身是复合字面量,并且其类型与 T 的元素或键类型相同,则可以省略相应的字面量类型。类似地,如果元素或键的类型是 *T,则当元素或键类型为 *T 时,可以省略 &amp;T

这解释了 cde 的情况。

c := []Ex{{1, 2}, {3, 4}}
d := []*Ex{{1, 2}, {3, 4}}
e := []*Ex{{1, 2}, &amp;Ex{3, 4}}

这些都是切片复合字面量,并且元素也是使用复合字面量提供的。因此,引用的部分适用。根据规范,您可以从元素的复合字面量(以及指针类型的情况下的 &amp; 运算符)中省略 T 的元素类型,此时它将从切片的元素类型(即“外部”复合字面量)中推断出来。

对于 c{1, 2} 被解释为复合字面量 Ex{1, 2}

对于 d{1, 2} 被解释为 &amp;Ex{1, 2},即取复合字面量 Ex{1, 2} 的地址。

对于 e,情况也是一样的(因为切片的元素类型相同)。

这是语言规范允许的复合字面量的简化。当从切片类型中已知元素类型时,为所有元素重复元素类型只是多余的,会使代码变得更长且更难阅读。

英文:

Spec: Composite literals:

> Within a composite literal of array, slice, or map type T, elements or map keys that are themselves composite literals may elide the respective literal type if it is identical to the element or key type of T. Similarly, elements or keys that are addresses of composite literals may elide the &amp;T when the element or key type is *T.

This explains the cases c, d and also e.

c := []Ex{{1, 2}, {3, 4}}
d := []*Ex{{1, 2}, {3, 4}}
e := []*Ex{{1, 2}, &amp;Ex{3, 4}}

All these are slice composite literals, and elements are also provided using composite literals. So the quoted part applies. As per the spec, you may omit the element type of T from the composite literals of the elements (and also the &amp; operator if it is a pointer type), in which case it is inferred from the element type of the slice (the "outer" composite literal).

In case of c, {1, 2} is interpreted as a composite literal Ex{1, 2}.

In case of d, {1, 2} is interpreted as &amp;Ex{1, 2}, namely taking the address of the composite literal Ex{1, 2}.

The same applies to case e (since the element type of the slice is the same).

This is a simplification of composite literals allowed by the language spec. Repeating the element type for all elements when it's known from the slice type is simply redundant, makes code longer and harder to read.

huangapple
  • 本文由 发表于 2021年8月21日 00:25:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/68865317.html
匿名

发表评论

匿名网友

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

确定