英文:
What happens when I range over an uninitialized pointer to array in golang
问题
我有这段代码:
var j *[33]byte
for i := range j {
fmt.Println(j[i])
}
当我运行这段代码时,当我尝试访问j
中的值时,我会得到nil指针解引用错误
。我不确定为什么我能够进入循环,考虑到我的指针未初始化。
我知道未初始化的数组的所有值都设置为它们的零值。也就是说,
var a [5]int
将具有默认值[0, 0, 0, 0, 0]
。
但是我不明白当你不初始化指向数组的指针时,Go语言会做什么。为什么range
能够遍历它,即使它是nil
的?
英文:
I have this code
var j *[33]byte
for i := range j {
fmt.Println(j[i])
}
Now when I run this code I get nil pointer dereference error
when I try access values in j
. I'm not sure why I was even able to enter the loop in the first place considering my pointer is uninitialized.
I know an uninitialized array has all its values set to their zero value. That is
var a [5]int
Will have a default value of [0, 0, 0, 0, 0]
.
But I don't understand what golang does when you don't initialize a pointer to an array. Why is range
able to range over it even though its nil?
答案1
得分: 1
根据Go规范中的Range子句:
> ...对于数组、数组指针或切片值a,索引迭代值按递增顺序产生...
因此,为了方便起见,Go语言会解引用指针,以便在其元素上进行迭代。指针为nil
是一个简单的编程错误。如果可能发生这种情况,应该在代码中加入运行时检查来防止它发生。
静态分析可能能够提前检测到这种类型的错误 - 但是如果变量j
可以从另一个goroutine访问 - 编译器如何确定另一个goroutine可能会在range
循环到达之前将其更新为非nil
值呢?
英文:
From the Go spec Range Clause:
> ... For an array, pointer to array, or slice value a, the index
> iteration values are produced in increasing order...
so as a convenience the Go language is dereferencing the pointer with the intent to iterating over its elements. The fact that the pointer is nil
is a simple programming error. If this can occur, one should have a runtime check in place to guard against it.
Static analysis may be able to detect this type of bug ahead of time - but what if the variable j
is accessible from another goroutine - how would the compiler know for sure that another goroutine may update it to a non-nil value right before the range
loop is reached?
答案2
得分: -3
当你使用var
关键字初始化变量时,Go语言为每种类型定义了一个零值(当使用:=
时,可能会发生变化,理想情况下用于需要值的副本或特定值的情况)。对于指针而言,零值是nil(对于映射、接口、通道、切片和函数也是如此),对于int类型的数组而言,零值是0。
所以,回答你的问题,Go语言能够进行迭代,因为无论该位置内的值是什么,你都有33个有效的空间。你可以查看Golang文档中关于切片和数组的区别,以获取更多关于这个问题的见解。
英文:
Go has a zero value defined for each type when you initialize a variable with var
keyword (this may change when using :=
, ideally used when need copies of values or specific values). In the case of the pointer the zero value is nil (also maps, interfaces, channels, slices, and functions) in case of array of type int the zero value is 0.
So, to answer your question, Go is able to iterate because you have 33 valid spaces idependently of what value is inside of that position. You can check the diference between slices and arrays on the Golang documentation to have more insights on why is that.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论