Go源代码中的那些秘密:time.minWall是1885?
前言前段时间 , 我在某个 Slack 工作区与朋友聊天:
朋友:“有人知道为什么time.minWall 的默认值是 1885 吗?” 我:“不知道 , 也许是从《回到未来 3》那一年开始的?”
我那么说基本是在开玩笑 , 因为我也不知道为什么将其设置为 1885 年 。 尽管其背后的事实与我在 Go 中的日常编码没有任何关系 , 但我还是情不自禁地询问了幕后花絮 。 我在团队聊天中问了我的同伴 Gophers , 但似乎没人能找到相关的线索 。
最后 , 我直接向 Russ Cox(@_rsc[1])发送了一封电子邮件 , 以了解背景 。
time.minWall一个 const 值time.minWall设置为 1885 , 在如下代码中:
- src/time/time.go[2]
const (hasMonotonic = 1 << 63maxWall= wallToInternal + (1<<33 - 1) // year 2157minWall= wallToInternal// year 1885nsecMask= 1<<30 - 1nsecShift= 30)
这是个常数值 , 它定义了时间包中值的时代 。 这是一个常量值 , 它定义了 time 包的时间纪元 。 我们经常使用 Unix 纪元(即 1970 年 1 月 1 日 UTC 的 00:00:00) , 但这只是几个用于表示日期时间值的标准或实现中的一个纪元 , 当然 Go 是一种多平台语言 , 因此 Go 中的纪元需要涵盖所有这些平台 。Russ Cox 在以下地方公开评论了 Go 的纪元 。 第一个是在 GitHub issue 上[3]:
已合入 Go 1.9 。 我将内部纪元移到 1885 年(最大年份为 2157 年) , 以避免 NTP 纪元派生的时间出现任何可能的问题 。 我还调整了设计文档 , 以调整此更改和一些较小的编码更改 。
但是这个评论只提到了为什么以及何时将内部纪元移到 1885 年 , 而没有提及为什么他们没有移至其他年份 , 例如 1900 年 。
第二个是内部纪元移动的提案文档 。
- 提案:Go 中的单调时间测量[4]
可见 , 理论依据也只是支持 1900 年之前的任何年份 , 而不是特指 1885 年 。 我几乎可以肯定 , 这一年来自“回到未来 3” , 但我想 100% 确定这一年 , 所以我联系了肯定知道这一点的人 , 即向 Russ Cox 发送了一封电子邮件 , 询问原因 。 他在一天之内做出了回应(考虑到 EDT 和 JST 之间的时区差异 , 这是非常快的):
是的 , 人们说服我移到 1900 年之前 , 而 1885 年是显而易见的选择 , 因为它对加利福尼亚的希尔山谷(Hill Valley)具有历史意义 。 :-)
这就是我知道的!!同样 , 我很高兴能够从谁做出决定中得到真正的答案 。
http.aLongTimeAgo尽管我很欣赏 Russ 的回答 , 但这还不是故事的结局 。 Russ 的回信中还有另外一行 。
另请参见 http.aLongTimeAgo , 现在将其设置为 time.Unix(1, 0) , 但以前是 time.Unix(233431200, 0) 。
正如他所说 , 在 Go1.15 中 , 它设置为time.Unix(1, 0) 。
- Go 1.15: src/net/http/http.go[5]
// aLongTimeAgo is a non-zero time, far in the past, used for// immediate cancellation of network operations.var aLongTimeAgo = time.Unix(1, 0)
【Go源代码中的那些秘密:time.minWall是1885?】因此 , 我们在源码中确认其原始值 。 你可以在 Go 1.8 中找到它 。- Go 1.8: src/net/http/http.go[6]
// aLongTimeAgo is a non-zero time, far in the past, used for// immediate cancelation of network operations.var aLongTimeAgo = time.Unix(233431200, 0)
我们将 UNIX 时间转换为人类可读的格式 。 当然 , Go 提供了超级简单的方法 。- 示例代码:以人类可读的格式读取 UNIX 时间[7]
package mainimport ("fmt""time")func main() {pdt, _ := time.LoadLocation("America/Los_Angeles")t := time.Unix(233431200, 0).In(pdt)fmt.Println(t)}
结果是:1977-05-25 11:00:00 -0700 PDT
我们得到 2 条提示:“A Long Time Ago”和 “1977-05-25” 。 这两个是:文章插图
当然 , 除了《星球大战:第四集》外 , 别无其他 。 它于1977年5月25日发布的Wikipedia:(film)
Go 包中如何使用此值呢?这是通过指定过去时间的截止日期来强制取消现有连接 , 例如:
cr.conn.rwc.SetReadDeadline(aLongTimeAgo)
当该值被改为 time.Unix(1, 0) 时 , 有人注意到了 , 因此对此作了一些评论(比如 1977-05-25 是谁的生日吗?) 。 我喜欢看到这些评论 。 这些有趣的聊天有时会在更改列表中进行 。- 脸上|那个被1亿锦鲤砸中的“信小呆”:失去工作后,脸上已无纯真笑容
- 夹缝|“互联网卖菜”背后:夹缝中的菜贩与巨头们的垄断
- 卷轴屏概念机|未量产一律按PPT手机处理!盘点那些华而不实的概念机
- 2021卷轴屏概念|“未来手机”初上手,谈谈OPPO卷轴屏带来的那些惊喜
- 骁龙865|5G手机中的性能怪兽,256+120W闪充,比iPhone12值得买
- RFID在冷链物流中的作用-RFID冷链资产管理解决方案
- 成员|千元机中的实力派再添新成员,三部千元机,一部更比一部强!
- Kotlin集合vs Kotlin序列与Java流
- 金融市场中的NLP——情感分析
- 二叉树:求搜索树中的众数