乐趣区

关于go:Go-120要来了看看都有哪些变化第2篇

前言

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

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

装置办法:

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

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

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

Go 1.20 公布清单

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

本文重点介绍 Go 1.20 在 Go 工具链方面的优化。

Go command

$GOROOT/pkg门路不再存储规范库源代码编译后生成的文件,包含以下几点:

  • go install不再往 $GOROOT/pkg 目录写文件。
  • go build不再查看 $GOROOT/pkg 下的文件。
  • Go 公布包不再带有这些编译文件。

以 macOS 环境来演示:在 Go 1.16 版本里,$GOROOT/pkg目录下的内容如下:

$ go version
go version go1.16.5 darwin/amd64
$ go env GOROOT
/usr/local/opt/go/libexec
$ ls /usr/local/opt/go/libexec/pkg
darwin_amd64        darwin_amd64_race    include            tool

然而在 Go 1.20rc1 版本里,$GOROOT/pkg目录下的内容如下:

$ go1.20rc1 version
go version go1.20rc1 darwin/amd64
$ go1.20rc1 env GOROOT
/Users/xxx/sdk/go1.20rc1
$ ls /Users/xxx/sdk/go1.20rc1/pkg
include    tool

少了 darwin_amd64darwin_amd64_race这 2 个文件夹:

$ ls /usr/local/opt/go/libexec/pkg/darwin_amd64
archive        database    go        io        net.a        runtime        testing.a
bufio.a        debug        hash        io.a        os        runtime.a    text
bytes.a        embed.a        hash.a        log        os.a        sort.a        time
cmd        encoding    html        log.a        path        strconv.a    time.a
compress    encoding.a    html.a        math        path.a        strings.a    unicode
container    errors.a    image        math.a        plugin.a    sync        unicode.a
context.a    expvar.a    image.a        mime        reflect.a    sync.a        vendor
crypto        flag.a        index        mime.a        regexp        syscall.a
crypto.a    fmt.a        internal    net        regexp.a    testing
$ ls /usr/local/opt/go/libexec/pkg/darwin_amd64_race/
archive        debug        hash        io.a        os        runtime.a    text
bufio.a        embed.a        hash.a        log        os.a        sort.a        time
bytes.a        encoding    html        log.a        path        strconv.a    time.a
compress    encoding.a    html.a        math        path.a        strings.a    unicode
container    errors.a    image        math.a        plugin.a    sync        unicode.a
context.a    expvar.a    image.a        mime        reflect.a    sync.a        vendor
crypto        flag.a        index        mime.a        regexp        syscall.a
crypto.a    fmt.a        internal    net        regexp.a    testing
database    go        io        net.a        runtime        testing.a

从 Go 1.20 开始,规范库的 package 会按需编译,编译后生成的文件会缓存在编译缓存 (build cache) 里,就像非 GOROOT 下的 package 一样。这个批改减小了 Go 安装包的大小。

go test -json的实现在 Go 1.20 版本更加鲁棒,对应用 go test -json 的开发者来说,不必做任何扭转。

然而,间接调用 Go 工具 test2json 的开发者,须要给测试的可执行程序减少 -v=test2json 参数,例如 go test -v=test2json 或者 ./pkg.test -test.v=test2json,而不是仅仅加一个-v 标记。

go test -json的另外一个批改是在每个测试程序执行的开始,减少了一个 Action 事件。当应用 go 命令同时运行多个测试程序时,这些 Action 事件的执行会依照命令行里的 package 的程序按序执行。

go命令当初新增了和 CPU 架构相干的编译标记参数,例如amd64.v2。有了这个参数后,在业务代码实现的时候就能够依据 CPU 架构的不同而做不同的解决。更多细节能够参考:go help buildconstraint

go子命令当初反对 -C <dir> 参数,能够在执行命令前扭转目录到 <dir> 下。如果一个脚本要在多个不同的 Go module 下执行,这个个性会带来不便。

go buildgo test 命令不再反对 -i 参数,这个参数从 Go 1.16 版本开始弃用。

go generate 命令承受 -skip <pattern> 参数,能够跳过匹配 <pattern>格局的 //go:generate 指令。

go test命令承受 -skip <pattern> 参数,能够跳过匹配 <pattern> 格局的测试用例。

go build, go install和其它编译相干的命令新增了一个 -pgo 标记参数,能够辅助开发者做程序优化。-pgo指定的是 profile 文件的门路。如果 -pgo=auto,那 go 命令会在 main 这个包的门路上来找名为default.pgo 的文件。-pgo=off能够敞开优化。详情能够参考:PGO Proposal。

go build, go install和其余编译相干的命令新增了一个 -cover 标记参数,能够用来对编译进去的可执行程序做代码覆盖率收集,详情能够参考本文前面介绍。

go version

go version -m命令反对读取和解析更多类型的 Go 二进制文件。

比方通过 go build -buildmode=c-share 编译进去的 Windows DLL 文件以及没有可执行权限的 Linux 二进制文件,当初都能够被 go version -m 解析和辨认到。

Cgo

晚期 Go 语言的一些规范库是用 C 语言实现的,须要依赖 cgo 来作为 go 语言和 C 语言的桥梁。

当初 Go 语言开始去除对 C 语言的的依赖。

从 Go 1.20 版本开始,如果机器上没有 C 语言的工具链,go 命令会默认禁用cgo

具体而言:如果没有设置 CGO_ENABLEDCC环境变量,而且默认的 C 语言编译器 (例如clanggcc)也找不到,那 CGO_ENABLED 会默认为 0。当然开发者能够通过设置 CGO_ENABLED 环境变量的值来扭转 CGO_ENABLED 的值。

这个批改会让 Go 语言缩小对 C 语言工具链的依赖,适配更多的环境,尤其是最小化的容器环境以及 macOS 环境。

Go 规范库里应用了 cgo 的 package 有:net, os/userplugin

在 macOS 环境,netos/user 包曾经被重写了,不再依赖 cgo。当初 netos/user的代码实现既能够用 cgo 编译,也能够不必 cgo 编译。同时,在 macOS 环境,race detector 曾经被重写了,不再依赖 cgo。

在 Windows 环境,netos/user 没有应用过 cgo。

在其它操作系统上,如果编译的时候禁用了 cgo,那会应用这些包的纯 go 语言实现。

在 macOS 环境,race detector 曾经被重写了,不再依赖 cgo。

Cover(代码覆盖率检测)

Go 1.20 版本之前只反对对单元测试 (unit test) 收集代码覆盖率,从 Go 1.20 版本开始反对对任何 Go 程序做代码覆盖率收集。

那如何收集呢?须要做如下操作:

  • go build 编译命令减少 -cover 标记
  • 给环境变量 GOCOVERDIR 赋值为某个门路
  • 运行 go build 编译进去的可执行程序时,会把代码覆盖率文件输入到 GOCOVERDIR 指定的门路下。

具体的介绍文档和应用阐明能够参考:coverage for integration tests’ landing page。

想理解设计原理和实现的能够参考:proposal。

Vet

检测循环变量被嵌套子函数谬误应用的场景

func TestTLog(t *testing.T) {t.Parallel()
    tests := []struct {
        name  string
        value int
    }{{name: "test 1", value: 1},
        {name: "test 2", value: 2},
        {name: "test 3", value: 3},
        {name: "test 4", value: 4},
    }
    for _, tc := range tests {t.Run(tc.name, func(t *testing.T) {t.Parallel()
            // Here you test tc.value against a test function.
            // Let's use t.Log as our test function :-)
            t.Log(tc.value)
        })
    }
}

大家能够猜一下这段程序里 t.Log 打印的后果是什么?后果是为 1,2,3,4 还是 4,4,4,4?是否和本人的预期相符。

想理解详情的能够参考:Be Careful with Table Driven Tests and t.Parallel()。

这个实质上和 goroutine 与闭包函数一起应用时,遇到的循环变量问题一样。

Go 1.20 版本开始通过 go vet 能够检测出单元测试里的这类问题。

查看谬误工夫格局

对于 Time.Formattime.Parse,如果代码里要转成 yyyy-dd-mm 的格局,会给出提醒。

因为 yyyy-dd-mm 不合乎罕用的日期格局规范,ISO 8601 日期格局是 yyyy-mm-dd 格局。

总结

下一篇会介绍 Go 1.20 在运行时、编译器、汇编器、链接器和外围库的优化工作,有一些内容值得学习,欢送大家放弃关注。

举荐浏览

  • Go 1.20 要来了,看看都有哪些变动 - 第 1 篇
  • Go 面试题系列,看看你会几题
  • Go 常见谬误和最佳实际系列

开源地址

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

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

集体网站:Jincheng’s Blog。

知乎:无忌。

福利

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

关注公众号「coding 进阶」,发送音讯 backend 支付材料礼包,这份材料会不定期更新,退出我感觉有价值的材料。还能够发送音讯「进群」,和同行一起交流学习,答疑解惑。

References

  • https://tip.golang.org/doc/go…
退出移动版