Is there a foreach construct in the Go language? Can I iterate over a slice or array using a for?
8 Answers
Answer recommended by Go Language
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:
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 _:
for _, element := range someSlice { // element is the element from someSlice for where we are } The underscore, _, is the blank identifier, an anonymous placeholder.
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 := <-theChan if !ok { break } } 4Following is the example code for how to use foreach in Go:
package main import ( "fmt" ) func main() { arrayOne := [3]string{"Apple", "Mango", "Banana"} for index,element := range arrayOne{ fmt.Println(index) fmt.Println(element) } } 1The 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, "", " ") }, 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; } 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?
You can in fact use range without referencing its return values by using for range against your type:
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++ } 2Yes, 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 "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) } } - You can skip the index or value by assigning to
_. - If you only want the index, drop the
,value entirely.
This may be obvious, but you can inline the array like so:
package main import ( "fmt" ) func main() { for _, element := range [3]string{"a", "b", "c"} { fmt.Print(element) } } outputs:
abc I have just implemented this library: .
This is an example of how to use the Foreach loop:
package main import ( "fmt" col "" ) 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) } 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 >>> Error produced with index == 2 <<< was produced 1