1 Go 1简介
Go 1对语言及核心库作了标准化定义。并声明之后发布的版本需遵守向后兼容的原则。
2 语言级变化
bytes := []byte{}
bytes = append(bytes, []byte("hello")...)
bytes = append(bytes, " world"...)
var c chan int
var csend chan<- int = c
var crecv <-chan int = c
close(c) // legal
close(csend) // legal
close(crecv) // illegal
type Date struct {
month string
day int
}
// Struct values, fully qualified; always legal.
holiday1 := []Date{
Date{"Feb", 14},
Date{"Nov", 11},
Date{"Dec", 25},
}
// Struct values, type name elided; always legal.
holiday2 := []Date{
{"Feb", 14},
{"Nov", 11},
{"Dec", 25},
}
// Pointers, fully qualified, always legal.
holiday3 := []*Date{
&Date{"Feb", 14},
&Date{"Nov", 11},
&Date{"Dec", 25},
}
// Pointers, type name elided; legal in Go 1.
holiday4 := []*Date{
{"Feb", 14},
{"Nov", 11},
{"Dec", 25},
}
使用如下命令可以简化构造代码gofmt -s x.go
var PackageGlobal int
func init() {
c := make(chan int)
go func() {
c <- 1
}()
PackageGlobal = <-c
}
The rune type 在Go 1之前,代码点是使用int类型来表示的。而因int类型在32位系统为32位位宽,在64位系统为64位位宽,这样,若int从32位变为64位,每个代码点会浪费32位的存储。为使转换至64位int更节省空间,Go 1引入一个新的基础类型rune来表示Unicode字符,与byte是uint8的别名相同,rune是int32的别名。如’a’, ‘中’, ‘\u0345’此类字符目前默认类型为rune。
The error type Go 1引入了一个新的内置类型,error,定义如下。
type error interface {
Error() string
}
delete(m, k)
m := map[string]int{"Sunday": 0, "Monday": 1}
for k, v := range m {
// This loop should not assume Sunday will be print first
fmt.Println(k, v)
}
Go 1采用从左至右对表达式或变量先估值,再从左至右进行赋值。
sa := []int{1, 2, 3}
i := 0
i, sa[i] = 1, 2 // sets i = 1, sa[0] = 2
sb := []int{1, 2, 3}
j := 0
sb[j], j = 2, 1 // sets sb[0] = 2, j = 1
sc := []int{1, 2, 3}
sc[0], sc[0] = 1, 2 // sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)
func Bug() (i, j, k int) {
for i = 0; i < 5; i++ {
for j := 0; j < 5; j++ { // Redeclares j.
k += i * j
if k > 100 {
return // Rejected: j is shadowed here.
}
}
}
return // OK: j is not shadowed here.
}
type Struct struct {
Public int
secret int
}
func NewStruct(a int) Struct { // Note: not a pointer.
return Struct{a, f(a)}
}
func (s Struct) String() string {
return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
}
在另一包对p.Struct进行赋值并拷贝,可以看到未导出的字段也会被赋值并拷贝。
import "p"
myStruct := p.NewStruct(23)
copyOfMyStruct := myStruct
fmt.Println(myStruct, copyOfMyStruct)
type Day struct {
long string
short string
}
Christmas := Day{"Christmas", "XMas"}
Thanksgiving := Day{"Thanksgiving", "Turkey"}
holiday := map[Day]bool{
Christmas: true,
Thanksgiving: true,
}
fmt.Printf("Christmas is a holiday: %t\n", holiday[Christmas])
3 包层次结构
Go 1对包作了梳理,删减与重命名,使其变得更紧凑简洁。
旧路径 新路径
asn1 encoding/asn1
csv encoding/csv
gob encoding/gob
json encoding/json
xml encoding/xml
exp/template/html html/template
big math/big
cmath math/cmplx
rand math/rand
http net/http
http/cgi net/http/cgi
http/fcgi net/http/fcgi
http/httptest net/http/httptest
http/pprof net/http/pprof
mail net/mail
rpc net/rpc
rpc/jsonrpc net/rpc/jsonrpc
smtp net/smtp
url net/url
exec os/exec
scanner text/scanner
tabwriter text/tabwriter
template text/template
template/parse text/template/parse
utf8 unicode/utf8
utf16 unicode/utf16
The package tree exp 包ebnf、html†(除EscapeString与UnescapeString仍在html包内),go/types已移到exp/下。
The package tree old old文件夹下的包不随Go 1发布版本发布,使用该包内容可从源码中找到。
Deleted packages Go 1已将如下包彻底删除,gotry命令也已删除。
container/vector
exp/datafmt
go/typechecker
old/regexp
old/template
try
4 核心库的几处大改动
type error interface {
Error() string
}
errors工具类包含一个创建error的函数。
func New(text string) error
System call errors Go 1中,对系统调用错误会返回error。
Time 之前Go time包未对绝对时间与时间段作区分。Go 1重新设计了time,用time.Time表示时刻,用time.Duration表示时间段,都含有最高纳秒级的精度。Time可以表示一个从远古至未来的任意一刻,而Duration的跨度仅为加上或减去290年。如下代码示例了使用方式。
// sleepUntil sleeps until the specified time. It returns immediately if it's too late.
// sleepUntil sleeps until the specified time. It returns immediately if it's too late.
func sleepUntil(wakeup time.Time) {
now := time.Now() // A Time.
if !wakeup.After(now) {
return
}
delta := wakeup.Sub(now) // A Duration.
fmt.Printf("Sleeping for %.3fs\n", delta.Seconds())
time.Sleep(delta)
}
5 核心库的几处小改动
https://golang.org/doc/go1#minor
6 go命令
Go 1引入了一组支持拉取、构建,包安装等的go命令,从此无需再用makefile来构建go应用了。
7 cgo命令
Go 1中,cgo命令对使用//export注释的包生成了不同的文件_cgo_export.h。会对前序语言编译多次,所以使用//export语句的包,切勿将函数定义与变量初始化放在C前序语言中。
参考资料