Is there a foreach
construct in the Go language? Can I iterate over a slice or array using a for
?
8 Answers
https://golang.org/ref/spec#For_range
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
}
}
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, "", " ") },
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?
Following is the example code for how to use foreach in golang
package main
import (
"fmt"
)
func main() {
arrayOne := [3]string{"Apple", "Mango", "Banana"}
for index,element := range arrayOne{
fmt.Println(index)
fmt.Println(element)
}
}
This is a running example https://play.golang.org/p/LXptmH4X_0
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 "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.
I have jus implement this library:https://github.com/jose78/go-collection. This is an example about how to use the Foreach loop:
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)
}
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
range
infor
loops is also mentioned in the "An Interlude about Types" section (towards its end) of the Go tutorial. – kostix