Go语言中NaN是否为可比较类型?为何可作为map键使用?
Go中NaN作为map键的行为解析
核心问题解答
NaN属于可比较类型吗?
float64(以及float32)是Go语言定义的可比较类型,因此可以作为map的键。这不是编译器Bug,完全符合Go语言规范。但需要注意:IEEE 754浮点数标准规定,NaN与任何值(包括自身)的比较结果都是false,这是NaN的特殊特性,也是后续异常行为的根源。为什么代码中map的长度最终是2?
我们逐行分析代码逻辑:
package main var x = 0.0 func main() { var a = x / x // a = NaN,符合IEEE 754标准的计算结果 var m = map[float64]int{a: 1} // 存入第一个NaN键的条目 m[a] = 2 // 由于a(NaN)与已有的NaN键比较结果为false,map会新增一个条目而非覆盖 for k := range m { delete(m, k) // 尝试删除遍历到的键,但k是NaN,k == k为false,map无法找到匹配的键,删除操作无效 } println(len(m)) // 两个条目都未被删除,输出2 }
- 当向map存入NaN键时,由于NaN无法与自身相等,后续使用同一个NaN变量赋值时,map会将其视为新键,导致重复存入。
- 遍历delete时,因为遍历得到的k是NaN,而map判断键匹配的依据是
==比较,k == k结果为false,因此delete操作无法定位到对应的键,自然无法删除任何条目。
总结
Go允许float类型作为map键,NaN作为float的有效值可以被存入,但由于其特殊的比较特性,会导致看似异常的行为——无法通过自身变量覆盖或删除对应的map条目。这是标准规定的特性,而非编译器Bug。
内容的提问来源于stack exchange,提问作者Kushal Billaiya
相关产品推荐
相关产品推荐

