Go 1.1 Release Notes

Introduction to Go 1.1

2012年3月发布的Go版本1 (简称Go 1或Go 1.0)引入了Go语言和库的新稳定时期. 这种稳定性帮助滋养了全球不断增长的Go用户和系统社区. 此后发布了多个"点"发行版(1.0.1、1.0.2和1.0.3). 这些要点发布了已修复的已知错误,但未对实现进行非关键性的更改.

This new release, Go 1.1, keeps the promise of compatibility but adds a couple of significant (backwards-compatible, of course) language changes, has a long list of (again, compatible) library changes, and includes major work on the implementation of the compilers, libraries, and run-time. The focus is on performance. Benchmarking is an inexact science at best, but we see significant, sometimes dramatic speedups for many of our test programs. We trust that many of our users' programs will also see improvements just by updating their Go installation and recompiling.

本文档总结了Go 1和Go 1.1之间的更改. 即使需要修改任何代码才能在Go 1.1上运行,也很少有,尽管此发行版中出现了一些罕见的错误情况,如果出现,需要加以解决. 详细信息如下; 请参阅有关64位整数Unicode文字的讨论.

Changes to the language

Go兼容性文档承诺以Go 1语言规范编写的程序将继续运行,并且遵守这些承诺. 为了确保规范,这里有一些错误情况的详细说明. 还有一些新的语言功能.

Integer division by zero

在Go 1中,整数除以常数零会导致运行时恐慌:

func f(x int) int {
	return x/0
}

在Go 1.1中,将整数除以常数零不是合法程序,因此它是编译时错误.

Surrogates in Unicode literals

改进了字符串和符文文字的定义,以从有效的Unicode代码点集中排除代理半部分. 有关更多信息,请参见Unicode部分.

Method values

Go 1.1现在实现了方法值 ,这些方法值已绑定到特定的接收器值. 例如,在给定Writerw ,表达式w.Write (方法值)是将始终写入w的函数; 它等效于关闭w的函数文字:

func (p []byte) (n int, err error) {
	return w.Write(p)
}

方法值不同于方法表达式,后者从给定类型的方法生成函数. 方法表达式(*bufio.Writer).Write等效于带有一个额外的第一个参数的函数,即类型(*bufio.Writer)的接收器:

func (w *bufio.Writer, p []byte) (n int, err error) {
	return w.Write(p)
}

更新 :现有代码不受影响; 更改严格向后兼容.

Return requirements

在Go 1.1之前,返回值的函数需要在函数末尾进行显式"返回"或调用panic . 这是使程序员明确了解函数含义的简单方法. 但是在很多情况下,最终的"返回"显然是不必要的,例如只有无限的" for"循环的函数.

在Go 1.1中,有关最终"返回"语句的规则更为宽松. 它介绍了终止语句的概念,该语句保证是函数执行的最后一条语句. 示例包括无条件的" for"循环和" if-else"语句,其中每半均以" return"结尾. 如果可以将函数的最终语句在语法上显示为终止语句,则不需要最终的" return"语句.

请注意,该规则纯粹是语法上的:它不关注代码中的值,因此不需要复杂的分析.

更新 :更改是向后兼容的,但是带有多余的" return"语句和对panic情况的调用的现有代码可以手动进行简化. 可以通过go vet识别此类代码.

Changes to the implementations and tools

Status of gccgo

GCC的发布时间表与Go的发布时间表不一致,因此gccgo的发布中不可避免地会有一些偏差. GCC的4.8.0版本已于2013年3月发布,其中包含将近1.1的gccgo版本. 它的库比发行版要晚一些,但是最大的不同是没有实现方法值. 我们预计2013年7月左右的某个时候,GCC 4.8.2将随gccgo提供完整的Go 1.1实施.

Command-line flag parsing

在gc工具链中,编译器和链接器现在使用与Go标志包相同的命令行标志解析规则,这与传统的Unix标志解析不同. 这可能会影响直接调用该工具的脚本. 例如,必须将go tool 6c -Fw -Dfoo编写为go tool 6c -F -w -D foo .

Size of int on 64-bit platforms

该语言允许实现选择int类型和uint类型是32位还是64位. 先前的Go实现在所有系统上都将intuint 32位. 现在,gc和gccgo实现都可以在64位平台(例如AMD64 / x86-64)上将intuint 64位. 除其他外,这使得能够在64位平台上分配具有20亿个元素的分片.

更新 :大多数程序将不受此更改的影响. 因为Go不允许在不同的数字类型之间进行隐式转换,所以没有任何程序会由于此更改而停止编译. 但是,包含int仅32位的隐式假设的程序可能会更改行为. 例如,此代码在64位系统上打印一个正数,在32位系统上显示一个负数:

x := ^uint32(0) // x is 0xffffffff
i := int(x)     // i is -1 on 32-bit systems, 0xffffffff on 64-bit
fmt.Println(i)

打算使用32位符号扩展(在所有系统上均为-1 )的可移植代码将改为:

i := int(int32(x))

Heap size on 64-bit architectures

在64位体系结构上,最大堆大小已从几GB扩展到几十GB. (具体细节取决于系统,并且可能会更改.)

在32位体系结构上,堆大小没有更改.

更新 :除了允许它们以更大的堆运行之外,此更改对现有程序没有任何影响.

Unicode

为了能够在UTF-16中表示大于65535的代码点,Unicode定义了代理半部分 ,这是一系列代码点,仅在大值的汇编中使用,并且仅在UTF-16中使用. 该代理范围内的代码点出于任何其他目的都是非法的. 在Go 1.1中,编译器,库和运行时都遵循此约束:编码为UTF-8或单独编码为UTF-16时,代用半数作为符文值是非法的. 例如在从符文转换为UTF-8时遇到该错误,它将被视为编码错误,并将产生替换符文utf8.RuneError ,U + FFFD.

这个程序

import "fmt"

func main() {
    fmt.Printf("%+q\n", string(0xD800))
}

印刷"\ud800"在Go 1.0,但打印"\ufffd"在Go 1.1.

Surrogate-half Unicode values are now illegal in rune and string constants, so constants such as '\ud800' and "\ud800" are now rejected by the compilers. When written explicitly as UTF-8 encoded bytes, such strings can still be created, as in "\xed\xa0\x80". However, when such a string is decoded as a sequence of runes, as in a range loop, it will yield only utf8.RuneError values.

现在允许以UTF-8编码的Unicode字节顺序标记U + FEFF作为Go源文件的第一个字符. 尽管显然不需要以无字节序的UTF-8编码形式出现它,但一些编辑器还是将标记添加为一种"魔术数字",用以标识UTF-8编码文件.

更新 :大多数程序将不受代理更改的影响. 依赖旧行为的程序应进行修改,以避免出现此问题. 字节顺序标记更改严格向后兼容.

Race detector

A major addition to the tools is a 种族探测器, a way to find bugs in programs caused by concurrent access of the same variable, where at least one of the accesses is a write. This new facility is built into the go tool. For now, it is only available on Linux, Mac OS X, and Windows systems with 64-bit x86 processors. To enable it, set the -race flag when building or testing your program (for instance, go test -race). The race detector is documented in a separate article.

The gc assemblers

由于将int更改为64位并使用了新的函数内部表示形式,因此gc工具链中的函数参数在堆栈上的排列方式已更改. 至少需要调整以汇编语言编写的功能,以调整框架指针的偏移量.

更新go vet命令现在检查在程序集中实现的功能是否与他们实现的Go功能原型相匹配.

Changes to the go command

go命令获得了一些更改,旨在改善新Go用户的体验.

首先,当无法找到包时,当编译,测试或运行Go代码时, go命令现在将提供更详细的错误消息,包括搜索路径列表.

$ go build foo/quxx
can't load package: package foo/quxx: cannot find package "foo/quxx" in any of:
        /home/you/go/src/pkg/foo/quxx (from $GOROOT)
        /home/you/src/foo/quxx (from $GOPATH)

其次,当下载软件包源代码时, go get命令不再允许$GOROOT作为默认目标. 要使用go get命令,现在需要一个有效的$GOPATH .

$ GOPATH= go get code.google.com/p/foo/quxx
package code.google.com/p/foo/quxx: cannot download, $GOPATH not set. For more details see: go help gopath

最后,由于之前的更改,当$GOPATH$GOROOT设置为相同的值时, go get命令也会失败.

$ GOPATH=$GOROOT go get code.google.com/p/foo/quxx
warning: GOPATH set to GOROOT (/home/you/go) has no effect
package code.google.com/p/foo/quxx: cannot download, $GOPATH must not be set to $GOROOT. For more details see: go help gopath

Changes to the go test command

The go test command no longer deletes the binary when run with profiling enabled, to make it easier to analyze the profile. The implementation sets the -c flag automatically, so after running,

$ go test -cpuprofile cpuprof.out mypackage

文件mypackage.test将保留在运行go test的目录中.

go test命令现在可以生成性能分析信息,该信息报告goroutine在何处被阻止,也就是它们倾向于在等待事件(例如通道通信)时停滞的位置. 该信息显示为通过go test-blockprofile选项启用的阻止配置文件 . 运行go help test以获取更多信息.

Changes to the go fix command

fix命令通常以go fix形式运行,不再应用修订来更新Go 1之前的代码以使用Go 1 API. 要将Go 1之前的代码更新为Go 1.1,请使用Go 1.0工具链首先将代码转换为Go 1.0.

Build constraints

" go1.1 "标记已添加到默认构建约束列表中. 这使程序包可以利用Go 1.1中的新功能,同时仍与Go的早期版本兼容.

要仅使用Go 1.1及更高版本构建文件,请添加以下构建约束:

// +build go1.1

要仅使用Go 1.0.x构建文件,请使用相反约束:

// +build !go1.1

Additional platforms

Go 1.1工具链增加了对freebsd/armnetbsd/386netbsd/amd64netbsd/armopenbsd/386openbsd/amd64平台的实验支持.

freebsd/armnetbsd/arm需要ARMv6或更高版本的处理器.

Go 1.1在linux/arm上添加了对cgo实验性支持.

Cross compilation

交叉编译时,默认情况下, go工具将禁用cgo支持.

要显式启用cgo ,请设置CGO_ENABLED=1 .

Performance

对于大多数Go程序,使用Go 1.1 gc工具套件编译的代码的性能应该明显更好. 相对于Go 1.0的典型改进似乎约为30%-40%,有时更多,但偶尔更少甚至根本不存在. 在工具和库中有太多基于性能的小调整,无法在此处列出所有这些调整,但以下主要更改值得注意:

Changes to the standard library

bufio.Scanner

扫描bufio包中的文本输入的各种例程, ReadBytesReadString ,尤其是ReadLine ,对于简单的目的来说,不必要地很复杂. 在Go 1.1中,添加了一种新类型Scanner ,以使其更容易执行简单的任务,例如以行或空格分隔的单词的形式读取输入. 它通过终止对有问题的输入(如病理上较长的行)的扫描来简化此问题,并且具有一个简单的默认值:面向行的输入,每行都剥去了其终结符. 以下是一次重现输入内容的代码:

scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
    fmt.Println(scanner.Text()) // Println will add back the final '\n'
}
if err := scanner.Err(); err != nil {
    fmt.Fprintln(os.Stderr, "reading standard input:", err)
}

可以通过控制输入细分的功能来调整扫描行为(请参见SplitFunc的文档),但是对于棘手的问题或需要继续解决过去的错误,可能仍需要使用较旧的界面.

net

net程序包中特定于协议的解析器以前对于传入的网络名称比较松懈.尽管文档很清楚, ResolveTCPAddr的唯一有效网络是"tcp""tcp4""tcp6" ,但Go 1.0的实现默默地接受任何字符串. 如果网络不是这些字符串之一,则Go 1.1实现将返回错误. 其他协议特定的解析器ResolveIPAddrResolveUDPAddrResolveUnixAddr .

ListenUnixgram的先前实现返回了UDPConn作为连接端点的表示. Go 1.1实现返回一个UnixConn以允许使用其ReadFromWriteTo方法进行读写.

数据结构IPAddrTCPAddrUDPAddr添加了一个名为Zone的新字符串字段. 由于使用了新字段,因此使用未加标签的复合文字(例如net.TCPAddr{ip, port} )而不是加标签的文字( net.TCPAddr{IP: ip, Port: port} )的代码将中断. Go 1兼容性规则允许进行此更改:客户端代码必须使用带标记的文字,以避免此类损坏.

更新 :要纠正由新的struct字段引起的损坏, go fix将重写代码以添加这些类型的标签. 更一般而言, go vet会识别应修改为使用字段标签的复合文字.

reflect

reflect包有几个重要的补充.

现在可以使用reflect包运行"选择"语句. 有关详细信息,请参见SelectSelectCase的描述.

新方法Value.Convert (或Type.ConvertibleTo )提供了对Value执行Go转换或类型断言操作(或测试其可能性)的功能.

新函数MakeFunc创建了一个包装函数,使使用现有Values的函数更容易调用,在参数之间进行标准的Go转换,例如,将实际的int传递给形式interface{} .

最后,新函数ChanOfMapOfSliceOf从现有类型构造新的Types ,例如构造仅给定T的类型[]T

time

在FreeBSD,Linux,NetBSD,OS X和OpenBSD上,以前版本的time包以微秒精度返回时间. 这些系统上的Go 1.1实现现在返回的时间具有纳秒级精度. 以微秒精度写入外部格式并读回以期望恢复原始值的程序将受到精度损失的影响. 有两种新的Time方法, RoundTruncate ,可用于在将精度传递到外部存储之前从某个时间删除精度.

新方法YearDay返回由时间值指定的一年的一索引整数天数.

Timer类型具有新的Reset方法,该方法将计时器修改为在指定的持续时间后过期.

最后,新功能ParseInLocation类似于现有的Parse但是在位置(时区)的上下文中解析时间,而忽略了解析字符串中的时区信息. 此函数解决了时间API中常见的混乱原因.

更新 :需要修改使用较低精度的外部格式读取和写入时间的代码,以使用新方法.

Exp and old subtrees moved to go.exp and go.text subrepositories

为了使二进制发行版在需要时更易于访问它们,未包含在二进制发行版中的expold源子树已移至code.google.com/p/go.exp的新go.exp存储库中. . 例如,要访问ssa软件包,请运行

$ go get code.google.com/p/go.exp/ssa

然后在Go源代码中

import "code.google.com/p/go.exp/ssa"

旧的软件包exp/norm也已移至新仓库go.text ,其中将开发Unicode API和其他与文本相关的软件包.

New packages

有三个新软件包.

Minor changes to the library

下表总结了对该库的一些较小更改,主要是新增内容. 有关每个更改的更多信息,请参见相关的软件包文档.

by  ICOPY.SITE