在Go语言中有foreach循环吗?

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

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 -->

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

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

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

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

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

英文:

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 -->

  1. for index, element := range someSlice {
  2. // index is the index where we are
  3. // element is the element from someSlice for where we are
  4. }

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

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

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

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

答案2

得分: 224

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

遍历数组切片

  1. // 索引和值
  2. for i, v := range slice {}
  3. // 仅索引
  4. for i := range slice {}
  5. // 仅值
  6. for _, v := range slice {}

遍历映射

  1. // 键和值
  2. for key, value := range theMap {}
  3. // 仅键
  4. for key := range theMap {}
  5. // 仅值
  6. for _, value := range theMap {}

遍历通道

  1. for v := range theChan {}

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

  1. for {
  2. v, ok := &lt;-theChan
  3. if !ok {
  4. break
  5. }
  6. }
英文:

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

Iterate over an array or a slice:

  1. // index and value
  2. for i, v := range slice {}
  3. // index only
  4. for i := range slice {}
  5. // value only
  6. for _, v := range slice {}

Iterate over a map:

  1. // key and value
  2. for key, value := range theMap {}
  3. // key only
  4. for key := range theMap {}
  5. // value only
  6. for _, value := range theMap {}

Iterate over a channel:

  1. for v := range theChan {}

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

  1. for {
  2. v, ok := &lt;-theChan
  3. if !ok {
  4. break
  5. }
  6. }

答案3

得分: 23

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

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. arrayOne := [3]string{"Apple", "Mango", "Banana"}
  7. for index, element := range arrayOne {
  8. fmt.Println(index)
  9. fmt.Println(element)
  10. }
  11. }

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

英文:

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

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. )
  5. func main() {
  6. arrayOne := [3]string{&quot;Apple&quot;, &quot;Mango&quot;, &quot;Banana&quot;}
  7. for index,element := range arrayOne{
  8. fmt.Println(index)
  9. fmt.Println(element)
  10. }
  11. }

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

答案4

得分: 14

是的,range

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

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

示例:

  1. package main
  2. import "fmt"
  3. var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
  4. func main() {
  5. for i, v := range pow {
  6. fmt.Printf("2**%d = %d\n", i, v)
  7. }
  8. for i := range pow {
  9. pow[i] = 1 << uint(i) // == 2**i
  10. }
  11. for _, value := range pow {
  12. fmt.Printf("%d\n", value)
  13. }
  14. }
  • 通过将值赋给 _,可以跳过索引或值。
  • 如果只想要索引,完全省略 , 后面的值。
英文:

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:

  1. package main
  2. import &quot;fmt&quot;
  3. var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
  4. func main() {
  5. for i, v := range pow {
  6. fmt.Printf(&quot;2**%d = %d\n&quot;, i, v)
  7. }
  8. for i := range pow {
  9. pow[i] = 1 &lt;&lt; uint(i) // == 2**i
  10. }
  11. for _, value := range pow {
  12. fmt.Printf(&quot;%d\n&quot;, value)
  13. }
  14. }
  • 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循环。

  1. func PrintXml (out io.Writer, value interface{}) error {
  2. var data []byte
  3. var err error
  4. for _, action := range []func() {
  5. func () { data, err = xml.MarshalIndent(value, "", " ") },
  6. func () { _, err = out.Write([]byte(xml.Header)) },
  7. func () { _, err = out.Write(data) },
  8. func () { _, err = out.Write([]byte("\n")) }} {
  9. action();
  10. if err != nil {
  11. return err
  12. }
  13. }
  14. return nil;
  15. }

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

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

英文:

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

  1. func PrintXml (out io.Writer, value interface{}) error {
  2. var data []byte
  3. var err error
  4. for _, action := range []func() {
  5. func () { data, err = xml.MarshalIndent(value, &quot;&quot;, &quot; &quot;) },
  6. func () { _, err = out.Write([]byte(xml.Header)) },
  7. func () { _, err = out.Write(data) },
  8. func () { _, err = out.Write([]byte(&quot;\n&quot;)) }} {
  9. action();
  10. if err != nil {
  11. return err
  12. }
  13. }
  14. return nil;
  15. }

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 -->

  1. arr := make([]uint8, 5)
  2. i,j := 0,0
  3. for range arr {
  4. fmt.Println("数组循环", i)
  5. i++
  6. }
  7. for range "bytes" {
  8. fmt.Println("字符串循环", j)
  9. j++
  10. }

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 -->

  1. arr := make([]uint8, 5)
  2. i,j := 0,0
  3. for range arr {
  4. fmt.Println(&quot;Array Loop&quot;, i)
  5. i++
  6. }
  7. for range &quot;bytes&quot; {
  8. fmt.Println(&quot;String Loop&quot;, j)
  9. j++
  10. }

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

答案7

得分: 1

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

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. for _, element := range [3]string{"a", "b", "c"} {
  7. fmt.Print(element)
  8. }
  9. }

输出:

  1. abc

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

英文:

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

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. )
  5. func main() {
  6. for _, element := range [3]string{&quot;a&quot;, &quot;b&quot;, &quot;c&quot;} {
  7. fmt.Print(element)
  8. }
  9. }

outputs:

  1. abc

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

答案8

得分: 1

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

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

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.:

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

答案9

得分: 0

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

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

  1. package main
  2. import (
  3. "fmt"
  4. col "github.com/jose78/go-collection/collections"
  5. )
  6. type user struct {
  7. name string
  8. age int
  9. id int
  10. }
  11. func main() {
  12. newList := col.ListType{user{"Alvaro", 6, 1}, user{"Sofia", 3, 2}}
  13. newList = append(newList, user{"Mon", 0, 3})
  14. newList.Foreach(simpleLoop)
  15. if err := newList.Foreach(simpleLoopWithError); err != nil{
  16. fmt.Printf("This error >>> %v <<< was produced", err )
  17. }
  18. }
  19. var simpleLoop col.FnForeachList = func(mapper interface{}, index int) {
  20. fmt.Printf("%d.- item:%v\n", index, mapper)
  21. }
  22. var simpleLoopWithError col.FnForeachList = func(mapper interface{}, index int) {
  23. if index > 1{
  24. panic(fmt.Sprintf("Error produced with index == %d\n", index))
  25. }
  26. fmt.Printf("%d.- item:%v\n", index, mapper)
  27. }

这个执行的结果应该是:

  1. 0.- item:{Alvaro 6 1}
  2. 1.- item:{Sofia 3 2}
  3. 2.- item:{Mon 0 3}
  4. 0.- item:{Alvaro 6 1}
  5. 1.- item:{Sofia 3 2}
  6. Recovered in f Error produced with index == 2
  7. ERROR: Error produced with index == 2
  8. 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:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. col &quot;github.com/jose78/go-collection/collections&quot;
  5. )
  6. type user struct {
  7. name string
  8. age int
  9. id int
  10. }
  11. func main() {
  12. newList := col.ListType{user{&quot;Alvaro&quot;, 6, 1}, user{&quot;Sofia&quot;, 3, 2}}
  13. newList = append(newList, user{&quot;Mon&quot;, 0, 3})
  14. newList.Foreach(simpleLoop)
  15. if err := newList.Foreach(simpleLoopWithError); err != nil{
  16. fmt.Printf(&quot;This error &gt;&gt;&gt; %v &lt;&lt;&lt; was produced&quot;, err )
  17. }
  18. }
  19. var simpleLoop col.FnForeachList = func(mapper interface{}, index int) {
  20. fmt.Printf(&quot;%d.- item:%v\n&quot;, index, mapper)
  21. }
  22. var simpleLoopWithError col.FnForeachList = func(mapper interface{}, index int) {
  23. if index &gt; 1{
  24. panic(fmt.Sprintf(&quot;Error produced with index == %d\n&quot;, index))
  25. }
  26. fmt.Printf(&quot;%d.- item:%v\n&quot;, index, mapper)
  27. }

The result of this execution should be:

  1. 0.- item:{Alvaro 6 1}
  2. 1.- item:{Sofia 3 2}
  3. 2.- item:{Mon 0 3}
  4. 0.- item:{Alvaro 6 1}
  5. 1.- item:{Sofia 3 2}
  6. Recovered in f Error produced with index == 2
  7. ERROR: Error produced with index == 2
  8. This error &gt;&gt;&gt; Error produced with index == 2
  9. &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:

确定