[譯]Go 1.8 新特性

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

譯自 tylerchr 的 What's Coming in Go 1.8。

隨著Go 1.8 新特性的開發工作已經凍結,Go 1.8 將在2017年2月左右發布,現在讓我們看一些在Go 1.8更有趣的API的改變。

HTTP server connection draining

Brad Fitzpatrick最近關閉了一個將近四年的issue,這個issue請求實現http.Server的串連耗盡(draining)的功能。現在可以調用srv.Close可以立即停止http.Server,也可以調用srv.Shutdown(ctx)等待已有的串連處理完畢(耗盡,draining, github.com/tylerb/graceful 的使用者應該熟悉這個特性)。

下面這個例子中,伺服器當收到SIGINT訊號後(^C)會優雅地關閉。

1234567891011121314151617181920212223242526272829303132333435363738394041424344
package mainimport ("context""io""log""net/http""os""os/signal""time")func main() {// subscribe to SIGINT signalsstopChan := make(chan os.Signal)signal.Notify(stopChan, os.Interrupt)mux := http.NewServeMux()mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {time.Sleep(5 * time.Second)io.WriteString(w, "Finished!")}))srv := &http.Server{Addr: ":8081", Handler: mux}go func() {// service connectionsif err := srv.ListenAndServe(); err != nil {log.Printf("listen: %s\n", err)}}()<-stopChan // wait for SIGINTlog.Println("Shutting down server...")// shut down gracefully, but wait no longer than 5 seconds before haltingctx, _ := context.WithTimeout(context.Background(), 5*time.Second)srv.Shutdown(ctx)log.Println("Server gracefully stopped")}

一旦收到SIGINT訊號,伺服器會立即停止接受新的串連,srv.ListenAndServe()會返回http.ErrServerClosedsrv.Shutdown會一直阻塞,直到所有未完成的request都被處理完以及它們底層的串連被關閉。

更複雜的處理可以通過context實現,例如使用context.Timeout實現最大的關閉等待時間。你可以嘗試複製 https://github.com/tylerchr/examples/tree/master/draining 中的例子並實現它。

通過 http.Pusher 實現 HTTP/2.0 server push

HTTP/2.0 包含 Server Push 特性, 允許 HTTP/2 伺服器主動地發送額外的 HTTP response 給用戶端,即使用戶端沒有發送請求。目標是在用戶端無需請求的情況下,伺服器可以及時地將用戶端所需的資源推送給用戶端。可以查看wiki HTTP/2 Server Push看具體的例子。

如果一個伺服器支援 HTTP/2, 提供給 handler 的 http.ResponseWriter 會實現 http.Pusher 介面。Handler 可以使用這個功能區觸發Server Push, 虛擬請求(synthetic request)可以被註冊的 http.Server Handler所處理。

下面的程式處理/index.html, 可以push一個/static/gopher.png:

123456789101112131415161718192021222324
package mainimport "net/http"func main() {http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))http.Handle("/index.html", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {// server push is available if w implements http.Pusherif p, ok := w.(http.Pusher); ok {p.Push("/static/gopher.png", nil}}// load the main pagew.Header().Set("Content-Type", "text/html")w.Write([]byte(`<img src="/static/gopher.png" />`))}))http.ListenAndServeTLS(":4430", "cert.pem", "key.pem", nil)}

你可以從 https://github.com/tylerchr/examples/serverpush 複製這個例子,下面是在 Chrome 54 訪問的結果:

明顯地可以在 Initiator 那一列中看到 gopher.pngPush,你也可以看到標藍色的gopher.png先於/index.html被接收過來,這表明這個資源先於請求之前被推送到用戶端。HTML下載完後<img>可以顯示。

有人可能會問如何寫一個測試用來校正實現 Server Push的 Handler。因為http.NewTLSServer沒有啟動 HTTP/2 伺服器,httptest.ResponseRecorder也沒有實現http.Pusher。我的解決方案是封裝httptest.ResponseRecorder實現Pusher介面,這裡有個例子。

database/sql

database/sql包有幾個主要的改變,可以讓使用者更好的控制資料庫查詢,允許使用者更好的利用資料庫的特性。

  • 查詢可以使用context.Context取消查詢
  • 純資料庫列類型可以通過sql.ColumnType得到
  • 如果底層資料庫支援,查詢可以使用具名引數

更多的細節可以閱讀Daniel Theophanes的文章 What is new in database/sql?,他實現了大部分的改變。

plugin包實現動態外掛程式

新增加的標準庫plugin提供了初步的外掛程式支援,它允許程式可以在啟動並執行時候動態載入外掛程式。

但是這個庫看起來還是bug多多,我甚至不能寫一個正常的程式來測試它,但是假定它的使用應該如下面的樣子:

1234567891011
// hexify.gopackage mainimport "encoding/hex"func Hexify(in string) string {return hex.EncodeToString([]byte(in))}$ go build -buildmode=shared hexify.go// produces hexify.so
1234567891011
// main.gopackage mainimport "plugin"func main() {p, _ = plugin.Open("hexify.so")f := p.Lookup("Hexify")fmt.Println(f.(func(string) string)("gopher"))// 676f70686572}

在這個例子中,hexify.go實現了Hexify函數,它被編譯成一個共用庫,第二個程式動態載入它。這允許Go程式可以不在編譯的時候也能調用其它的庫。

別名

別名(aliasing)曾被增加到 Go 1.8 的語言規範中,但是現在又被移除了,看這個說明: this post from Russ Cox,有可能會出現在 Go 1.9中。
這個特性也引起了很多的爭議,

指示符別名(Identifier aliasing)用來定義多個類型為同一個類型的文法。一個用處用來重構複雜的代碼的時候,允許重新劃分包而不必帶來類型的不一致。 Ian Lance Taylor舉了一個[例子](https://groups.google.com/d/msg/golang-dev/OmjsXkyOQpQ/OrcHWiGUBAAJ):

舉個具體的例子,將擴充包golang.org/x/net/context移動到標準庫context的過程。因為context已經被廣泛地使用,將所有的使用者的代碼統一轉換很困難,因此允許這兩個包通用很有必要。

別名的定義如下:

1
type Foo => pkg.Bar

這個文法定義 Foopkg.Bar別名。Foo可以用在任何pkg.Bar出現的地方。以上個例子為例,任何需要類型golang.org/x/net/context的地方都可以用標準庫context代替,它們是等價的。

別名也可以用在常量、變數、函數等類型上。

這是一個很有爭議的特性,可以參考issue 16339和golang-dev post 看大家的討論。因為它從Go 1.8中移除了,大家可以暫時不用關注這個特性了。

新的slice排序API

統一的slice排序由新的 sort.Slice 函數實現。它允許任意的slice都可以被排序,只需提供一個回調比較函數即可,而不是像以前要提供一個特定的sort.Interface的實現。這個函數沒有傳回值。想其它的排序函數一樣,它提供了原地的排序。

下面的例子根據海拔高度排序知名山峰的slice。

12345678910111213141516171819202122
type Peak struct {Name      stringElevation int // in feet}peaks := []Peak{{"Aconcagua", 22838},{"Denali", 20322},{"Kilimanjaro", 19341},{"Mount Elbrus", 18510},{"Mount Everest", 29029},{"Mount Kosciuszko", 7310},{"Mount Vinson", 16050},{"Puncak Jaya", 16024},}// does an in-place sort on the peaks slice, with tallest peak firstsort.Slice(peaks, func(i, j int) bool {return peaks[i].Elevation >= peaks[j].Elevation})// peaks is now sorted

通過sort.Interface類型的Len()Swap(i, j int)提供了抽象的排序類型,這是以前的排序方法,而Less(i, j int)作為一個比較回呼函數,可以簡單地傳遞給sort.Slice進行排序。

其它

  • 87b1aaa encoding/base64 encoder現在有了strict 模式.
  • 6ba5b32 expvar暴露出來,可以用在其它的mux中.
  • 003a598 偽隨機碼可以通過rand.Uint64()產生 (先前僅支援uint32).
  • 67ea710 增加了一個新的time.Until函數,和time.Since對應.

net/http故意只實現了使用TLS的HTTP/2,你可以查看[issue 14141]https://github.com/golang/go/issues/14141()瞭解細節。
sort.SliceStable提供了穩定的slice排序,就像以前的sort.Stable一樣。

譯者增加的內容

Go 1.8 一個很大的特性就是效能的提升,包括二進位檔案的大小、編譯速度和運行速度。
並且非常大的提升就是提供小於100us GC暫停。

net/http提供了更多的逾時設定,比如ReadHeaderTimeoutIdleTimeout

一個完整的改動列表:Go 1.8

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.