Question
In Go, is there a simpler or more idiomatic way to get a slice of keys from a map?
Right now, I am iterating over the map and copying each key into a slice:
i := 0
keys := make([]int, len(mymap))
for k := range mymap {
keys[i] = k
i++
}
I want to know whether Go provides a cleaner built-in approach, or whether manually iterating over the map is the standard way to do this.
Short Answer
By the end of this page, you will understand how to extract keys from a map in Go, why iteration is the normal approach, and how to write this pattern clearly and safely. You will also learn when to preallocate a slice, when to use append, and how to sort keys when order matters.
Concept
In Go, a map is an unordered collection of key-value pairs. If you want all keys from a map, you must iterate over the map and collect them yourself.
There is no built-in function in the standard language syntax that directly returns a slice of keys for any map. The idiomatic approach is to use a for range loop.
Why this matters:
- Maps are used everywhere in Go for lookups, caching, grouping, and counting.
- Very often, you need the keys separately for display, sorting, or further processing.
- Understanding that map iteration is explicit helps you write predictable and readable Go code.
A key detail is that map iteration order is not guaranteed. That means the slice of keys you build may come out in a different order each time. If you need a stable order, you must sort the keys after collecting them.
There are two common ways to build the keys slice:
- Preallocate with
makeand fill by index - Start empty and use
append
Both are valid. In many cases, using append is a little cleaner and easier to read.
Mental Model
Think of a Go map like a box of labeled index cards.
- The label on each card is the key.
- The content written on the card is the value.
- If you want a list of all labels, you must pick up each card one by one and copy its label into a new list.
Go does not hand you a ready-made list of labels automatically. You create that list by walking through the box yourself.
Syntax and Examples
Basic pattern
The standard way to get keys from a map is:
keys := make([]int, 0, len(m))
for k := range m {
keys = append(keys, k)
}
Why this version is nice
make([]int, 0, len(m))creates an empty slice- It reserves enough capacity for all keys
appendkeeps the code simple
Example
package main
import "fmt"
func main() {
mymap := map[int]string{
10: "apple",
20: "banana",
30: "orange",
}
keys := make([]int, 0, len(mymap))
for k := range mymap {
keys = append(keys, k)
}
fmt.Println(keys)
}
Step by Step Execution
Consider this code:
m := map[int]string{
5: "a",
2: "b",
9: "c",
}
keys := make([]int, 0, len(m))
for k := range m {
keys = append(keys, k)
}
Step by step:
mis created with 3 key-value pairs.len(m)is3.make([]int, 0, len(m))creates:- a slice of length
0 - a capacity of
3
- a slice of length
- The loop
for k := range mstarts iterating over the map. - On each iteration, Go gives one key from the map.
append(keys, k)adds that key to the slice.- After all iterations,
keyscontains all map keys.
A possible trace:
Real World Use Cases
Getting keys from a map is common in real Go programs.
1. Displaying available IDs
You may store records in a map and need to list all IDs:
users := map[int]string{
101: "Ava",
102: "Noah",
}
You can extract the keys to show which users exist.
2. Sorting configuration names
A service might load feature flags into a map:
flags := map[string]bool{
"betaUI": true,
"logging": false,
}
You collect the keys, sort them, and print them in a stable order.
3. Building API responses
Sometimes your internal data is stored as a map, but the API response needs a list of keys or IDs.
4. Validating allowed values
You might keep allowed values in a map for fast lookup, then later need the keys for an error message:
allowed := map[string]struct{}{
"json": {},
"xml": {},
}
If the user passes an invalid format, you can return the list of valid formats.
Real Codebase Usage
In real Go codebases, developers usually use one of these patterns.
Pattern 1: Extract keys with append
This is the most readable general-purpose style:
keys := make([]string, 0, len(settings))
for k := range settings {
keys = append(keys, k)
}
Pattern 2: Sort immediately when order matters
This is very common in CLI tools, logs, tests, and API output:
keys := make([]string, 0, len(settings))
for k := range settings {
keys = append(keys, k)
}
sort.Strings(keys)
Pattern 3: Helper function
Teams often wrap this in a small helper for repeated use:
func mapKeys(m map[string]int) []string {
keys := make([]string, 0, len(m))
k := m {
keys = (keys, k)
}
sort.Strings(keys)
keys
}
Common Mistakes
1. Expecting map keys to come out in a fixed order
Broken assumption:
m := map[int]string{1: "a", 2: "b", 3: "c"}
keys := make([]int, 0, len(m))
for k := range m {
keys = append(keys, k)
}
// Do not assume keys == [1, 2, 3]
Fix
Sort the slice if order matters.
sort.Ints(keys)
2. Mixing up slice length and capacity
Broken code:
keys := make([]int, 0, len(m))
for k := range m {
keys[i] = k // panic: index out of range
i++
}
Why it breaks:
- Length is
0, sokeys[0]is invalid - Capacity is reserved, but elements do not exist yet
Comparisons
Common ways to collect map keys
| Approach | Example | Pros | Cons | When to use |
|---|---|---|---|---|
| Preallocate full length and assign by index | keys := make([]int, len(m)) | Efficient, no append calls | Needs manual index variable | When you know exact length and are comfortable managing i |
Empty slice with capacity and append | keys := make([]int, 0, len(m)) | Readable, idiomatic, less error-prone | Slightly more abstract for beginners | Best default choice |
| Empty slice without capacity | var keys []int then append | Short and simple | May reallocate as it grows |
Cheat Sheet
Key pattern
keys := make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
Replace K with the map key type.
Example with int keys
keys := make([]int, 0, len(m))
for k := range m {
keys = append(keys, k)
}
Example with string keys
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
If order matters
sort.Ints(keys)
sort.Strings(keys)
Alternative indexed version
i :=
keys := ([], (m))
k := m {
keys[i] = k
i++
}
FAQ
Is there a built-in Go function to get all map keys?
Not in the basic language syntax for ordinary maps. The standard approach is to iterate with for range and collect the keys.
What is the idiomatic way to get map keys in Go?
Usually:
keys := make([]KeyType, 0, len(m))
for k := range m {
keys = append(keys, k)
}
Why is my keys slice in a different order each run?
Because Go map iteration order is not guaranteed. Sort the keys if you need stable output.
Should I use append or assign by index?
Both work. append is often easier to read and less error-prone. Index assignment is fine if you pre-size the slice correctly.
Why use make([]T, 0, len(m)) instead of just var keys []T?
It preallocates enough capacity for all keys, which can reduce reallocations while keeping the code simple.
Can I get both keys and values during iteration?
Yes:
for k, v := range m {
fmt.Println(k, v)
}
Do I need to sort keys in tests?
Mini Project
Description
Build a small Go program that stores a set of product IDs in a map and then extracts the keys into a slice. This demonstrates the standard pattern for collecting map keys, and it also shows how to sort them for stable output.
Goal
Create a program that reads keys from a map, stores them in a slice, sorts the slice, and prints the result.
Requirements
- Create a map with at least five integer keys
- Extract all keys into a slice using a
for rangeloop - Use
appendto build the slice - Sort the keys before printing
- Print the final sorted slice
Keep learning
Related questions
Blank Identifier Imports in Go: What `_` Means in an Import Statement
Learn what `_` means in a Go import, why blank identifier imports run package init code, and when to use them safely.
Check if a Value Exists in a Slice in Go
Learn how to check whether a value exists in a slice in Go, and why Go has no Python-style `in` operator for arrays or slices.
Concatenating Slices in Go with append
Learn how to concatenate two slices in Go using append and the ... operator, with examples, pitfalls, and practical usage.