当在Go语言中对未初始化的指向数组的指针进行范围遍历时会发生什么?

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

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.

huangapple
  • 本文由 发表于 2022年5月12日 06:45:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/72208376.html
匿名

发表评论

匿名网友

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

确定