译自 tylerchr 的 What's Coming in Go 1.8。
随着Go 1.8 新特性的开发工作已经冻结,Go 1.8 将在2017年2月左右发布,现在让我们看一些在Go 1.8更有趣的API的改变。
HTTP server connection draining
Brad Fitzpatrick最近关闭了一个将近四年的issue,这个issue请求实现http.Server
的连接耗尽(draining)的功能。现在可以调用srv.Close
可以立即停止http.Server
,也可以调用srv.Shutdown(ctx)
等待已有的连接处理完毕(耗尽,draining, github.com/tylerb/graceful 的用户应该熟悉这个特性)。
下面这个例子中,服务器当收到SIGINT
信号后(^C
)会优雅地关闭。
|
|
一旦收到SIGINT
信号,服务器会立即停止接受新的连接,srv.ListenAndServe()
会返回http.ErrServerClosed
。srv.Shutdown
会一直阻塞,直到所有未完成的request都被处理完以及它们底层的连接被关闭。
更复杂的处理可以通过context
实现,例如使用context.Timeout
实现最大的关闭等待时间。你可以尝试复制 https://github.com/tylerchr/examples/tree/master/draining 中的例子并实现它。
通过 http.Pusher
实现 HTTP/2.0 server push
HTTP/2.0 包含 Server Push 特性, 允许 HTTP/2 服务器主动地发送额外的 HTTP response 给客户端,即使客户端没有发送请求。目标是在客户端无需请求的情况下,服务器可以及时地将客户端所需的资源推送给客户端。可以查看wiki HTTP/2 Server Push看具体的例子。
如果一个服务器支持 HTTP/2
, 提供给 handler 的 http.ResponseWriter
会实现 http.Pusher
接口。Handler 可以使用这个功能区触发Server Push, 虚拟的请求(synthetic request)可以被注册的 http.Server Handler所处理。
下面的程序处理/index.html
, 可以push一个/static/gopher.png
:
|
|
你可以从 https://github.com/tylerchr/examples/serverpush 克隆这个例子,下面是在 Chrome 54 访问的结果:
明显地可以在 Initiator 那一列中看到 gopher.png
被 Push
,你也可以看到标蓝色的gopher.png
先于/index.html
被接收过来,这表明这个资源先于请求之前被推送到客户端。HTML下载完后<img>
可以显示。
有人可能会问如何写一个测试用来校验实现 Server Push的 Handler。因为http.NewTLSServer
没有启动 HTTP/2 服务器,httptest.ResponseRecorder
也没有实现http.Pusher
。我的解决方案是包装httptest.ResponseRecorder
实现Pusher
接口,这里有个例子。
database/sql
database/sql
包有几个主要的改变,可以让用户更好的控制数据库查询,允许用户更好的利用数据库的特性。
- 查询可以使用
context.Context
取消查询 - 纯数据库列类型可以通过
sql.ColumnType
得到 - 如果底层数据库支持,查询可以使用命名参数
更多的细节可以阅读Daniel Theophanes的文章 What is new in database/sql?,他实现了大部分的改变。
plugin包实现动态插件
新增加的标准库plugin
提供了初步的插件支持,它允许程序可以在运行的时候动态的加载插件。
但是这个库看起来还是bug多多,我甚至不能写一个正常的程序来测试它,但是假定它的使用应该如下面的样子:
|
|
|
|
在这个例子中,hexify.go
实现了Hexify
函数,它被编译成一个共享库,第二个程序动态加载它。这允许Go程序可以不在编译的时候也能调用其它的库。
别名
别名(aliasing)曾被增加到 Go 1.8 的语言规范中,但是现在又被移除了,看这个说明: this post from Russ Cox,有可能会出现在 Go 1.9中。
这个特性也引起了很多的争议,
指示符别名(Identifier aliasing)用来定义多个类型为同一个类型的语法。一个用处用来重构复杂的代码的时候,允许重新划分包而不必带来类型的不一致。 Ian Lance Taylor举了一个[例子](https://groups.google.com/d/msg/golang-dev/OmjsXkyOQpQ/OrcHWiGUBAAJ):
举个具体的例子,将扩展包
golang.org/x/net/context
移动到标准库context
的过程。因为context已经被广泛地使用,将所有的用户的代码统一转换很困难,因此允许这两个包通用很有必要。
别名的定义如下:
|
|
这个语法定义 Foo
是 pkg.Bar
别名。Foo
可以用在任何pkg.Bar
出现的地方。以上个例子为例,任何需要类型golang.org/x/net/context
的地方都可以用标准库context
代替,它们是等价的。
别名也可以用在常量、变量、函数等类型上。
这是一个很有争议的特性,可以参考issue 16339和golang-dev post 看大家的讨论。因为它从Go 1.8中移除了,大家可以暂时不用关注这个特性了。
新的slice排序API
统一的slice排序由新的 sort.Slice 函数实现。它允许任意的slice都可以被排序,只需提供一个回调比较函数即可,而不是像以前要提供一个特定的sort.Interface
的实现。这个函数没有返回值。想其它的排序函数一样,它提供了原地的排序。
下面的例子根据海拔高度排序知名山峰的slice。
|
|
通过sort.Interface
类型的Len()
和Swap(i, j int)
提供了抽象的排序类型,这是以前的排序方法,而Less(i, j int)
作为一个比较回调函数,可以简单地传递给sort.Slice
进行排序。
其它
- 87b1aaa
encoding/base64
encoder现在有了严格模式. - 6ba5b32
expvar
暴露出来,可以用在其它的mux中. - 003a598 伪随机码可以通过
rand.Uint64()
产生 (先前仅支持uint32). - 67ea710 增加了一个新的
time.Until
函数,和time.Since
对应.
net/http
故意只实现了使用TLS的HTTP/2,你可以查看[issue 14141]https://github.com/golang/go/issues/14141()了解细节。
sort.SliceStable
提供了稳定的slice排序,就像以前的sort.Stable
一样。
译者增加的内容
Go 1.8 一个很大的特性就是性能的提升,包括二进制文件的大小、编译速度和运行速度。
并且非常大的提升就是提供小于100us GC暂停。
net/http
提供了更多的超时设置,比如ReadHeaderTimeout
、IdleTimeout
。
一个完整的改动列表:Go 1.8