在Go语言中有foreach循环吗?

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

Is there a foreach loop in Go?

问题

在Go语言中有foreach结构吗?我可以使用for循环遍历切片或数组吗?

英文:

Is there a foreach construct in the Go language?
Can I iterate over a slice or array using a for?

答案1

得分: 1103

从*带有range子句的for语句*:

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

例如:

<!-- language: lang-golang -->

for index, element := range someSlice {
    // index是我们所在的索引
    // element是someSlice中我们所在位置的元素
}

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

<!-- language: lang-golang -->

for _, element := range someSlice {
    // element是someSlice中我们所在位置的元素
}

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

英文:

From For statements with range clause:

> A "for" statement with a "range" clause iterates through all entries
> of an array, slice, string or map, or values received on a channel.
> For each entry it assigns iteration values to corresponding iteration
> variables and then executes the block.

As an example:

<!-- language: lang-golang -->

for index, element := range someSlice {
    // index is the index where we are
    // element is the element from someSlice for where we are
}

If you don't care about the index, you can use _:

<!-- language: lang-golang -->

for _, element := range someSlice {
    // element is the element from someSlice for where we are
}

The underscore, _, is the blank identifier, an anonymous placeholder.

答案2

得分: 224

Go有一种类似于foreach的语法。它支持数组/切片、映射和通道。

遍历数组切片

// 索引和值
for i, v := range slice {}

// 仅索引
for i := range slice {}

// 仅值
for _, v := range slice {}

遍历映射

// 键和值
for key, value := range theMap {}

// 仅键
for key := range theMap {}

// 仅值
for _, value := range theMap {}

遍历通道

for v := range theChan {}

遍历通道等同于从通道接收数据,直到通道关闭:

for {
    v, ok := &lt;-theChan
    if !ok {
        break
    }
}
英文:

Go has a foreach-like syntax. It supports arrays/slices, maps and channels.

Iterate over an array or a slice:

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

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

// value only
for _, v := range slice {}

Iterate over a map:

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

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

// value only
for _, value := range theMap {}

Iterate over a channel:

for v := range theChan {}

Iterating over a channel is equivalent to receiving from a channel until it is closed:

for {
    v, ok := &lt;-theChan
    if !ok {
        break
    }
}

答案3

得分: 23

以下是在Go中使用foreach的示例代码:

package main

import (
    "fmt"
)

func main() {

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

    for index, element := range arrayOne {

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

    }

}

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

英文:

Following is the example code for how to use foreach in Go:

package main

import (
    &quot;fmt&quot;
)

func main() {

    arrayOne := [3]string{&quot;Apple&quot;, &quot;Mango&quot;, &quot;Banana&quot;}

    for index,element := range arrayOne{

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

    }

}

This is a running example https://play.golang.org/p/LXptmH4X_0

答案4

得分: 14

是的,range

for 循环的 range 形式可以迭代一个切片或映射。

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

示例:

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)
    }
}
  • 通过将值赋给 _,可以跳过索引或值。
  • 如果只想要索引,完全省略 , 后面的值。
英文:

Yes, range:

The range form of the for loop iterates over a slice or map.

When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.

Example:

package main

import &quot;fmt&quot;

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

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

    for i := range pow {
        pow[i] = 1 &lt;&lt; uint(i) // == 2**i
    }
    for _, value := range pow {
        fmt.Printf(&quot;%d\n&quot;, value)
    }
}
  • You can skip the index or value by assigning to _.
  • If you only want the index, drop the , value entirely.

答案5

得分: 13

以下示例展示了如何在for循环中使用range运算符来实现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;
}

该示例遍历一个函数数组,以统一处理函数的错误。完整示例可在Google的playground中找到。

PS:它还显示了悬挂括号对于代码的可读性是一个不好的主意。提示:for条件在action()调用之前结束。显而易见,不是吗?

英文:

The following example shows how to use the range operator in a for loop to implement a foreach loop.

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

    for _, action := range []func() {
        func () { data, err = xml.MarshalIndent(value, &quot;&quot;, &quot;  &quot;) },
        func () { _, err = out.Write([]byte(xml.Header)) },
        func () { _, err = out.Write(data) },
        func () { _, err = out.Write([]byte(&quot;\n&quot;)) }} {
        action();
        if err != nil {
            return err
        }
    }
    return nil;
}

The example iterates over an array of functions to unify the error handling for the functions. A complete example is at Google´s playground.

PS: it shows also that hanging braces are a bad idea for the readability of code. Hint: the for condition ends just before the action() call. Obvious, isn't it?

答案6

得分: 12

你实际上可以使用range而不引用其返回值,通过对你的类型使用for range

<!-- language: lang-go -->

arr := make([]uint8, 5)
i,j := 0,0
for range arr {
    fmt.Println("数组循环", i)
    i++
}

for range "bytes" {
    fmt.Println("字符串循环", j)
    j++
}

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

英文:

You can in fact use range without referencing its return values by using for range against your type:

<!-- language: lang-go -->

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

for range &quot;bytes&quot; {
    fmt.Println(&quot;String Loop&quot;, j)
    j++
}

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

答案7

得分: 1

这可能很明显,但你可以像这样内联数组:

package main

import (
	"fmt"
)

func main() {
	for _, element := range [3]string{"a", "b", "c"} {
		fmt.Print(element)
	}
}

输出:

abc

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

英文:

This may be obvious, but you can inline the array like so:

package main

import (
	&quot;fmt&quot;
)

func main() {
	for _, element := range [3]string{&quot;a&quot;, &quot;b&quot;, &quot;c&quot;} {
		fmt.Print(element)
	}
}

outputs:

abc

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

答案8

得分: 1

我看到很多使用range的例子。提醒一下,range会创建一个迭代对象的副本。如果你在foreach循环中对副本进行更改,那么原始容器中的值不会改变,这种情况下你需要使用传统的for循环,通过索引递增并解引用索引引用。例如:

for i := 0; i < len(arr); i++ {
	element := &arr[i]
	element.Val = newVal
}
英文:

I'm seeing a lot of examples using range. Just a heads up that range creates a copy of whatever you're iterating over. If you make changes to the contents in a foreach range you will not be changing the values in the original container, in that case you'll need a traditional for loop with an index you increment and deference indexed reference. E.g.:

for i := 0; i &lt; len(arr); i++ {
	element := &amp;arr[i]
	element.Val = newVal
}

答案9

得分: 0

我刚刚实现了这个库:https://github.com/jose78/go-collection。

这是如何使用Foreach循环的示例:

package main

import (
    "fmt"

    col "github.com/jose78/go-collection/collections"
)

type user struct {
    name string
    age  int
    id   int
}

func main() {
    newList := col.ListType{user{"Alvaro", 6, 1}, user{"Sofia", 3, 2}}
    newList = append(newList, user{"Mon", 0, 3})

    newList.Foreach(simpleLoop)

    if err := newList.Foreach(simpleLoopWithError); err != nil{
        fmt.Printf("This error >>> %v <<< was produced", err )
    }
}

var simpleLoop col.FnForeachList = func(mapper interface{}, index int) {
    fmt.Printf("%d.- item:%v\n", index, mapper)
}


var simpleLoopWithError col.FnForeachList = func(mapper interface{}, index int) {
    if index > 1{
        panic(fmt.Sprintf("Error produced with index == %d\n", index))
    }
    fmt.Printf("%d.- item:%v\n", index, mapper)
}

这个执行的结果应该是:

0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
2.- item:{Mon 0 3}
0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
Recovered in f Error produced with index == 2

ERROR: Error produced with index == 2
This error >>> Error produced with index == 2 <<< was produced

在playGrounD中尝试这段代码

英文:

I have just implemented this library: https://github.com/jose78/go-collection.

This is an example of how to use the Foreach loop:

package main

import (
    &quot;fmt&quot;

    col &quot;github.com/jose78/go-collection/collections&quot;
)

type user struct {
    name string
    age  int
    id   int
}

func main() {
    newList := col.ListType{user{&quot;Alvaro&quot;, 6, 1}, user{&quot;Sofia&quot;, 3, 2}}
    newList = append(newList, user{&quot;Mon&quot;, 0, 3})

    newList.Foreach(simpleLoop)

    if err := newList.Foreach(simpleLoopWithError); err != nil{
        fmt.Printf(&quot;This error &gt;&gt;&gt; %v &lt;&lt;&lt; was produced&quot;, err )
    }
}

var simpleLoop col.FnForeachList = func(mapper interface{}, index int) {
    fmt.Printf(&quot;%d.- item:%v\n&quot;, index, mapper)
}


var simpleLoopWithError col.FnForeachList = func(mapper interface{}, index int) {
    if index &gt; 1{
        panic(fmt.Sprintf(&quot;Error produced with index == %d\n&quot;, index))
    }
    fmt.Printf(&quot;%d.- item:%v\n&quot;, index, mapper)
}

The result of this execution should be:

0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
2.- item:{Mon 0 3}
0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
Recovered in f Error produced with index == 2

ERROR: Error produced with index == 2
This error &gt;&gt;&gt; Error produced with index == 2
 &lt;&lt;&lt; was produced

Try this code in playGrounD.

huangapple
  • 本文由 发表于 2011年10月16日 12:47:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/7782411.html
匿名

发表评论

匿名网友

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

确定