Iterate Go map get index

golang map
golang iterate map with index
golang range int
golang map get keys
index range golang
golang range two map
golang range vs for loop
iterate through an array in go

In order to use revel's even keyword in templates I would like to get the index of a map entry when iterating with range. Is there any way to do so? My map has the structure:

map[string][]string

You can't do this only with template actions, but you may register a function which provides the necessary help.

You may register a function which returns a function (closure), which alternates its return value whenever called (exactly how "odd" and "even" indices alternate):

func isEven() func() bool {
    e := false
    return func() bool {
        e = !e
        return e
    }
}

I named it isEven() to not collide with ravel's even(). Using it:

func main() {
    t := template.Must(template.New("").Funcs(template.FuncMap{
        "isEven": isEven,
    }).Parse(templ))

    m := map[string]string{
        "a": "A", "b": "B", "c": "C", "d": "D",
    }
    if err := t.Execute(os.Stdout, m); err != nil {
        panic(err)
    }
}

const templ = `{{$e := isEven}}
{{- range $k, $v := . -}}
    [even:{{call $e}}] key={{$k}}; value={{$v}}
{{end}}`

Output (try it on the Go Playground):

[even:true] key=a; value=A
[even:false] key=b; value=B
[even:true] key=c; value=C
[even:false] key=d; value=D

If you want different output for odd and even iterations, you can call $e in an {{if}} action, like this:

const templ = `{{$e := isEven}}
{{- range $k, $v := . -}}
    [{{if call $e}}even{{else}}odd {{end}}] key={{$k}}; value={{$v}}
{{end}}`

Output of this (try it on the Go Playground):

[even] key=a; value=A
[odd ] key=b; value=B
[even] key=c; value=C
[odd ] key=d; value=D
Under the hood

This template action:

{{$e := isEven}}

Creates a new template variable named $e, and its value will be the result (return value) of the isEven() function call. isEven() returns a function value, a closure that has access to a local variable e of type bool. When later you do {{call $e}}, you're not calling the isEven() Go function, but the function it returned (the closure) and is stored in $e. That closure has a reference to the local bool variable e, it is not "freed" until the function returned by isEvent() is accessible.

So whenever you do {{call $e}}, it calls the closure, which "has" an e variable of type bool, whose value is retained between calls of this $e.

If you would call isEvent in the template again, that would return a new function (closure), wrapping a new instance of the local variable e, being independent of the first wrapped variable of the closure returned by the first isEvent() call.

How to iterate over a Map using for loop in Go?, range on arrays and slices provides both the index and value for each entry. Above we didn't range can also iterate over just the keys of a map. for k := range  How can we reverse a simple string in Go? How pointer & and * and ** works in Golang? Sierpinski triangle in Go Programming Language; How do you write multi-line strings in Go? Golang Get current Date and Time in EST, UTC and MST? How to read input from console line? How to find length of Map in Go?

A Simple way to achieve index while looping through a map:

package main

import (
    "fmt"
)

func main() {
    mm := map[string]int{"xx" : 1, "gg" : 2}
    cnt := 0
    for a, b:= range mm{
        fmt.Println("a", a, "b",b, "c" , cnt)
        cnt++
    }
    fmt.Println("Hello, playground")
}

And prints:

a xx b 1 c 0
a gg b 2 c 1
Hello, playground

Range, With a range expression in a for-loop we iterate over those indexes. We can also In Go, maps return their keys in a somewhat random (unpredictable) way. Home / Go Cookbook / 3 ways to iterate in Go edit Try Documentalist , my app that offers fast, offline access to 190+ programmer API docs. Iteration is a frequent need, be it iterating over lines of a file, results or of SELECT SQL query or files in a directory.

Map entries have no index in Go; there's no way you can get an index out of any element. Also, each time you iterate on a map with range, you get a different order - another hint that there's no index concept in maps.

Indexes are related to ordered data structures only (e.g. arrays, slices, lists, etc), not maps. Take a look at https://blog.golang.org/go-maps-in-action for more details.

4 basic range loop (for-each) patterns · YourBasic Go, Here is an idea. http://play.golang.org/p/CkJoCv7HV7. range loops are the only way to iterate over a map (or otherwise "find out" what keys a  Randomized range loop. The Go runtime randomizes the loop order over a map when the range keyword is used. This means programs that rely on a certain ordering of elements will fail sooner. And: This improves program quality because programs will not develop dependencies on map orders.

{{range $key, $element := .Map}}
  {{$index := index .Map $key}}
{{end}}

Golang range: Slice, String and Map, 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  In this article we will discuss 3 different ways to Iterate over a map in C++. Suppose we have a map of string and int as key-value pair i.e. Now let’s see how to iterate over this map in 3 different ways i.e. First of all, create an iterator of std::map and initialize it to the beginning of map i.e. Now, let’s iterate over the map by

Iterate over map without range?, A map is like an array except, instead of an integer index, you can have string or any other data range in for loop will return key and value of map element. To iterate through rows of a DataFrame, use DataFrame.iterrows() function which returns an iterator yielding index and row data for each row. In this tutorial, we shall go through examples demonstrating how to iterate over rows of a DataFrame.

Range, Go - Range - The range keyword is used in for loop to iterate over items of an array, slice, channel or map. With array and slices, it returns the index of the item​  Find local businesses, view maps and get driving directions in Google Maps. When you have eliminated the JavaScript , whatever remains must be an empty page. Enable JavaScript to see Google Maps.

The anatomy of maps in Go - RunGo, On each iteration, the value of the current element is assigned to $value and the Notice how the last index in $arr1 is now the value from the last index in $arr2! If you accidentally put a semicolon after the foreach statement, you get no  Go has 1 loop: the for-loop. But this loop can be used in many ways, to loop from a start to an end, or until a condition is reached. With range, a keyword, we can iterate over more complex things like slices or maps.

Comments
  • Your map keys are strings like "foo" and "wtf". What is an even string? That's not how things work.
  • Must you use even, or could you use CSS styling (:nth-child(odd), :nth-child(even)) and forget about even?
  • @kennytm this actually solved my problem. If you post it as Answer I will accept it, so the case is cleared
  • Its works, but I am curious, why does e not gets reset to false every time I call isEven()?
  • @Mrlenny Added a new Under the hood section to explain the internals.
  • here both $index and $element are string/[]string. But I want the number of iteration
  • with the edit i get ` error calling index: cannot index slice/array with type string`. I worked around it by now with help of @keynnytm's comment