Go1.1新特性介紹(語言和庫更完善/效能提高約30%)

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

前幾天GCC4.8發布, 已經部分包含Go1.1特性, 詳細介紹:

  • http://gcc.gnu.org/gcc-4.8/changes.html#go

根據golang-nuts的訊息, 4月第1周可能會進入Go1.1發布流程(就是下周).
要修複的問題還剩20多一點的, 估計應該不會出現大的延期.

  • http://swtch.com/~rsc/go11.html

Go1.1主要的目標是效能的最佳化和一些bug的修複, 詳細內容參考:

  • https://go.googlecode.com/hg/doc/go1.1.html
  • http://tip.golang.org/doc/go1.1

Go1.1的更新主要涉及 語言/實現/效能最佳化/標準庫 幾個部分.

補充:

  • Go1.1正式版本已經於2013.05.14正式發布
  • Go1.1的二進位安裝包將包含gotour程式(啟動命令: go tool tour, 但是還有點問題).
  • gccgo1.1的發布流程和GCC4.8.1同步.
  • 和C的效能對比請參考: Go1.1效能測試報告(和C差距在10%以內)

語言的改變

Go1發布時曾作出承諾, 保證在Go1.x發布後不會修改之前的語言特性. 這裡有一些問題的修複, 還有一些新增加的特性.

整數除以零是編譯錯誤

在Go1中, 整數被一個常量0除會導致一個運行時 panic:

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

在 Go1.1 中, 整數被一個常量0將會被當作一個編譯錯誤處理.

Unicode代理區碼點不能用於面值

字串和 rune 字面值的定義更加嚴格. Unicode代理區碼點不能用於面值. 細節請參考後面的 Unicode 章節.

方法值和方法運算式

Go1.1新實現了方法值(method values), 它是綁定到receiver值的一個閉包. 比如有一個實現了Writerw 值, 那麼 w.Write 將等價於下面的閉包函數:

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

方法值(method values)不同於方法運算式(method expressions), 方法運算式是從一個類型對應的函數. 比如 (*bufio.Writer).Write 和下面的普通函數類型:

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

更新: 現有的代碼不需要更新, 這個是新加的特性.

GoSpec中給出了很多例子:

f := t.Mv; f(7)   // like t.Mv(7)f := pt.Mp; f(7)  // like pt.Mp(7)f := pt.Mv; f(7)  // like (*pt).Mv(7)f := t.Mp; f(7)   // like (&t).Mp(7)f := makeT().Mp   // invalid: result of makeT() is not addressable

有了方法值, Go1.1可以從interface值中取出方法值(Go1.0不支援方法值):

var i interface { M(int) } = myValf := i.M; f(7)  // like i.M(7)

這樣改動的好處是類型的方法和interface方法完全統一了.

Return requirements

在Go1.1之前, 函數如果有傳回值的話, 則最後必須有一個retune或panic語句.

func abs(x int) int {    if x >= 0 {        return x    } else {        return -x    }}

會有以下編譯錯誤:

function ends without a return statement

之前一般可以在末尾加一個panic來迴避這個問題:

func abs(x int) int {    if x >= 0 {        return x    } else {        return -x    }    panic("not reachable")}

在Go1.1規範, 對函數的終結語句做了定義:

  • https://go.googlecode.com/hg/doc/go_spec.html#Terminating_statements

主要有以下幾種類型:

  • return或者goto語句
  • 調用內建的panic函數
  • if語句: 必須帶else, 並且if和else部分都有明確的終結語句
  • for語句: 死迴圈的類型(無允出準則和break語句)
  • switch語句: 沒有break語句, 必須有default分支, 每個分支都有終結語句(或者是fallthrough到下個分支的終結語句)
  • select語句: 無break語句, 必須有default分支, 每個分支都有終結語句
  • 用於goto的Label

已有的代碼可以不用更新, 當然有些代碼可以寫的更簡化.

實現和工具的變化

gccgo的變化

上個月發布的 GCC 4.8.0 還沒有完整的包含 Go1.1. 確實的主要功能是沒有方法值, 標準庫也有一些差異. 可以期望5月份發布GCC4.8.1時, gccgo能夠完整支援Go1.1.

命令列參數解析

在目前的gc工具鏈中, 編譯器和連接器使用的是同樣的命令列參數解析規則, 基於Go語言的flag包實現. 和傳統的UNIX命令列習慣有些不同. 這可能影響直接調用GC工具的指令碼. 例如, 原有的 go tool 6c -Fw -Dfoo 命令, 現在要這樣寫 go tool 6c -F -w -D foo.

64位系統 int 大小為int64

語言規範運行實現自由選擇 intuint 為32位或64位. 在之前的實現中, intuint都是32位. 現在, 在 AMD64/x86-64 平台, GC和gccgo實現的intuint 都是64位的. 一個相關的變化是, 在64位系統切片將可以分配超出int32能表示的20多億個元素.

更新: 大部分代碼不受影響. 如果可能會影響涉及 int 類型轉換有關的代碼:

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

下面是一種可移植的寫法(-1在所有系統是可以確定的):

i := int(int32(x))

64位平台的堆大小

對於64位平台, 堆的最大上限擴大很大, 從幾個GB到幾十個GB(具體細節取決於系統,並且可能會更改).

在32位系統, 堆的大小沒有變化.

更新: 現有代碼沒有影響. 當時新程式可以使用更多的記憶體.

補充: Windows/amd64目前預設為32GB(以後會根據不同版本調整).

Unicode

主要是和UTF16相關的代理區碼點有關:

  • 代理區碼點不能用在字元/字串面值中.
  • 代理區碼點的輸出也有變化

比如:

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

Go 1.0輸出為 “\ud800”, Go 1.1 輸出為 “\ufffd”.

Race detector

go tool內建資料競爭偵查工具. 目前只支援64位系統. 使用時需要指定-race選項.

比如以下的代碼, 在2個不同goroutine中競爭訪問m.

func main() {    c := make(chan bool)    m := make(map[string]string)    go func() {        m["1"] = "a" // First conflicting access.        c <- true    }()    m["2"] = "b" // Second conflicting access.    <-c    for k, v := range m {        fmt.Println(k, v)    }}

可以這樣測試:

$ go run -race mysrc.go  // to run the source file

補充: 偵查工具目前是基於LLVM的ThreadSanitizer race detector實現的.

gc assemblers

主要是為了適應64位系統int的預設大小變化, 和其他一些內部約定的變化.

go 的變化

go get時必須設定GOPATH, 並且GOPATHGOROOT不能相同.

補充: 建議兲朝使用者手工下載, 因為go get預設使用的https協議經常被牆.

go test 的變化

當啟動了剖析選項時, go test預設不在刪除二進位測試程式. 有專門的選項-cpuprofile:

$ go test -cpuprofile cpuprof.out mypackage

還有-blockprofile選項, 可以檢測goroutines被阻塞情況.

更多細節請參考: go help test

go fix 的變化

現在go fix將不再支援Go1之前的代碼到Go1的轉換. 如果需要處理Go1之前的代碼, 需要先使用Go1的工具做預先處理.

新的構建約束

如果只在Go1.1+環境編譯, 可以設定以下構建選項:

// +build go1.1

如果是Go1.0.x的變化條件, 則是:

// +build !go1.1

新支援的平台

Go1.1工具鏈實驗性的增加freebsd/arm, netbsd/386, netbsd/amd64, netbsd/arm, openbsd/386openbsd/amd64平台的支援.

對於 freebsd/armnetbsd/arm 必須是ARMv6或更高的版本.

Go1.1對於linux/arm平台實驗性的提供cgo的支援.

交叉編譯

交叉編譯時間, 預設禁止CGO. 如果需要啟動CGO, 需要手工設定CGO_ENABLED=1.

效能最佳化

主要有以下幾個地方:

  • gc編譯器產生代碼最佳化, 特別是Intel 32-bit下的浮點運算
  • gc編譯器採用更多的內聯最佳化, 比如內建的append函數和interface的轉換等
  • map的一個改進實現, 顯著減少記憶體片段和CPU時間
  • 在多核的CPU上, 可以並行的運行記憶體回收
  • 更精確的記憶體回收, 可以顯著減少堆的大小, 特別是在32位系統
  • 運行時和網路程式庫配合更緊密, 減少環境切換代價
  • 標準庫的最佳化

根據官方的說法, Go1.1效能提升基本有30%-40%, 有時更多(當然也有不明顯的情況).

補充: Windows版本很多最佳化的代碼還沒有合并進來, 特別是運行時/網路部分.

標準庫的變化

  • reflect包功能完善: 實現了select的支援; 類型轉換支援; 變數到閉包的轉換; chan/map/slice的支援等.
  • 新加的包: go/format/net/http/cookiejar/runtime/race
  • 其他很多包的問題修複/功能完善/效能最佳化 等.

這個部分細節太多, 具體查看官方文檔吧.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.