GoGo example

How to remove a key from a map in Go

6 min read▶ Runs in an isolated hosted runtimeUpdated Aug 2026

Quick answer

Use the built-in delete: delete(m, key). It returns nothing, and if the key isn't in the map it does nothing at all — no error, no panic, no KeyError. To empty the whole map at once, clear(m) (Go 1.21+).

Removal is the one map operation with no punctuation to learn: delete is a builtin, like len and append, so there is nothing to import and nothing to check afterwards. The interesting parts are the edges — what happens when the key was never there, what happens if you delete while ranging over the map, how to empty a map without allocating a new one, and why a map that has been emptied still holds on to its memory. Each example runs on this page — hit Run, then edit the code and run it again.

1The delete builtinRecommended

delete(m, key) removes the key and its value from the map. It is a statement, not an expression: there is no return value to inspect and nothing to assign. Crucially, deleting a key that was never in the map is a defined no-op — Go simply does nothing, where Python would raise KeyError and JavaScript would hand you back a meaningless true. That means you never need to guard a delete.

delete.go

Output

Prints 4, then 3 after the two deletes — only one of them changed anything. The last two lines show what the key became: ports["ftp"] is 0, the value type's zero value, and the comma-ok check reports false. delete on a nil map is a no-op too, which is unusual — writing to a nil map panics, but deleting from one does not.

2Delete only if the key was there

Because delete returns nothing, it can't tell you whether it removed anything. When you need to know — logging a removal, decrementing a counter, returning the old value — do a comma-ok lookup first and delete inside the if. That is Go's equivalent of Python's dict.pop(key, default), and it costs one extra hash lookup.

pop.go

Output

Prints removed pens: 12, removed chairs: 0, then 0 false 0. The middle line is the point: chairs held a legitimate 0, so testing if stock[k] != 0 before deleting would have skipped it. Maps are reference types, so pop mutates the caller's map — no pointer needed, and no copy is made when you pass one to a function.

3Deleting while you range

In many languages, mutating a collection you are iterating is undefined behaviour or an outright exception. Go explicitly allows it: the spec says entries removed during iteration simply will not be produced, and entries you delete behind the cursor are already done. So filtering a map in place is a plain range loop with a delete in it — no second pass, no copy of the keys.

ranging.go

Output

Prints 2 falsebob and dee are gone — then 2 0: the second loop still visited both survivors even though it deleted each one as it went. Adding during a range is the risky direction: a key created mid-loop may or may not be produced later, so the result is genuinely unspecified. Note also that the loop deliberately never prints the map directly — Go randomises iteration order, so sort the keys first when output must be stable.

4Removing every key: clear vs make vs nil

To empty a map, Go 1.21 added the clear builtin: clear(m) deletes every entry and keeps the same map. The older move — m = make(map[string]int) — looks equivalent but isn't: it points m at a different map, so any other variable, struct field, or goroutine still holding the original sees an unchanged map. Setting m = nil is a third thing again: readable and deletable, but the next write panics.

clear.go

Output

clear prints 0 0 — both views empty — and the write after it prints 1 1, because they are still the same map. The make line prints 0 1: m is fresh, alias kept the old contents. Then true 0 for the nil map and 0 after deleting from it. Before 1.21 the idiom was for k := range m { delete(m, k) }, which the compiler already special-cased into the same fast path clear uses.

5Which should you use?

MethodRemovesExisting references see itBest for
delete(m, k)One keyYesAlmost everything
v, ok := m[k]; delete(m, k)One key + tells youYesPop semantics, logging a removal
maps.DeleteFunc(m, pred)Every matchYesFiltering in place, Go 1.21+
clear(m)All keysYesReusing a map between batches
m = make(map[K]V)All keys, new mapNo — they keep the old mapShrinking after a big purge
m = nilThe whole mapNo — they keep the old mapDropping a map for good — writes then panic

6Deleting many keys — and the memory that stays

maps.DeleteFunc (Go 1.21+) deletes every entry matching a predicate, which is the in-place filter from section 3 with the loop written for you. Dropping a known list of keys is just a loop of delete calls — no existence checks, because misses are free. But neither shrinks the map: Go's runtime never releases a map's bucket array, so a map that held a million entries still occupies that space after you delete them all. If the purge was huge and the map is long-lived, copy the survivors into a fresh map and let the old one be collected.

bulk.go

Output

Prints [ann cy], then [ann] after the two deletes — one hit, one miss — then 2 [ann cy] from the rebuilt map. Sizing the new map with make(map[string]int, len(big)) avoids rehashing as it grows. The memory caveat is real but easy to over-apply: for maps that churn between a floor and a ceiling, delete and clear reusing those buckets is the point — only rebuild when the high-water mark is far above the steady state and the map outlives the spike.

Frequently asked questions

What happens if you delete a key that does not exist in a Go map?

Nothing. delete(m, key) on a key that is not in the map is a defined no-op — no error, no panic, and no return value to check. This is unlike Python, where del d[key] raises KeyError. It also means you never need to guard a delete with an existence check unless you specifically want to know whether something was removed.

Does delete return anything in Go?

No. delete is a builtin statement with no result, so you cannot write if delete(m, k) or capture the removed value. For pop semantics, do a comma-ok lookup first: v, ok := m[k]; if ok { delete(m, k) } — that gives you both the old value and whether the key was there.

Is it safe to delete map entries while iterating in Go?

Yes. The Go spec explicitly permits it: entries deleted during a range over a map will not be produced by that iteration, and entries already visited are unaffected. Adding entries mid-range is the unspecified case — a newly created key may or may not appear later in the same loop. Note that a map is not safe for concurrent use, so this only applies to a single goroutine; use sync.Map or a mutex otherwise.

How do I remove all keys from a Go map?

On Go 1.21+, clear(m) deletes every entry while keeping the same map, so every variable referencing it sees the empty map. Assigning m = make(map[K]V) instead creates a different map — other holders of the original keep seeing the old contents. Before 1.21, the idiom was for k := range m { delete(m, k) }, which the compiler optimises into the same operation clear performs.

Does deleting keys from a Go map free memory?

Not the map’s own storage. delete drops the key and value (so anything they pointed at can be collected) but the runtime never shrinks a map’s bucket array, and neither does clear. A map that peaked at a million entries keeps that footprint. When a large map is long-lived and has shrunk permanently, copy the survivors into a new map and drop the reference to the old one.

Can you delete a key from a nil map in Go?

Yes — delete(m, k) on a nil map is a no-op, just like reading from one. Only writing to a nil map panics with assignment to entry in nil map. That asymmetry means removal and lookup code works on a zero-value map without any make or nil check.