前言

Go官方团队在2022.12.08发布了Go 1.20 rc1(release candidate)版本,Go 1.20的正式release版本预计会在2023年2月份发布。

让我们先睹为快,看看Go 1.20给我们带来了哪些变化。

安装方法:

1
2
$ go install golang.org/dl/go1.20rc1@latest
$ go1.20rc1 download

这是Go 1.20版本更新内容详解的第4篇,欢迎大家关注公众号,及时获取本系列最新更新。

Go 1.20发布清单

和Go 1.19相比,改动内容适中,主要涉及语言(Language)、可移植性(Ports)、工具链(Go Tools)、运行时(Runtime)、编译器(Compiler)、汇编器(Assembler)、链接器(Linker)和核心库(Core library)等方面的优化。

第1篇主要涉及Go 1.20在语言、可移植性方面的优化,原文链接:Go 1.20版本升级内容第1篇

第2篇主要涉及Go命令和工具链方面的优化,原文链接:Go 1.20版本升级内容第2篇

第3篇主要涉及Go在运行时、编译器、汇编器、链接器等方面的优化,原文链接:Go 1.20版本升级内容第3篇

本文重点介绍Go 1.20在核心库方面的优化。

crypto/ecdh

Go 1.20新增了 crypto/ecdh 这个package,ecdh实现了Elliptic Curve Diffie-Hellman这个新的加密算法。

封装多个error

Go 1.20允许一个error变量里封装多个error。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
	"errors"
	"fmt"
)

func main() {
	err1 := errors.New("err1")
	err2 := errors.New("err2")
	err := errors.Join(err1, err2)
	fmt.Printf("%T, %v\n", err, err)
	if errors.Is(err, err1) {
		fmt.Println("err is err1")
	}
	if errors.Is(err, err2) {
		fmt.Println("err is err2")
	}
	err3 := fmt.Errorf("error3: %w", err)
	fmt.Printf("%T, %v\n", err3, errors.Unwrap(err3))
	if errors.Is(err3, err1) {
		fmt.Println("err3 is err1")
	}
	if errors.Is(err3, err2) {
		fmt.Println("err3 is err2")
	}
}

这段程序的输出结果为:

1
2
3
4
5
6
7
8
*errors.joinError, err1
err2
err is err1
err is err2
*fmt.wrapError, err1
err2
err3 is err1
err3 is err2

详情可以参考:https://pkg.go.dev/errors@master#pkg-overview

fmt.Errorf里带有%w参数,就会返回一个实现了Unwrap方法的error类型的变量。

HTTP ResponseController

net/http这个package新增了名为ResponseController的新类型。

1
2
3
4
5
func RequestHandler(w ResponseWriter, r *Request) {
  rc := http.NewResponseController(w)
  rc.SetWriteDeadline(0) // disable Server.WriteTimeout when sending a large response
  io.Copy(w, bigData)
}

A ResponseController is used by an HTTP handler to control the response.

A ResponseController may not be used after the Handler.ServeHTTP method has returned.

详情可以参考:https://pkg.go.dev/net/http@master#ResponseController。

Rewrite钩子函数

httputil.ReverseProxy 类型新增了一个 Rewrite 方法,这是一个钩子函数,用来取代之前的Director钩子函数。

1
2
3
4
5
6
7
proxyHandler := &httputil.ReverseProxy{
  Rewrite: func(r *httputil.ProxyRequest) {
    r.SetURL(outboundURL) // Forward request to outboundURL.
    r.SetXForwarded()     // Set X-Forwarded-* headers.
    r.Out.Header.Set("X-Additional-Header", "header set by the proxy")
  },
}

详情可以参考:https://pkg.go.dev/net/http/httputil@master#ReverseProxy.Rewrite。

标准库的修改

  • bytes

    新增了 CutPrefixCutSuffix 函数,这2个函数功能上类似 TrimPrefixTrimSuffix ,但是还会返回一个bool类型的变量,表示这个string是否被修改了。

    新增了 Clone 函数,会创建一个byte slice的拷贝。

  • encoding/binary

    ReadVarintReadUvarint函数如果读的数据的值被损坏,比如只写了一部分内容,会返回 io.ErrUnexpectedEOF,而不是像之前返回io.EOF

  • errors

    新的 Join函数可以把多个error变量的值组合在一起,封装为一个新的error变量。

  • fmt

    Errorf支持%w格式化字符串,可以返回一个实现了Unwrap方法的error类型变量。

  • strings

    新增了CutPrefixCutSuffix函数,这2个函数功能上类似 TrimPrefixTrimSuffix ,但是还会返回一个bool类型的变量,表示这个string是否被修改了。

    新增了 Clone函数,会创建一个string的拷贝。

  • sync

    Map 类型新增了3个新方法: SwapCompareAndSwapCompareAndDelete ,允许对已有的map做原子更新。

  • testing

    新增了B.Elapsed 方法,可以返回当前的benchmark性能测试耗时了多久。

  • time

    新增了3个常量DateTimeDateOnlyTimeOnly,方便开发者做格式转换,不用在代码里写死"2006-01-02 15:04:05"。

总结

Go 1.20版本即将在2023年2月份发布。

总体而言,Go 1.20版本没有大的修改,主要在细节方面做了各种优化。

推荐阅读

开源地址

文章和示例代码开源在GitHub: Go语言初级、中级和高级教程

公众号:coding进阶。关注公众号可以获取最新Go面试题和技术栈。

个人网站:Jincheng’s Blog

知乎:无忌

福利

我为大家整理了一份后端开发学习资料礼包,包含编程语言入门到进阶知识(Go、C++、Python)、后端开发技术栈、面试题等。

关注公众号「coding进阶」,发送消息 backend 领取资料礼包,这份资料会不定期更新,加入我觉得有价值的资料。还可以发送消息「进群」,和同行一起交流学习,答疑解惑。

References