距离2013.08.12正式发布Go1.1.2大约1个月了. 目前Go语言已经进入Go1.2的发布流程, 预计将在2013年底发布.
本文主要列举Go1.2的一些大的改进, 并会持续保持更新.
语言的改变
禁止nil对象取值
对于Go1.0, 有以下代码:
type T struct {
X [1<<24]byte
Field int32
}
func main() {
var x *T
}
操作 x.Field
将会对应到 1<<24
位置的内存.
在Go1.2中, 将导致 panic
或 错误.
切片语法增加cap域
之前在切片时, cap默认为最大. 比如:
var array [10]int
slice := array[2:4]
slice
的容量是8. 在Go1.2中, 如希望容量为6, 可以这样:
slice = array[2:4:6]
如果第一部分的开始地址省略, 则默认为0.
有了可定制的cap语法,就可以自己new一个大内存,然后自己构造malloc/free内存管理函数了。
每次malloc返回的slice的cap被严格限定为申请的size。
该语法的设计文档: https://docs.google.com/document/d/1GKKdiGYAghXRxC2BFrSEbHBZZgAGKQ-yXK-hRKBo0Kk/pub
cgo支持C++源码
CGO支持函数指针, 用法请参考 https://code.google.com/p/go/source/browse/misc/cgo/test/fpvar.go.
CGO支持C++语法, 但是只支持C语言的导入符号.
针对C++增加了 CPPFLAGS
和 CXXFLAGS
参数设置选项.
比较适合用C语言导出, 但是用C++实现的库.
注: windows版本的MinGW还不支持外部链接, 详情请参考 Issue6533.
runtime实现的变化
goroutines 的函数入口采用抢占式调度.
在之前的版本中, 如果goroutines内部有死循环, 那么其他的 goroutines 可能无法获取此线程的CPU资源, 特别是在 GOMAXPROCS 设置为 1 个线程的时候.
在Go1.2中部分解决了此问题: 调度器会在函数的 入口处被偶尔触发. 也就是说, 如果任何循环 内部调用了一个非内联的函数的话, 其他goroutines 也将有机会在同一个线程执行.
在Go1.2, goroutine 的默认堆栈大小临时由4KB改为8KB. 新改的8KB大小对于很多实际的程序可以带来一定的性能提升. 当然, 更大的默认堆栈也导致了程序可能使用更多的内存, 在后续的Go开发中采用更好的堆栈技术解决这个问题.
同时goroutine的栈有最大限制(不是无限的), 64位系统默认限制为1GB,
32位系统模型限制为250MB.
如果需要调整默认值, 可以调用 runtime/debug
包的 SetMaxStack
函数修改.
具体请参考: CL12541052
程序开启的系统线程有增加了最大数量限制(默认为10000).
如果需要调整默认值, 可以调用 runtime/debug
包的 SetMaxThreads
函数修改.
具体请参考: CL13037043
关于动态库支持
Linux/Arm 版本已经支持外部链接. 这是Go的编译工具链支持动态库特性的一个关键环节.
gccgo的状态
期望GCC4.9能包含完整的Go1.2. 目前的GCC4.8.2包含Go1.1.2.
性能优化
- compress/bzip2: 30%的性能提升
- crypto/des: 5倍的性能提升
- encoding/json: encoding 30% 的性能提升
- net: windows/BSD下 网络和
runtime
的深度集成(Linux/OS X在Go1.1已经支持), 30% 的性能提升
标准库的变化
较大的变化有:
- encoding: 新包, 提供通用的
encoding
接口 - fmt: 引入参数索引支持, 主要是处理不同语言翻译之后参数顺序的变化
- sync/atomic: 增加了
Swap
函数 - text/template: 增加
eq
/lt
等比较函数, 增加{{else if ... }}
简化语法 - runtime: 简化
SetFinalizer
参数f
的参数类型的限制, 只要可赋值即可 - testing: 增加的
TB
接口 image/gif
增加了encode
函数- MD5/HASH等增加便利的函数
fmt新支持的参数索引:
fmt.Printf("%[3]c %[1]c %[1]c %c\n", 'a', 'b', 'c')
// output: c a a b
简化的HASH用法:
hash := sha1.Sum([]byte("123"))
fmt.Printf("H(data) = %x\n", hash)
杂项消息(个人补充)
- go 命令行工具迁移到
go.tools
, 并将大幅改进版面 go.text/encoding
增加了 GBK 的支持, 彻底解决中文Windows命令行中文乱码问题.go.image
增加了 bmp 的保存 和 分块 tiff 的读取支持, 目前还不支持超大tiff图像.- notepad++ 更好的高亮显示, builtin函数的自动补全, 函数/方法列表等功能.