golang1.16新特性速覽

今天是假期最後一天,明天起你們也要陸續復工了。golang1.16也在今天正式發佈了。html

原定計劃是2月1號年前發佈的,不過遲到也是golang的老傳統了,正好也趁着最後的假期快速預覽一下golang1.16的新特性吧。linux

本文索引

語言內建的資源嵌入支持

以前市面上已經有不少把今天文件嵌入golang二進制程序的工具了,此次golang官方將這一功能加入了embed標準庫,從語言層面上提供了支持。git

我以前以及寫了embed的使用教程,能夠看這裏github

這兒還有一篇官方推薦的教程golang

支持arm64

m1芯片可謂是最近的焦點,golang天然也不會落下。bash

在golang1.16中官方已經支持darwin/arm64平臺,cgo和編譯成c語言可調用的動態/靜態連接庫的功能也已支持。一樣受益的還有bsd家族的arm64版本。數據結構

如今能夠在新版mac上嘗試golang了。tcp

不過plugin模式的支持仍在進行中,想要完整支持arm64還須要一段時間。svn

go modules的新特性

本次更新依舊帶來了許多modules的新特性。函數

GO111MODULE如今默認爲on

1.16開始默認啓用modules,這在1.15的時候已經預告過了。如今GO111MODULE的默認值爲on。

不過golang仍是提供了一個版本的適應期,若是你還不習慣modules,能夠把GO111MODULE設置回auto。在1.17中這個環境變量將會被刪除。

都1202年了,也該學學go modules怎麼用了。

go build再也不更改mod相關文件

之前的教程裏我提到過go build會自動下載依賴,這會更新mod文件。

如今這一行爲被禁止了。想要安裝、更新依賴只能使用go get命令,go build和go test將不會再作這類工做。

go install的變化

go install在1.16中也有了不小的變化。

首先是經過go install my.module/tool@1.0.0 這樣在module末尾加上版本號,能夠在不影響當前mod的依賴的狀況下安裝golang程序。

go install是將來惟一能夠安裝golang程序的命令,go get的編譯安裝功能如今能夠靠-d選項關閉,而將來編譯安裝功能會從go get移除。

也就是說go的命令各司其職,再也不長臂管轄了。

新的GOVCS環境變量

新的GOVCS環境變量指定了golang用什麼版本控制工具下載源代碼。

其格式爲:GOVCS=<module prefix>:<tool name>,[<module prefix>:<tool name>, ...]

其中module prefix爲github.com等,而tool name就是版本控制工具的名字,好比git,svn。

一個更具體的例子是:GOVCS=github.com:git,evil.com:off,*:git|hg

module prefix也能夠用*通配任何模塊的前綴。

tool name還能夠設置爲all和off,all表明容許使用任何可用的工具,而off則表示不容許使用任何版本控制工具。

不過如今設置爲off的模塊的代碼仍然可能會被下載。

更多的細節能夠參考go help vcs

相對路徑導入不在被容許

golang1.16開始禁止import導入的模塊以.開頭,模塊路徑中也不容許出現任何非ASCII字符,因此下面的代碼再也不合法:

import (
    "./tools/factory"
    "../models/user"
    "some.pkg.com/殺馬特/音樂工廠"
)

對非ASCII字符一如既往的不友好,不過也只能按規矩辦事了。

標準庫的變化

golang1.16除了對標準庫進行一般的功能更新和修復,還引入了一些重大變化。

testing

testing包主要的變化是在測試用例裏調用os.Exit(0)會從程序終止變成測試失敗。

好比這個:

package main

import (
    "os"
    "testing"
)

func TestXXX(t *testing.T) {
    t.Log("exit")
    os.Exit(0)
}

如今會是這樣的輸出:

$ go test -v a_test.go

=== RUN   TestXXX
    a_test.go:9: exit
--- FAIL: TestXXX (0.00s)
panic: unexpected call to os.Exit(0) during test [recovered]
        panic: unexpected call to os.Exit(0) during test

goroutine 18 [running]:
testing.tRunner.func1.2(0x51b920, 0x56cc28)
        /usr/local/go/src/testing/testing.go:1144 +0x332
testing.tRunner.func1(0xc000082600)
        /usr/local/go/src/testing/testing.go:1147 +0x4b6
panic(0x51b920, 0x56cc28)
        /usr/local/go/src/runtime/panic.go:965 +0x1b9
os.Exit(0x0)
        /usr/local/go/src/os/proc.go:68 +0x6d
command-line-arguments.TestXXX(0xc000082600)
        /tmp/a_test.go:10 +0x76
testing.tRunner(0xc000082600, 0x54df18)
        /usr/local/go/src/testing/testing.go:1194 +0xef
created by testing.(*T).Run
        /usr/local/go/src/testing/testing.go:1239 +0x2b3
FAIL    command-line-arguments  0.004s
FAIL

ioutils包已經廢棄

1.16已經標記io/ioutil爲廢棄,函數被轉移到了os和io這兩個包裏,具體見下表:

ioutil舊函數 新函數
Discard io.Discard
NopCloser io.NopCloser
ReadAll io.ReadAll
ReadDir os.ReadDir
ReadFile os.ReadFile
WriteFile os.WriteFile
TempDir os.MkdirTemp
TempFile os.CreateTemp

如今開始能夠作移植了。

tcp半鏈接隊列擴容

在Linux kernel 4.1之前,golang設置tcp的listen隊列的長度是從/proc/sys/net/core/somaxconn獲取的,一般爲4096。

而在4.1之後golang會直接設置半鏈接隊列的長度爲2^32 - 1也就是4294967295。

更大的半鏈接隊列意味着能夠同時處理更多的新加入請求,並且不用再讀取配置文件性能也會略微提高。

重大更新io/fs

1.16除了支持嵌入靜態資源外,最大的變化就是引入了io/fs包。

golang認爲文件的io操做是依賴於文件系統(filesystem,fs)的,因此決定模仿Linux的vfs作一套基於fs的io接口。

這樣作的目的有三個:

  1. os包應該專一於和系統交互而不是包含一部分io接口
  2. io包和os包分別包含了io接口的一部分,致使互相依賴職責不清晰
  3. 能夠把有關聯的一部分文件或者數據組成虛擬文件系統,供通用接口處理提高程序的可擴展性,好比zip打包的文件

因此io/fs誕生了。

fs包中主要包含了下面幾種數據類型(都是接口類型):

名稱 做用
FS 文件系統的抽象,有一個Open方法用來從FS打開獲取文件數據
DirEntry 描述目錄項目(包含目錄自身)的數據結構
File 描述文件數據的結構,包含Stat,Read,Close方法
ReadDirFile 在File的基礎上支持ReadDir,能夠表明目錄自身
FileMode 描述文件類型,好比是一般文件仍是套接字或者是管道
FileInfo 文件的元數據,例如建立時間等

其中有一些接口和os包中的同名,其實是os包引入fs包後起的別名。

對於FS,還有如下的擴展,以便增量描述文件系統容許的操做:

名稱 做用
GlobFS 增長Glob方法,能夠用通配符查找文件
ReadDirFS 增長ReadDir方法,能夠遍歷目錄
ReadFileFS 增長ReadFile方法,能夠用文件名讀取文件全部內容
StatFS 增長Stat方法,能夠得到文件/目錄的元信息
SubFS 增長Sub方法,Sub方法接受一個文件/目錄的名字,從這個名字做爲根目錄返回一個新的文件系統對象

fs包還提供了諸如Glob,WalkDir等傳統的文件操做接口。

fs的主要威力在於處理zip、tar文件,以及http的文件接口時能夠大幅簡化代碼。並且新的embed靜態資源嵌入也是依賴fs實現的。

由於只是速覽的緣故,沒法詳盡介紹io/fs包,你能夠參考golang的文檔或這篇文章作進一步瞭解。

其餘改進

其餘的改進包括Unicode更新到了13.0、新增長了runtime/metrics包已提供更好更規範的運行時信息等。

同時1.16優化了連接器,如今它在linux/amd64上比1.15快了20-25%,內存佔用減小了5-15%。

在Windows上已經全面支持了地址空間佈局隨機化(ASLR),此前不支持將golang編譯爲dll時啓用ASLR。

本次更新中語言自己沒有什麼變化。

更多信息能夠查看golang1.16 release notes

相關文章
相關標籤/搜索