我们现在使用的是Go 1.7.6版本。至于为什么从1.5开始总结,这是一个很重要的版本,实现方面有很多变化。最重要的是实现了自举。本文列出一些重大变化以及对我们升级有用的信息。
Go 1.5
该版本主要变化有以下几点
- 实现自举,使用少量汇编,用GO写GO。实现自举的目的是为了能更好的对GC管理优化
- 引入并发垃圾回收器,大幅降低GC延迟(Stop The World)
- 默认情况下,Go 程序运行时的 GOMAXPROCS 会被设置为可用的核数,之前默认为 1。再也不用手动去设置了
Map literals
Go1.4之前我们需要这样写代码:
1 | package main |
可以看到,对于i32
类型来说,在初始化一个切片时,无需显式的带上元素类型名称i32
,即
1 | var i = []i32{{1}, {2}} |
而不是需要传入名称:
1 | var i = []i32{i32{1}, i32{2}} |
但是当i32
作为map类型的key时,初始化map时则需要带上元素类型i32
。在Go 1.5版本修复了。也就是说,下面的代码在Go 1.5以及之后版本中可以顺利编译通过
1 | func main() { |
GO 1.6
该版本主要对GO的生态进行了调整
- 添加
linux/mips64
,linux/mips64le
,android/386
平台的实验性支持。 - go tool工具链调整,对位于我们升级意义不大。
- 运行时和大面积的标准库BUG修复和调整。
运行时
现在如果我们并发的map进行操作,GO会检测并抛出错误。Go 1.6之前版本,一旦程序以panic方式退出,runtime便会将所有goroutine的stack信息打印出来,现在只会打印正在running的goroutine的stack信息。
核心库和标准包
HTTP/2
Go 1.6已经标准库中已经支持HTTP/2。并且当使用https
时,client和server端将自动默认使用HTTP/2协议。
Templates
Go templates的空白字符包括:空格、水平tab、回车和换行符。Go 1.6提供了来帮助大家去除action前后的空白字符。示例
1 | package main |
输出hello<br>world
,<br>
左右的空白将会被清除。
Tls
crypto/tls
包现在如果没有指定证书也可以监听。
1 | package main |
Go 1.7
该版本的主要是对性能的影响
- 实验性的支持
linux/s390x
,plan9/arm
- 编译性能提升,编译出的文件变小
- 运行时和标准库BUG修复和调整
HTTP Tracing
引用net/http/httptrace
包对http请求进行追踪测试
测试
包testing
现在支持子测试(subtest),更好的支持表驱动测试和更细的粒度测试。
表格驱动测试:有时也被归为关键字驱动测试(keyword-driven testing,是针对自动化测试的软件测试方法,它将创建测试程序的步骤分为规划及实现二个阶段。
1 | package main |
平常我们是使用此方法测试,s1
是我们期望的结果,我们改造一下使用subtest
1 | // sub_test.go |
1 | === RUN TestEq/index_1#01 |
测试结果中index_1
是我们子测试的名称,这样我们可很清楚的知道那部分测试是有问题的。
核心标准库
Context
Go 1.7 已经将context上下文包引入到标准库中,可以直接import,轻松进行并发控制,平滑退出
1 | package main |
1 | 正在监控Goroutine |
Strings
strings
的Reader
的 Read
方法如果没有数据将会返回长度0和io.EOF
之前的版本不会产生错误!
Time
time.Duration 如果0时段,现在time.Duration.String
是0s
而不是0
1 | package main |
Go 1.8
此版本调整的地方
- GC延迟大幅降低,通常是100ms,大部分情况下都是10ms左右
- 正式支持
linux/mips64
,linux/mips64le
- 移除
go tool yacc
- 编译性能提升15%
- 默认安装Go之后
$GOPATH
默认路径为$HOME/go
,如果是Windows则是%USERPROFILE%/go
- Plugin的初步支持
语言
1.8 开始,tag不一样的struct可以执行显性转化。
1 | package main |
核心和标准库
Sort
1.8 之前版本,我们对自定义的slice排序需要实现sort.Inteface接口
1 | package main |
1.8 之后,我们可以使用更快的方式
1 | package main |
两种结果是一样的,省掉额外代码实现sort.Inteface接口
HTTP/2 Push
Go 1.8新增了对HTTP/2 Push的支持。
简单的介绍下HTTP/2 Push:从图中当Browser向Server发起Get page.html请求后,在同一条TCP Connection上,Server主动将style.css和image.png两个资源文件也推送给了Browser。这是由于Server端启用了HTTP/2 Push机制,并预测判断Browser很可能会在接下来发起Get style.css和image.png两个资源的请求。这些主动推送给Browser的资源很可能是Browser所不需要的或是已经在Browser cache中存在的资源,会造成带宽资源浪费。
HTTP Server 优雅退出
1.8 新增优雅退出的方法
1 | func (srv *Server) Shutdown(ctx context.Context) error |
我们传入一个上下文,当前有未处理完的active connections。将等待处理完,当然我们也不能无限等待下去,我们可以指定上下文的超时时间。
Go 1.9
该版本几点变化
- 引入类型别名
- 并行编译,速度大大提升
./…
不再匹配vendor目录- 新增并发map支持
sync.Map
语言
新的类型别名,类型别名声明方式
1 | type A = B |
type alias并未创造新类型,只是源类型的“别名”,在类型信息上与源类型一致,因此可以直接赋值。
1 | A.BValue = 2 |
也可以使用源类型的方法,但是不能定义新方法
1 | A.Bfunc() |
核心和标准包
Sync
新增并发map的支持,sync.Map
结构
Database/sql
如果Tx.Stmt
不可用,将会使用缓存好的Stmt
,这样是避免每次重新prepare
Math
Go 1.9提供了高性能math/bits
应对bit位的操作这个问题。
Go 1.10
该版本变化不大,几点特色:
- 默认的GOROOT,开发者无需显式设置GOROOT环境变量,go程序会自动根据自己所在路径推导出GOROOT的路径。
- 通过cache实现增量构建
- 新的环境变量
GOTMPDIR
- test的文件没有变化,那么test的结果会被缓存
核心和标准包
Strings
该包中添加了一个Builder
类型,可以用来字符串拼接。降低字符串的拼接的拷贝带来的内存分配和释放的性能损失。
Go 1.11
该版本添加了WebAssembly的支持,最重要是引入了包管理go moudle。启用go module
1 | export GO111MODULE=on |
初始化项目
1 | go mod init your-project |
此时使用go build
会自动下载包依赖构建。
对于被墙的包,可以设置代理
1 | export GOPROXY=https://goproxy.cn |
Go 1.12
该版本变化也很小
- GO111MODULE=on时,获取go module不再显式需要go.mod,go get 时不需要创建go.mod文件了-
- 添加对TLS 1.3的支持,默认不开启
- go安装包中移除go tour
Go 1.13
该版本变化也很小
GO111MODULE
的默认值继续auto
,但是只要当前目录包含go.mod
文件或位于go.mod
文件的目录下,auto
设置就会激活go命令的模块Go1.13这个版本引入了一个新的环境变量
GOPRIVATE
,用来指示私有的模块路径。1
2# 设置不走proxy的私有仓库,多个用逗号相隔
go env -w GOPRIVATE=*.corp.example.com1.13版本提高了
defer
性能达30%。
语言
- 新增数字表示方式0b0010 (二进制)、0o1276(八进制)、0x.8p-0(十六进制浮点)
核心和标准包
Sync
sync
包的Once.Do
方法比之前快了两倍,Mutex/RWMutex
方法的速度提高了10%。
Go 1.14
版本主要还是标准包的修改,语言结构上略有变化。
- defer性能继续提升,几乎可以忽略不计
time.After
,time.Tick
,net.Conn.SetDeadline
这些计时器修改减少资源竞争和上下文切换,性能提升
语言
interface类型相同的方法可以覆盖了,下面的代码在1.14之前无法编译通过
1 | package main |
1.14
之前版本报错
1 | # command-line-arguments |
工具链
- 1.14已经完全建议开发者使用go module版本管理。
- go.mod 包中的
+incompatible
标识的包本,如果模块的最新版本包含go.mod文件,则除非明确要求或已经使用该版本,否则go get将不再升级到该模块的不兼容版本。
核心和标准包
crypto/tls
- 移除SSLv3的支持
reflect
StructField
元素添加PkgPath字段,StructOf支持创建未导出的字段。
hash/maphash
- 标准库的新成员,用与字节哈希序列化,产生的结果单处理器上是一致性的,不同的处理器将产生不同结果,且不是密码安全的。