Skip to content

Latest commit

 

History

History
93 lines (69 loc) · 2.2 KB

clear-removes-map-keys-but-keeps-slice-indexes.md

File metadata and controls

93 lines (69 loc) · 2.2 KB
Error in user YAML: (<unknown>): found character that cannot start any token while scanning for the next token at line 1 column 8
---
title: `clear()` removes map keys but keeps slice indexes
description: The built-in `clear()` function removes all the keys from a map, but it does not remove the indexes from a slice.  
---

clear() built-in function removes map keys but keeps slice indexes

The documentation for the clear() built-in function that was introduced in go1.20.0 states this clearly:

For maps, clear deletes all entries, resulting in an empty map. For slices, clear sets all elements up to the length of the slice to the zero value of the respective element type.

While documented and correct, this still falls into "unexpected" behaviors category.

For example this code:

package main

import (
	"fmt"
)

func main() {
	m := map[string]int{"one": 1, "two": 2}
	s := []int{1, 2}

	fmt.Println("Original:")
	fmt.Printf("m=%#v (len %d)\n", m, len(m))
	fmt.Printf("s=%#v (len %d)\n", s, len(s))
	fmt.Println()

	clear(m)
	clear(s)
	fmt.Println("Cleared:")
	fmt.Printf("m=%#v (len %d)\n", m, len(m))
	fmt.Printf("s=%#v (len %d)\n", s, len(s))
	fmt.Println()
}

Prints:

Original:
m=map[string]int{"one":1, "two":2} (len 2)
s=[]int{1, 2} (len 2)

After clear():
m=map[string]int{} (len 0)
s=[]int{0, 0} (len 2)

As you can see, the length of the map is zeroed, while the length of the slice remains the same, but the values are zeroed.

Why?

Consider reading the spec issue on the official golang repository for more context.

One of the reasons might be that you can't always remove all keys from a map using the delete() function, while there's a builtin syntax for changing a slice length.

Extra

It's also worth mentioning that clear() clears up to the length of the provided slice, not up to it's capacity, for example:

package main

import (
	"fmt"
)

func main() {
	s := []int{1, 2}
	fmt.Println("Original:")
	s = s[:1]
	clear(s)
	fmt.Println("Cleared:")
	fmt.Println(s)
	s = s[:2]
	fmt.Println("Extended:")
	fmt.Println(s)
}

Outputs:

Original:
Cleared:
[0]
Extended:
[0 2]