808

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

2
  • 1
    check out: groups.google.com/group/golang-nuts/browse_thread/thread/… Commented Oct 16, 2011 at 5:19
  • 2
    The usage of range in for loops is also mentioned in the "An Interlude about Types" section (towards its end) of the Go tutorial. Commented Oct 16, 2011 at 12:31

9 Answers 9

1154

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.

Sign up to request clarification or add additional context in comments.

4 Comments

In this example, element is the value of the element (a copy) -- it is not the element itself. Although you can assign to element, this will not effect the underlying sequence.
I know in Python and C it's frequent to use underscore as a function for localization ( i.e. the gettext ). Would the use of underscore cause any problems in Go ? Does Go even use the same library for localization ?
@SergiyKolodyazhnyy Py docs says "(gettext) function is usually aliased as _() in the local namespace" which is just by convention, it's not part of the localization lib. The underscore _ is a valid label, and it's also convention in Go (and Python and Scala and other langs) to assign to _ for return values you won't use. The scope of _ in this example is restricted to the body of the for loop. If you have a package-scoped function _ then it would be shadowed inside the scope of the for loop. There's a few packages for localization, I've not seen any use _ as a function name.
See Moshe Revah's answer below for more usage examples of for...range. Includes slices, maps and channels.
234

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

4 Comments

Although the OP only asked for slice usage, I prefer this answer, because most will eventually need the other usages as well.
important distinction about the chan usage: ranging over a channel will gracefully exit the loop if the writer closes the channel at some point. In the for {v := <-theChan} equivalent, it will not exit on channel close. You can test for this via the second ok return value. TOUR EXAMPLE
Thought the same when reading it, for { ... } stands for an infinite loop.
How about just for without both key, value.I just want to run specific len. And do nothing with array. Ex: for _ := range slice{}
27

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

    }

}

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

1 Comment

Sometimes it's the simplest example that is the most useful. Thanks! I've got nothing against the most esoteric answers from the other commenters — they certainly illustrate the intricacies of very idiomatic Go programming, to the point that they become... unreadable and hard to follow — but I prefer your answer: it goes straight to the core with the simplest possible example (which works and it's obvious why it works).
16

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.

Comments

13

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?

5 Comments

Add a , and it's clearer where the for condition ends: play.golang.org/p/pcRg6WdxBd - This is actually the first time I've found a counter argument to the go fmt style, thanks!
@topskip both are go fmt valid; just pick the best one :)
@FilipHaglund It is not the point if it is valid. The point is that IMO it's clearer where the for condition ends in that particular case above.
In my opinion, this answer is unreasonably complex for the targeted question.
@AndreasHassing How to do it instead without introducing redundancy?
11

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

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

2 Comments

Good to know but that's not going to be useful in most cases
Agreed @Sridhar it's pretty niche.
1

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

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

Comments

1

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 < len(arr); i++ {
    element := &arr[i]
    element.Val = newVal
}

Comments

0

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

Try this code in playGrounD.

1 Comment

How is it a for-each loop? Isn't it just list processing? Can you elaborate in your answer? (But without "Edit:", "Update:", or similar - the question/answer should appear as if it was written today.)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.