忽略 Go 范围内的值

woo*_*kie 5 memory range go

我有一个关于 Gorange和忽略返回值的工作方式的问题。

就文档而言,每次迭代都会range产生两个值 - 当前元素的索引和副本,因此如果在迭代期间我们想要更改当前 elmenet 中的字段或元素本身,我们必须通过 引用它elements[index],因为elment只是一个副本(假设循环看起来像这样for index, element := range elements)。

Go 还允许使用 忽略一些返回值_,因此我们可以编写for index, _ := elements.

但它让我思考。Go 是否足够聪明以至于在使用_in时实际上不制作副本range?如果不是,那么如果 inelements中的元素非常大并且我们有多个进程/go-routines 运行我们的代码,我们就是在浪费内存,最好使用基于len(elements).

我对吗?

编辑

我们也可以使用

for index := range elements

这似乎是一个不错的选择。

icz*_*cza 8

for range构造最多可以生成 2 个值,但不一定是 2 个(它也可以是在通道上发送的单个索引值或映射键或值,甚至根本没有)。

引用规范:对于语句:

如果范围表达式是通道,则最多允许一个迭代变量,否则最多允许两个。

继续引用:

如果最后一个迭代变量是空白标识符,则 range 子句相当于没有该标识符的同一子句。

这意味着:

for i, _ := range something {}
Run Code Online (Sandbox Code Playgroud)

相当于:

for i := range something {}
Run Code Online (Sandbox Code Playgroud)

还有另一段来自 Spec: For statements 的引述,稍后再讲:

对于数组、指向数组的指针或切片值a,索引迭代值从元素索引开始按升序生成0如果最多存在一个迭代变量,则范围循环会生成从0到 的迭代值len(a)-1,并且不会索引到数组或切片本身。

所以第一种情况下额外的空白标识符不会导致额外的分配或复制,并且完全没有必要和无用。