unexpected-go

Unexpected Golang behaviors

View on GitHub

You can’t remove a NaN key from a map without clearing it

Consider the following example code:

package main

import (
	"fmt"
	"math"
)

func main() {
	m := map[float64]string{
		1:          "one",
		math.NaN(): "not a number",
	}
	
	fmt.Println("Original: ", m)
	delete(m, 1)
	delete(m, math.NaN())
	fmt.Println("After deleting: ", m)
}

It will output:

Original:  map[NaN:not a number 1:one]
After deleting:  map[NaN:not a number]

As you can see, the NaN value is not removed from the map.

Why?

NaN values are not equal to themselves, so the delete() function can’t find the key to remove it.

Solution

You can completely clear the map by calling the clear() built-in function that was introduced in go1.21.0, or alternatively you can build a new map by iterating the original one, and skipping the NaN keys by using the math.IsNaN() function:

Extra

A corollary of NaN keys not being equal to other NaN keys is that you can have as many NaN keys as you want:

package main

import (
	"fmt"
	"math"
)

func main() {
	m := map[float64]string{
		math.NaN(): "first",
		math.NaN(): "second",
	}

	fmt.Println("Original: ", m)
	m[math.NaN()] = "third"
	fmt.Println("Modified: ", m)
}

Prints:

Original:  map[NaN:second NaN:first]
Modified:  map[NaN:third NaN:second NaN:first]