Go中有一个foreach循环吗?

tat*_*tou 521 foreach go slice

foreachGo语言中是否有构造?我可以使用for?迭代切片或数组吗?

Kei*_*son 791

http://golang.org/doc/go_spec.html#For_statements

带有"range"子句的"for"语句遍历数组,切片,字符串或映射的所有条目,或者在通道上接收的值.对于每个条目,它将迭代值分配给相应的迭代变量,然后执行该块.

举个例子:

for index, element := range someSlice {
    // index is the index where we are
    // element is the element from someSlice for where we are
}
Run Code Online (Sandbox Code Playgroud)

如果您不关心索引,可以使用_:

for _, element := range someSlice {
    // element is the element from someSlice for where we are
}
Run Code Online (Sandbox Code Playgroud)

下划线_空标识符,一个匿名占位符.

  • 在此示例中,“ element”是元素(副本)的“值”-不是元素本身。尽管您可以分配给`element`,但这不会影响基础序列。 (5认同)
  • @SergiyKolodyazhnyy Py 文档说“(gettext) 函数通常在本地命名空间中别名为`_()`”,这只是_按照约定_,它不是本地化库的一部分。下划线 `_` 是一个有效的标签,它也是 Go(以及 Python、Scala 和其他语言)中的约定,将你不会使用的返回值分配给 `_`。本例中`_` 的作用域仅限于`for` 循环的主体。如果你有一个包作用域的函数 `_`,那么它会被隐藏在 for 循环的作用域内。有一些用于本地化的包,我没有看到任何使用 `_` 作为函数名称的情况。 (4认同)

Mos*_*vah 130

迭代数组切片:

// index and value
for i, v := range slice {}

// index only
for i := range slice {}

// value only
for _, v := range slice {}
Run Code Online (Sandbox Code Playgroud)

迭代地图:

// key and value
for key, value := range theMap {}

// key only
for key := range theMap {}

// value only
for _, value := range theMap {}
Run Code Online (Sandbox Code Playgroud)

迭代一个频道:

for v := range theChan {}
Run Code Online (Sandbox Code Playgroud)

迭代通道相当于从通道接收直到它关闭:

for {
    v, ok := <-theChan
    if !ok {
        break
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然OP只询问切片使用情况,但我更喜欢这个答案,因为大多数人最终还需要其他用法. (9认同)
  • 关于`chan`用法的重要区别:如果作者在某个时刻关闭了频道,那么在一个频道上的范围将优雅地退出循环.在`for {v:= <-theChan}`_equivalent_中,它将*不*在通道关闭时退出.你可以通过第二个'ok`返回值来测试它.[旅游示例](https://tour.golang.org/concurrency/4) (2认同)

cev*_*ing 13

以下示例说明如何rangefor循环中使用运算符来实现foreach循环.

func PrintXml (out io.Writer, value interface{}) error {
    var data []byte
    var err error

    for _, action := range []func() {
        func () { data, err = xml.MarshalIndent(value, "", "  ") },
        func () { _, err = out.Write([]byte(xml.Header)) },
        func () { _, err = out.Write(data) },
        func () { _, err = out.Write([]byte("\n")) }} {
        action();
        if err != nil {
            return err
        }
    }
    return nil;
}
Run Code Online (Sandbox Code Playgroud)

该示例遍历一系列函数以统一函数的错误处理.一个完整的例子是在谷歌的游乐场.

PS:它还表明挂括号对于代码的可读性是一个坏主意.提示:for条件在action()通话之前结束.很明显,不是吗?

  • 在我看来,对于有针对性的问题,这个答案是不合理的. (7认同)
  • 添加一个`,`更清楚`for`条件结束的地方:http://play.golang.org/p/pcRg6WdxBd - 这实际上是我第一次找到`go fmt`风格的反驳参数, 谢谢! (3认同)

rob*_*uck 10

事实上,您可以range使用for range针对您的类型而不引用它的返回值来使用:

arr := make([]uint8, 5)
i,j := 0,0
for range arr {
    fmt.Println("Array Loop",i)
    i++
}

for range "bytes" {
    fmt.Println("String Loop",j)
    j++
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/XHrHLbJMEd

  • 很高兴知道,但在大多数情况下这不会有用 (3认同)

Nis*_*Edu 8

以下是如何在golang中使用foreach的示例代码

package main

import (
    "fmt"
)

func main() {

    arrayOne := [3]string{"Apple", "Mango", "Banana"}

    for index,element := range arrayOne{

        fmt.Println(index)
        fmt.Println(element)        

    }   

}
Run Code Online (Sandbox Code Playgroud)

这是一个运行示例https://play.golang.org/p/LXptmH4X_0

  • 有时,最简单的例子才是最有用的。谢谢!我对其他评论者提供的最深奥的答案没有任何异议——它们确实说明了非常惯用的 Go 编程的复杂性,以至于它们变得……难以阅读和难以理解——但我更喜欢你的答案:它是直接的用最简单的示例来深入了解(它有效,而且很明显为什么有效)。 (2认同)

Ami*_*esh 6

是的,范围

for 循环的范围形式迭代切片或地图。

当对一个切片进行测距时,每次迭代都会返回两个值。第一个是索引,第二个是该索引处元素的副本。

例子 :

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
    for i, v := range pow {
        fmt.Printf("2**%d = %d\n", i, v)
    }

    for i := range pow {
        pow[i] = 1 << uint(i) // == 2**i
    }
    for _, value := range pow {
        fmt.Printf("%d\n", value)
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 您可以通过分配给 _ 来跳过索引或值。
  • 如果您只想要索引,请完全删除 , 值。