442

Is there a way to get a list of all the keys in a Go language map? The number of elements is given by len(), but if I have a map like:

m := map[string]string{ "key1":"val1", "key2":"val2" };

How do I iterate over all the keys?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Martin Redmond
  • 13,366
  • 6
  • 36
  • 32

6 Answers6

735

https://play.golang.org/p/JGZ7mN0-U-

for k, v := range m { 
    fmt.Printf("key[%s] value[%s]\n", k, v)
}

or

for k := range m {
    fmt.Printf("key[%s] value[%s]\n", k, m[k])
}

Go language specs for for statements specifies that the first value is the key, the second variable is the value, but doesn't have to be present.

Dougnukem
  • 14,709
  • 24
  • 89
  • 130
Jonathan Feinberg
  • 44,698
  • 7
  • 80
  • 103
  • 36
    As a possible gotcha, note that the order of the iteration is undefined. https://groups.google.com/d/msg/golang-nuts/YfDxpkI34hY/4pktJI2ytusJ – mna Sep 22 '12 at 02:18
  • 31
    Sudhir: golang language spec explicitly defines maps as having undefined ordering of keys. Furthermore, since Go 1, key order is intentionally randomized between runs to prevent dependency on any perceived order. – Mark Renouf Apr 28 '13 at 15:04
  • 9
    Note that this is not a mutable iteration, which is to say deleting a key will require you to restart the iteration. – Rick Smith Dec 13 '13 at 17:42
  • Also for small data sets, map order could be predictable. – woot Jan 17 '18 at 02:41
21

Here's some easy way to get slice of the map-keys.

// Return keys of the given map
func Keys(m map[string]interface{}) (keys []string) {
    for k := range m {
        keys = append(keys, k)
    }
    return keys
}

// use `Keys` func
func main() {
    m := map[string]interface{}{
        "foo": 1,
        "bar": true,
        "baz": "baz",
    }
    fmt.Println(Keys(m)) // [foo bar baz]
}
a8m
  • 9,334
  • 4
  • 37
  • 40
  • Is it possible for the `Keys` function to take a map with keys of any type, not just strings? – Robert T. McGibbon Feb 09 '15 at 03:32
  • `func Keys(m map[interface{}]interface{}) (keys []interface{})`, @RobertT.McGibbon you need to change the function "prototype" – a8m Feb 09 '15 at 13:19
  • 1
    @ArielM. That would only work for the exact type `map[interface{}]interface{}`. Go does not support generics. You can't create a function with a `map` parameter which accepts maps with different key types. – icza Jun 17 '15 at 10:07
  • is there anyway I can put an if condition on k in the for loop and change its value? means : Keys(m map[string]interface{}) (keys []string) { for k := range m { if k = "abc" { k = "dce" } keys = append(keys, k) } return keys } – MBA Jan 11 '23 at 20:24
19

Is there a way to get a list of all the keys in a Go language map?

ks := reflect.ValueOf(m).MapKeys()

how do I iterate over all the keys?

Use the accepted answer:

for _, k := range m { ... }
Sridhar
  • 2,416
  • 1
  • 26
  • 35
  • 5
    I think you meant `for _, k := range v.MapKeys()`, since in your example, `k` would be the int index of the slice of keys – Brian Leishman Apr 23 '19 at 14:05
6

A Type agnostic solution:

for _, key := range reflect.ValueOf(yourMap).MapKeys() {
    value := yourMap.MapIndex(key).Interface()
    fmt.Println("Key:", key, "Value:", value)
}  
Mohsen
  • 4,000
  • 8
  • 42
  • 73
4

Using Generics:

func Keys[K comparable, V any](m map[K]V) []K {
    keys := make([]K, 0, len(m))

    for k := range m {
        keys = append(keys, k)
    }

    return keys
}
fliX
  • 773
  • 8
  • 24
0

For sorted keys of map[string]string.

package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]string{"key1": "val1", "key2": "val2"}
    sortStringMap(m)
}

// sortStringMap prints the [string]string as keys sorted
func sortStringMap(m map[string]string) {
    var keys []string
    for key := range m {
        keys = append(keys, key)
    }
    sort.Strings(keys)  // sort the keys
    for _, key := range keys {
        fmt.Printf("%s\t:%s\n", key, m[key])
    }
}

output:

key1    :val1
key2    :val2

ralonr
  • 180
  • 1
  • 1
  • 9