Go 1.18 是一个大版本,具有泛型、模糊测试和工作空间等巨大功能。它的次要甚至超次要功能令人兴奋。Go 1.19不是那个规模的版本。但它确实包含了许多可以帮助普通 Go 开发人员的小改进。让我们来看看其中一些是什么。

全新 Go 1.19 到底有什么新功能?插图

新的url.JoinPath

url.JoinPath是 url 包中的一个新函数和方法对,它执行它在 tin 上所说的内容。Github 上一位名为wanglong001的用户提出了该功能,我们在问题中讨论了实现细节。我对它特别感兴趣,因为我刚刚为我的 HTTP 请求库开发了 URL 路径连接功能。

新的time.Duration.Abs()

此功能源于在生产中咬我的一个错误。? 如果你有两个time.Times 并且想知道它们是否在 N 分钟内,你可以尝试减去它们,如果它是负数,则将差值转换为正数,然后查看该持续时间是否小于 N 分钟。这是行不通的,因为负数比正数多time.Duration表示一纳秒,因为它只是一个普通的隐蔽签名。这将在两者之一为零时出现,因为零时间比.int64time.Timestime.Duration

在 Go 1.19 中,新方法time.Duration.Abs()通过在饱和情况下舍入来解决问题。

在我打开问题后,Russ Cox 一如既往地帮助我找到更好的解决方案。

新的http.MaxByteError

这个问题的根本问题可以追溯到 2019年。和 一样http.MaxBytesHandler,促使我努力解决这个问题的原因是阅读了Alex Edwards的《让我们走得更远》 。问题是,如果您使用并希望将正确的错误消息返回给有故障的客户端,那么从现在开始就没有可靠的方法来检测错误。您只需要查看错误字符串,看看它是否是. 如果 Go 团队曾经更改过这个错误字符串,检查就会中断。http.MaxBytesReaderhttp.MaxBytesReader"http: request body too large"

http.MaxBytesError功能可让您可靠地errors.As检查错误并发送正确的响应。它还可以让您查看客户端超出的限制。

第一次在标准库中使用泛型

多年来,我们都在等待 Go 获得泛型,但 Go 团队故意选择暂时将泛型推出标准库​​的速度放慢。

好吧,眨眼,你会错过它,但这是标准库中第一个使用泛型的新 API atomic.Pointer[T]:.

在以前的 Go 版本中,您可以使用atomic.StorePointer和朋友来实现相同的功能,因此这并不是一个真正的新功能,但它是使用该功能的一种更方便的方式。

这些新特性源于Russ Cox修改Go 的内存模型的工作。和以前一样,内存模型警告说:“如果你必须阅读本文档的其余部分才能理解程序的行为,那你就太聪明了。” 对于大多数程序员来说,变化的长短在于 Go 现在记录了它的内存模型保证与其他语言或多或少相似,但普通程序员编写的代码应该没有任何变化。

Go 文档改进

Go 的一个很好的特性一直是 go 工具的各个部分如何协同工作:它使用 格式化代码go fmt,使用 运行测试go test,并使用go doc. 但是,go doc预期的确切格式有点神秘。它支持标题、列表和块引用,但你必须知道阅读正确的 Github 存储库才能弄清楚如何去做。

幸运的是,对于 Go 1.19,已经澄清了预期的格式go doc,现在甚至go fmt可以清理文档注释的某些格式问题。您还可以在您的文档注释中包含链接,它应该在pkg.go.dev上正确显示。

软内存限制

Go 刻意限制了可用于调整垃圾收集的“旋钮”的数量,以试图让大部分用户都能正常工作。通过设置GOGC,您可以根据分配的新内存与剩余旧内存的百分比来告诉 Go 何时触发下一轮垃圾收集。这导致了一些奇怪的技巧,比如Twitch 的“内存镇流器”优化,他们试图通过分配一大块他们实际上并不需要的内存来平滑垃圾收集。

Go 1.19 增加了一个软内存限制,可以通过环境变量GOMEMLIMITruntime/debug.SetMemoryLimit. Michael Knyszek 为这个问题撰写了提案,该提案应该使“内存镇流器”过时,并使其更容易在手机和平​​板电脑等具有大量 RAM 但有硬上限的设备中使用 Go。它本质上设置了一个目标并随着使用的内存量接近该目标而触发越来越激进的垃圾收集(在 CPU 限制内)。

更多 AppendX 功能

添加bufio.Writer.AvailableBuffer()了Go 1.18以使低级附加到预分配字节切片模式更易于使用。

Go 1.19 通过添加fmt.Appendfmt.Appendffmt.Appendln大大扩展了这种模式。这些函数的工作方式与fmt.Print等类似,但它们不是打印到标准输出或io.Writer字符串,而是附加到字节切片,从而可以非常精确地控制内存分配。

新的flag.TextVar

我是flag package 的忠实粉丝,所以我总是很高兴看到它的改进。该flag.TextVar函数和方法允许您使用任何直接作为标志实现encoding.TextUnmarshaler的类型,而无需编写适配器。已经实现 TextUnmarshaler 的一些示例类型是big.Intnet.IPtime.Time

sort.Find的排序算法

虽然我们正在等待slices.Sort被添加到标准库(承诺加速),但好的旧排序包正在自己做一些改进。Rob Pike提出 sort.Find,这是一种在预排序序列中搜索项目的新方法

此外,对算法进行sort.Sort了微调,以使用击败快速排序变体的模式。平均而言,在最坏的情况下,它仍然是 O( n log n ),但在某些情况下它可以达到 O( n ) 的最佳情况时间,例如当序列已经排序时。