在Go语言中动态初始化数组大小

104

我试着用Go语言写一个小应用程序,从标准输入中获取'x'个整数,计算平均值并输出。目前我的代码只完成了这些:

func main() {
var elems, mean int
sum := 0

fmt.Print("Number of elements? ")

fmt.Scan(&elems)

var array = new([elems]int)

for i := 0; i < elems; i++ {
    fmt.Printf("%d . Number? ", i+1)
    fmt.Scan(&array[i])
    sum += array[i];
}............

尝试编译时,我收到了以下错误信息:

invalid array bound elems

这里有什么问题?


我已经在某处看到过这个了 :) 让我猜一下,是不是在 https://www.hackerrank.com/challenges/simple-array-sum/problem? 上? - bin2hex
3个回答

156
你应该使用切片(slice)而不是数组(array):
//var array = new([elems]int) - no, arrays are not dynamic
var slice = make([]int,elems) // or slice := make([]int, elems)

请参考 go slices的用法和内部结构。此外,您可能需要考虑在循环中使用range:

// for i := 0; i < elems; i++ { - correct but less idiomatic
for i, v := range slice {

@Atom:我认为他可以在循环中使用v代替array[i]。但是我同意,我的寻找惯用代码的尝试有时会有点过分(我是那些在国外寻找“典型”餐厅然后被“典型地”宰割的人之一)。 - Paolo Falabella
2
应该写成 slice := make([]int, elems) 以避免混淆。 - Ivan Chau
1
如果它是“动态”的,为什么我们需要设置切片的长度? - alramdein
@PaoloFalabella 我已经找到了答案。在 Go 中,动态数组实际上不需要长度。它可以用这个简单的简短声明来声明s := []int{}。所以当我需要添加值时,只需要使用append(s, value)即可。顺便说一下,谢谢你的回答,我非常感激。 - alramdein
@AlifRamdani 切片仍在为具有初始设置长度的数组分配内存,而append如果超过初始数组容量则会分配更多空间。 如果您知道数组将包含多少项,您可能会更好地表现,如果您设置了初始容量(分配新内存相对昂贵)。 - Paolo Falabella
显示剩余2条评论

22
我的观点是,这是由于对newmake函数的使用产生了混淆。正如在golang-nuts的几次讨论中所证明的那样,这是Go语言中已知的一个问题/特性。
通过让Go打印出newmake创建的值的类型,可以更清楚地区分它们之间的区别。
package main

import "fmt"

func main() {
    fmt.Printf("%T  %v\n", new([10]int), new([10]int))
    fmt.Printf("%T  %v\n", make([]int, 10), make([]int, 10))
}

输出结果:
*[10]int  &[0 0 0 0 0 0 0 0 0 0]
[]int  [0 0 0 0 0 0 0 0 0 0]

从类型上可以看出,要访问new([10]int)数组元素,我们首先需要解引用指针。 newmake都需要一个Go类型作为它们的第一个参数。然而,表达式[elems]int不是一个Go类型(除非elems是一个Go常量,在这里不是这种情况)。
更多参考资料,请参见http://golang.org/doc/go_spec.html#Allocationhttp://golang.org/doc/go_spec.html#The_zero_value
为了更好地理解new的结果是否可用,查找lencap是否与零(nil)值一起使用可能会有所帮助:http://golang.org/doc/go_spec.html#Length_and_capacity

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接