内容简介:Go team如期在2月末言归正传,我们来看看Go 1.12版本中值得我们关注的几个变化。Go 1.12一如既往的保持了
Go team如期在2月末 发布了 Go 1.12 版本。从Go 1.12的 Release Notes 粗略来看,这个版本相较于之前增加了go modules机制、 WebAssembly支持 的Go 1.11,变化略“小”。这也给下一个 Go 1.13 版本预留了足够的“惊喜”空间:)。从目前的plan来看,Go 1.13很可能落地的包括:Go2的几个proposals: Go 2 number literals , error values 和 signed shift counts 等,以及 优化版Escape Analysis 等。
言归正传,我们来看看Go 1.12版本中值得我们关注的几个变化。
一. Go 1.12的可移植性
Go 1.12一如既往的保持了 Go1兼容性规范 ,使用Go 1.12编译以往编写的遗留代码,理论上都可以编译通过并正常运行起来。这是很难得的,尤其是在”Go2″有关proposal逐步落地的“时间节点”,想必Go team为了保持Go1付出了不少额外的努力。
Go语言具有超强的可移植性。在Go 1.12中,Go又增加了对aix/ppc64、windows/arm的支持,我们可以在运行于树莓派3的Windows 10 IoT Core上运行Go程序了。
但是对于一些较老的平台系统,Go也不想背上较重的包袱。Go也在逐渐“放弃”一些老版本的系统,比如Go 1.12是最后一个支持macOS 10.10、FreeBSD 10.x的版本。在我的一台Mac 10.9.2的老机器上运行go 1.12将会得到下面错误:
$./go version dyld: Symbol not found: _unlinkat Referenced from: /Users/tony/.bin/go1.12/bin/./go Expected in: flat namespace [1] 2403 trace trap ./go version
二. Go modules机制的优化
1. GO111MODULE=on时,获取go module不再显式需要go.mod
用过Go 1.11go module机制的童鞋可能都遇到过这个问题,那就是在GO111MODULE=on的情况下(非GOPATH路径),我要go get某个package时,如果compiler没有在适当位置找到go.mod,就会提示如下错误:
//go 1.11.2 # go get github.com/bigwhite/gocmpp go: cannot find main module; see 'go help modules' 或 # go get github.com/bigwhite/gocmpp go: cannot determine module path for source directory /Users/tony/test/go (outside GOPATH, no import comments)
这显然非常不方便。为了go get 一个package,我还需要显式地创建一个go.mod文件。在Go 1.12版本中,这个问题被优化掉了。
//go 1.12 # go get github.com/bigwhite/gocmpp go: finding github.com/bigwhite/gocmpp latest go: finding golang.org/x/text/encoding/unicode latest go: finding golang.org/x/text/transform latest go: finding golang.org/x/text/encoding/simplifiedchinese latest go: finding golang.org/x/text/encoding latest go: downloading golang.org/x/text v0.3.0 go: extracting golang.org/x/text v0.3.0
其他在go 1.11.x中对go.mod显式依赖的命令,诸如go list、go mod download也在Go 1.12版本中和go get一样不再显式依赖go.mod。
并且在Go 1.12中go module的下载、解压操作支持并发进行,前提是go module的Cache路径:$GOPATH/pkg/mod必须在一个支持file locking的文件系统中。
2. go.mod中增加go指示字段(go directive)
go 1.12版本在go.mod文件中增加了一个go version的指示字段,用于指示该module内源码所使用的 go版本。使用go 1.12创建的go.mod类似下面这样:
# go mod init github.com/bigwhite/test go: creating new go.mod: module github.com/bigwhite/test # cat go.mod module github.com/bigwhite/test go 1.12
按照release notes中的说法,如果go.mod中go指示器指示的版本高于你使用的go tool链版本,那么go也会尝试继续编译。如果编译成功了,那也是ok的。但是如果编译失败,那么会提示:module编译需要更新版本的go tool链。
我们使用go 1.11.4版本go compiler编译下面的上面github.com/bigwhite/test module的代码:
// main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("go world")
}
# go build main.go
# ./main
go world
我们看到,虽然go tool chain版本是1.11.4,低于go.mod中的go 1.12,但go 1.11.4仍然尝试继续编译代码,并且顺利通过。
如果我们将代码“故意”修改为下面这样:
//main.go
package main
import (
"fmt"
)
func main() {
fmt.Printl("go world") // 这里我们故意将Println写成Printl
}
再用go 1.11.4编译这段代码:
# go build main.go # command-line-arguments ./main.go:8:2: undefined: fmt.Printl note: module requires Go 1.12
我们看到go 1.11.4 compiler提示“需要go 1.12″版本编译器。从这里我们看出,我们可以使用go指示器用作module最低version约束的标识。在没有go指示器时,我们只能在文档上显式增加这种约束的描述。
不过,这里有一个小插曲,那就是这种不管go.mod中go版本号是多少,仍然尝试继续编译的机制仅适用于go 1.11.4以及后续高版本。从引入go module的go 1.11到go 1.11.3目前都还不支持这种机制,如果用go 1.11.3尝试编译以下上面的代码,会得到如下结果:
# go build main.go go build command-line-arguments: module requires Go 1.12
go 1.11.3不会继续尝试编译,而是在对比当前go tool chain版本与go.mod中go指示器的version后,给出了错误的提示并退出。
如果非要使用低于go 1.11.4版本的编译器去编译的话,我们可以使用go 1.12 工具 链的go mod edit -go命令来修改一下go.mod中的版本为go 1.11。然后再用go 1.11.4以下的版本去编译:
# go mod edit -go=1.11 # cat go.mod module github.com/bigwhite/test go 1.11 # go build main.go //使用go 1.11.3编译器
这样,我们就可用go 1.11~go 1.11.3正常编译源码了。
三. 对binary-only package的最后支持
我在2015的一篇文章 《理解Golang包导入》中提及到Go的编译对源码的依赖性。对于开源工程中的包,这完全不是问题。但是对于一些商业公司而言,源码是公司资产,是不能作为交付物提供给买方的。为此,Go team在Go 1.7中增加了对 binary-only package 的机制。
所谓”binary-only package”就是允许开发人员发布不包含源码的二进制形式的package,并且可直接基于该二进制package进行编译。比如下面这个例子:
// 创建二进制package
# cat $GOPATH/src/github.com/bigwhite/foo.go
package foo
import "fmt"
func HelloGo() {
fmt.Println("Hello,Go")
}
# go build -o $GOPATH/pkg/linux_amd64/github.com/bigwhite/foo.a
# ls $GOPATH/pkg/linux_amd64/github.com/bigwhite/foo.a
/root/.go/pkg/linux_amd64/github.com/bigwhite/foo.a
# mkdir temp
# mv foo.go temp
# touch foo.go
# cat foo.go
//go:binary-only-package
package foo
import "fmt"
# cd $GOPATH
# zip -r foo-binary.zip src/github.com/bigwhite/foo/foo.go pkg/linux_amd64/github.com/bigwhite/foo.a
updating: pkg/linux_amd64/github.com/bigwhite/foo.a (deflated 42%)
adding: src/github.com/bigwhite/foo/foo.go (deflated 11%)
我们将foo-binary.zip发布到目标机器上后,进行如下操作:
# unzip foo-binary.zip -d $GOPATH/ Archive: foo-binary.zip inflating: /root/.go/pkg/linux_amd64/github.com/bigwhite/foo.a inflating: /root/.go/src/github.com/bigwhite/foo/foo.go
接下来,我们就基于二进制的foo.a来编译依赖它的包:
//$GOPATH/src/bar.go
package main
import "github.com/bigwhite/foo"
func main() {
foo.HelloGo()
}
# go build -o bar bar.go
# ./bar
Hello,Go
但是经过几个版本的迭代,Go team发现: 对binary-only package越来越难以提供安全支持 ,无法保证binary-only package的编译使用的是与最终链接时相同的依赖版本,这很可能会造成因内存问题而导致的崩溃。并且经过调查,似乎用binary-only package的gopher并不多,并且gopher可以使用plugin、shared library、c-shared library等来替代binary-only package,以避免源码分发。于是Go 1.12版本将成为支持binary-only package的最后版本。
四. 运行时与标准库
经过 Go 1.5 ~Go 1.10对运行时,尤其是GC的大幅优化和改善后,Go 1.11、Go 1.12对运行时的改善相比之下都是小幅度的。
在Go 1.12中,一次GC后的内存分配延迟得以改善,这得益于在大量heap依然存在时清理性能的提升。运行时也会更加积极地将释放的内存归还给操作系统,以应对大块内存分配无法重用已存在的堆空间的问题。在 linux 上,运行时使用MADV_FREE释放未使用的内存,这更为高效,操作系统内核可以在需要时重用这些内存。
在多CPU的机器上,运行时的timer和deadline代码运行性能更高了,这对于提升网络连接的deadline性能大有裨益。
标准库最大的改变应该算是对 TLS 1.3 的支持了。不过默认不开启。Go 1.13中将成为默认开启功能。大多数涉及TLS的代码无需修改,使用Go 1.12重新编译后即可无缝支持TLS 1.3。
另一个”有趣“的变化是syscall包增加了Syscall18,依据syscall包中函数名字惯例,Syscall18支持最多传入18个参数,这个函数的引入是为了Windows准备的。现在少有 程序员 会设计包含10多个参数的函数或方法了,这估计也是为了满足Windows中“遗留代码”的需求。
五. 工具链及其他
1. go安装包中移除go tour
go tour被从go的安装包中移除了,Go的安装包从go 1.4.x开始到go 1.11.x变得日益“庞大”:以linux/amd64的tar.gz包为例,变化趋势如下:
go 1.4.3: 53MB go 1.5.4: 76MB go 1.6.4: 83MB go 1.7.6: 80MB go 1.8.7: 96MB go 1.9.7: 113MB go 1.10.8: 97MB go 1.11.5: 134MB go 1.12: 121MB
后续预计会有更多的非核心功能将会从go安装包中移除来对Go安装包进行瘦身,即便不能瘦身,也至少要保持在现有的size水平上。
本次go tour被挪到:golang.org/x/tour中了,gopher们可单独安装tour:
# go get -u golang.org/x/tour # tour //启动tour
Go 1.12也是godoc作为web server被内置在Go安装包的最后一个版本,在Go 1.13中该工具也会被从安装包中剔除,如有需要,可像go tour一样通过go get来单独安装。
2. Build cache成为必需
build cache在Go 1.10被引入以加快Go包编译构建速度,但是在Go 1.10和Go 1.11中都可以使用GOCACHE=off关闭build cache机制。但是在Go 1.12中build cache成为必需。如果设置GOCACHE=off,那么编译器将报错:
# GOCACHE=off go build github.com/bigwhite/gocmpp build cache is disabled by GOCACHE=off, but required as of Go 1.12
3. Go compiler支持-lang flag
Go compiler支持-lang flag,可以指示编译过程使用哪个版本的Go语法(注意不包括标准库变化等,仅限于语言自身语法)。比如:
//main.go
package main
import "fmt"
type Int = int
func main() {
var a Int = 5
fmt.Println(a)
}
# go run main.go
5
上面是一个使用了Go 1.9才引入的type alias语法的Go代码,我们使用Go 1.12可以正常编译运行它。但是如果我使用-lang flag,指定使用go1.8语法编译该代码,我们会得到如下错误提示:
# go build -gcflags "-lang=go1.8" main.go # command-line-arguments ./main.go:5:6: type aliases only supported as of -lang=go1.9
换成-lang=go1.9就会得到正确结果:
# go build -gcflags "-lang=go1.9" main.go # ./main 5
我的网课“ Kubernetes实战:高可用集群搭建、配置、运维与应用 ”在慕课网上线了,感谢小伙伴们学习支持!
我爱发短信 :企业级短信平台定制开发专家 https://51smspush.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。
著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个 链接地址 :https://m.do.co/c/bff6eed92687 开启你的DO主机之路。
我的联系方式:
微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite
微信赞赏:
商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。
© 2019,bigwhite. 版权所有.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Go 1.15 中值得关注的几个变化
- Go 1.11中值得关注的几个变化
- Go 1.14中值得关注的几个变化
- openCV之中值滤波&均值滤波(及代码实现)
- golang中值类型/指针类型的变量区别总结
- iOS知识梳理 - Objc语法中值得注意的东西
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
An Introduction to Genetic Algorithms
Melanie Mitchell / MIT Press / 1998-2-6 / USD 45.00
Genetic algorithms have been used in science and engineering as adaptive algorithms for solving practical problems and as computational models of natural evolutionary systems. This brief, accessible i......一起来看看 《An Introduction to Genetic Algorithms》 这本书的介绍吧!
随机密码生成器
多种字符组合密码
UNIX 时间戳转换
UNIX 时间戳转换