使用var关键字初始化一个切片。

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

Initializing a slice by using the var keyword

问题

现在我正在学习Golang,但不理解Golang的一个情况。

这是使用简写方式声明和初始化切片的示例:

ilist := []int{1, 2, 3}  //这样可以工作

另一方面,如果我尝试使用var关键字声明和初始化切片,会出现错误:

var ilist [] int = {1, 2, 3, 4, 5}  //错误

如果只初始化一个变量(而不是切片),它可以正常工作:

var i int = 5 //可以正常工作

为什么Golang会表现出这样的行为,是否有特定的原因呢?

英文:

Nowadays I am learning Golang and don't understand a situation how Golang behaves.

Here it is a declaration and initialization of a slice by short hand:

ilist := []int{1, 2, 3}  //it works

on the other hand if I try to declare and initialize it with the var keyword, it gives an error:

var ilist [] int = {1, 2, 3, 4, 5}  //error

If I initialize just a variable (not a slice) it works fine:

var i int = 5 // works fine

Why does Golang behave like this, is there any specific reason?

答案1

得分: 8

这就是问题所在:你没有提供创建复合字面量所需的所有信息。请查看规范:复合字面量部分,了解所需的信息。

这个字面量:

{1, 2, 3, 4, 5}

这个字面量缺少了_类型_信息。它可以是[]int{}字面量的一部分,也可以是[]float32{}字面量的一部分,甚至可以是一个结构体字面量的一部分,其中结构体类型具有int字段(例如type Ints struct{a,b,c,d,e int})。

是的,在这个变量声明中:

var ilist [] int = {1, 2, 3, 4, 5}  //error

只有[]int{}字面量是有意义的,但Go语言不是这样工作的。仅仅因为只有一个类型可以使这行代码有效,并不意味着你可以省略它。

请注意,如果类型可以从初始化表达式中推断出来,你可以省略声明中的类型,因此这两种形式都是有效的:

var ilist1 []int = []int{1, 2, 3, 4, 5}

var ilist2 = []int{1, 2, 3, 4, 5}

但是,{1, 2, 3, 4, 5}的类型将是模棱两可的(如果它是有效的)。

还要注意,如果你为[][]int这样的类型指定复合字面量,你可以省略元素的(子)字面量中的类型,因为它可以从复合字面量的类型中推断出来,所以这也是有效的:

var iilist = [][]int{
	{1, 2, 3},
	{4, 5, 6},
}

对于映射字面量也是如此,这是有效的(在Go 1.5中添加):

var imap = map[int][]int{
	1: {1, 2, 3},
	2: {4, 5, 6},
}

Go Playground上尝试一下吧。

英文:

> i give the all information to create composite literal

That's the thing: you did not give all the required information to create a composite literal. Check out the Spec: Composite literals section to see what is required.

This literal:

{1, 2, 3, 4, 5}

This literal misses the type information. It could be a part of an []int{} literal, it could be a part of a []float32{} literal, it could even be a part of a struct literal, where the struct type has int fields (e.g. type Ints struct{a,b,c,d,e int}).

Yes, in this variable declaration

var ilist [] int = {1, 2, 3, 4, 5}  //error

Only []int{} literal makes sense, but that is not how Go works. Just because there is only a single type that would make this line valid, it doesn't mean you can omit it.

Note that however you may omit the type from the declaration if it can be inferred from the initialization expression, so both of these forms are valid:

var ilist1 []int = []int{1, 2, 3, 4, 5}

var ilist2 = []int{1, 2, 3, 4, 5}

But the type of {1, 2, 3, 4, 5} would be ambiguous (if it would be valid).

Also note that if you're specifying a composite literal for a type like [][]int, you may omit the type from the (sub)literals of the elements, because it is known from the type of the composite literal, so this is also valid:

var iilist = [][]int{
	{1, 2, 3},
	{4, 5, 6},
}

Same goes for map literals, this is valid (was added in Go 1.5):

var imap = map[int][]int{
	1: {1, 2, 3},
	2: {4, 5, 6},
}

Try these on the Go Playground.

答案2

得分: 1

在Go语言中,不同的名称代表不同的类型。因此,当你定义一个变量时,你必须指定它的类型。这意味着你需要确保你的赋值是一个具体的类型。"{}"可以是多种类型,所以编译器无法找到"ilist"类型。顺便说一下,一些朋友们提出了一个关于Go语言别名声明的提案的讨论。

英文:

In go, different names mean different types. So when you define a variable, you must specify its type. That means, you need make sure that your assignment is a concrete type. "{}" can be more than one type, so the compilier can not find ilist type. BTW, some friends rise a discussion about Proposal: Alias declarations for Go

huangapple
  • 本文由 发表于 2017年5月29日 19:06:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/44241014.html
匿名

发表评论

匿名网友

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

确定