Go 大佬良心发现,愿意给 map 加清除了?

大家好,我是煎鱼。

一个东西来来回回的讨论,关了又开,关了后建新的,新的被 ban 了,又发现新的论据,再打开新的。这在职场工作中很常见,在 Go 的提案讨论中,也出现了。

今天要给大家介绍的是 map 在 NaN 上的一个小争议和可能即将出现的 API 增加。

背景和考题

NaN 是什么

在计算机科学中,有一个神奇的值,叫做:NaN(Not a Number,非数)。它是数值数据类型的一类值,表示未定义或不可表示的值。常在浮点数运算中使用。首次引入 NaN 的是 1985 年的 IEEE 754 浮点数标准。

在与 NaN 值的存储和比较时,会有问题。因为判断一个值是否为 NaN 时,不能通过判断 x=NaN 或 x≠NaN 来进行比较。但因为 NaN 永远不等于其自身,因此可通过判断 x=x 或 x≠x 来判断 x 是否为 NaN 值,将会分别返回 False 和 True。

当 NaN 与另一个浮点数 x(其中 x 可为正常值、正负无穷大或 NaN)进行比较时,比较结果如下:

比较结果
NaN ≥ xFalse
NaN ≤ xFalse
NaN > xFalse
NaN < xFalse
NaN = xFalse
NaN ≠ xTrue

这里的理解对于下面的考题很重要。

Go IEEE-754 考题

在 Go101 上看到一道关于 IEEE-754 浮点数的题,我这里引用题目,以下代码输出什么?

如下代码:

package main

import "math"

func main() {
    a, b, c := 2.0, 1.0, 0.0
    x, y := a/c, b/c     // infinity
    n := math.NaN()      // not a number
    m := math.Sqrt(-1.0) // not a number
    println(x == y, m == n)
}
  • A:true true。
  • B:true false。
  • C:false false。
  • D:false true。

答案是啥?是 A 吗,还是 D?

对上述程序进行解析,变量 x,y 是 +Inf 正无穷。m,n 是 NaN 无穷值。

正确的答案是:B。

你答对了吗?

提案

在对 NaN 有了基本的了解后,我们可以正式进入主题了。在 Go map 关联提案中,常提到新增 API,用于满足清空 map 的诉求:

但在多次讨论中,Go 官方团队给出的解决方案是:

for k := range m {
    delete(m, k)
}

并关闭了相关的提案,结束了这个议题。留下满脸 ”好吧,这都行“ 的疑惑打工人的我们,这是这类提案的背景。

但这块有一个坑,在包含任何 NaN 键值时,将无法通过循环 delete 的方式清空 map。一旦你 map 有 NaN,但你又 for+delete,以为删掉了,其实并没有,就会产生类似泄露的效果。

因此 Go 团队的灵魂人物 Russ Cox,重新发起了新提案《proposal: spec: add delete(m) to clear map to clear map")》。如下图:

希望借此来解决 map 在 NaN 的问题,并同时完成一直以来讨论的 map 清空/重置/清理等社区诉求。

也就是新增,如下特性:

delete(m)

支持清除 map 的功能(即使包含 NaN)。

总结

针对这个提案也有几种声音,分别是万恶的命名,对叫 delete,还是叫 clear 都有着不同的见解。

// Clear removes all entries from m, leaving it empty.
func Clear[M ~map[K]V, K comparable, V any](m M "M ~map[K]V, K comparable, V any")

delete(m)

也有声音提到不允许引入 NaN 值,但显然。在 Go1 已经很难了,因为 NaN 已经被允许引入,球已经在锅里了。

对于 map 新增 API 用于清空/重置/清除的作用,你怎么看呢?还是说你也更喜欢对 NaN 单独的处理?例如 panic?

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读

Go 图书系列


煎鱼的清汤锅
今天写代码了吗 :-) 博客地址:[链接]
8.2k 声望
12.7k 粉丝
0 条评论
推荐阅读
Go1.20 那些事:PGO、编译速度、错误处理等新特性,你知道多少?
最近 Go1.20 在 2 月 1 号已经正式发布,来的挺早的,以往都是拖到月底的,我翻了好几篇,发现最后还是做了不少功能取舍,放了些新特性(例如:arena 等)的鸽子!

煎鱼1

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木150阅读 12.3k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.2k评论 16

如何使用 PHPStorm 进行优雅的项目开发?
PHP Storm 这个开发工具,很多 phper 应该有所耳闻,甚至也有不少人使用其作为生产工具,但是很多人都没有最大限度的使用它,本文就来总结一些优雅开发的小技巧。

唯一丶45阅读 4.8k评论 7

从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木44阅读 7.4k评论 6

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木33阅读 6.2k评论 9

从零搭建 Node.js 企业级 Web 服务器(五):数据库访问
回顾 从零搭建 Node.js 企业级 Web 服务器(一):接口与分层,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,控制层与服务层实现了业务处理过程,模型层定义了业务实体并以 对象-关系...

乌柏木34阅读 4.6k评论 9

8.2k 声望
12.7k 粉丝
宣传栏