Iterate Go map get index

In order to use a revel


keyword in templates, I would like to get the index of the map entry when iterating with range

. Is there a way to do this? My map has the following structure:




source to share

4 answers

You cannot do this with template actions alone, but you can register a function that provides the assistance you need.

You can register a function that returns a function (a closure) that alternates between the return value when called (just like β€œodd” and β€œeven” indexes alternate):

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


I named it isEven()

to avoid colliding with ravel even()

. Using it:

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

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

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


Conclusion (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 need different output for odd and even iterations, you can call $e

in action {{if}}

, for example:

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


Result 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 is the template action:

{{$e := isEven}}


Creates a new template variable with a name $e

, and its value will be the result (return value) of the function call isEven()

. isEven()

returns the value of a function, a closure that has access to a local variable of the e

type bool

. When you are done {{call $e}}

, you are not calling the isEven()

Go function , but the function it returns (the closure) and saved to $e

. This closure has a reference to a local variable bool


, it is not "released" until the return function is available isEvent()


That way, whenever you do {{call $e}}

, it calls a closure that has a "has" e

type variable bool

whose value persists between calls to that $e


If you call it again isEvent

in the template, you will return a new function (closure) by wrapping a new instance of a local variable e

, independent of the first wrapped closure variable returned by the first call isEvent()




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




Map entries have no Go index; you cannot get the index from any element. Also, every time you iterate on a map with range

, you end up with a different order - another hint of the lack of an index concept on maps.

Indexes only refer to ordered data structures (such as arrays, fragments, lists, etc.), not maps. Take a look at for more details.



An easy way to reach the index while walking through the map:

package main

import (

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)
    fmt.Println("Hello, playground")


And prints:

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




All Articles