How to iterate maps in insertion order?

Issue

I have a navbar as a map:

var navbar = map[string]navbarTab{
}

Where navbarTab has various properties, child items and so on. When I try to render the navbar (with for tabKey := range navbar) it shows up in a random order. I’m aware range randomly sorts when it runs but there appears to be no way to get an ordered list of keys or iterate in the insertion order.

The playground link is here: http://play.golang.org/p/nSL1zhadg5 although it seems to not exhibit the same behavior.

How can I iterate over this map without breaking the insertion order?

Solution

Go maps do not maintain the insertion order; you will have to implement this behavior yourself.

Example:

type NavigationMap struct {
    m map[string]navbarTab
    keys []string
}

func NewNavigationMap() *NavigationMap { ... }

func (n *NavigationMap) Set(k string, v navbarTab) {
    n.m[k] = v
    n.keys = append(n.keys, k)
}

This example is not complete and does not cover all use-cases (eg. updating insertion order on duplicate keys).

If your use-case includes re-inserting the same key multiple times (this will not update insertion order for key k if it was already in the map):

func (n *NavigationMap) Set(k string, v navbarTab) {
    _, present := n.m[k]
    n.m[k] = v
    if !present {
        n.keys = append(n.keys, k)
    }
}

Choose the simplest thing that satisfies your requirements.

Answered By – Arjan

Answer Checked By – Senaida (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.