<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go1.17 新特性:新版構(gòu)建約束

          共 3335字,需瀏覽 7分鐘

           ·

          2021-07-17 02:26

          閱讀本文大概需要 6 分鐘。

          大家好,我是 polarisxu。

          Go 1.17 下個(gè)月就要正式發(fā)布了。很多人要問泛型了吧,泛型已經(jīng)很明確了,Go1.18 會(huì)有。今天給大家介紹 Go1.17 的一個(gè)新特性:構(gòu)建約束 — Build Constraints。

          確切來說,這個(gè)特性相關(guān)的工作在 1.16 時(shí)就加入,但處于過度階段,1.17 在各方面都更完善,更完整的支持,是時(shí)候了解它了。

          01 什么是構(gòu)建約束

          構(gòu)建約束(build constraint),也叫做構(gòu)建標(biāo)記(build tag),是在 Go 源文件最開始的注釋行,比如:

          // +build linux

          看到這個(gè),相信很多人都不陌生,因?yàn)檫@是 Go 一開始就有的特性,在 Go 源碼中有很多這樣的注釋行。上面注釋行的意思,這個(gè)文件只在 Linux 系統(tǒng)會(huì)包含在包中,其他系統(tǒng)會(huì)忽略這個(gè)文件。

          幾個(gè)注意點(diǎn):

          • 約束可以出現(xiàn)在任何源文件中,比如 .go.s 等;
          • 必須在文件頂部附近,它的前面只能有空行或其他注釋行;可見包子句也在約束之后;
          • 約束可以有多行;
          • 為了區(qū)別約束和包文檔,在約束之后必須有空行;

          針對(duì)某個(gè)構(gòu)建約束,可使用的詞如下:

          • 特定操作系統(tǒng),對(duì)應(yīng) runtime.GOOS 的可用值,比如 linux、windows 等;
          • 特定的架構(gòu),對(duì)應(yīng) runtime.GOARCH 的可用值,比如 386、amd64 等;
          • 使用的編譯器,比如 gc、gccgo;
          • 支持 cgo 命令時(shí),可以使用 cgo;
          • Go 的主要發(fā)布版本,比如 go1.17、go1.16 等;(測試版本和 fixbug 版本不支持)
          • 自定義的 tag,編譯時(shí)通過 -tags 傳遞的值;
          • 可以加入任意值,一般用 ignore 來忽略構(gòu)建;

          此外,文件名可以通過 GOOS 和 GOARCH 來做構(gòu)建約束。

          02 舊版構(gòu)建約束

          從上面看到,構(gòu)建約束的語法是 // +build 這種形式,如果多個(gè)條件組合,通過空格、逗號(hào)或多行構(gòu)建約束表示。比如:

          // +build linux,386

          你知道什么意思嗎?表示在 linux AND 386。逗號(hào)表示 AND,空格表示 OR。那看一個(gè)復(fù)雜的:

          // +build linux,386 darwin,!cgo

          是不是有點(diǎn)懵?我也有點(diǎn)懵!它表示的意思是:(linux AND 386) OR (darwin AND (NOT cgo)) 。

          有些時(shí)候,多個(gè)約束分成多行書寫,會(huì)更易讀些:

          // +build linux darwin
          // +build amd64

          這相當(dāng)于:(linux OR darwin) AND amd64 。

          是不是很復(fù)雜,很難記憶?

          正因?yàn)樘珡?fù)雜,很容易出錯(cuò)。而且,Go 中有不少注釋是有特殊意義的,也為了一致性考慮,因此有了新版的構(gòu)建約束。

          03 新版構(gòu)建約束

          在 Go 源碼中,經(jīng)常會(huì)見到類似下面開頭的注釋:

          //go:link

          新版的構(gòu)建約束,也使用了 //go: 開頭:

          //go:build

          注意 // 和 go 之間不能有空格。

          同時(shí)新版語法使用布爾表達(dá)式,而不是逗號(hào)、空格等。布爾表達(dá)式,會(huì)更清晰易懂,出錯(cuò)可能性大大降低。

          比如舊語法:

          // +build linux,386

          對(duì)應(yīng)的新語法:

          //go:build linux && 386

          構(gòu)建標(biāo)記的基礎(chǔ)語法與其當(dāng)前形式?jīng)]有變化,但是構(gòu)建標(biāo)記的組合現(xiàn)在是用 Go 的 || 、 && 和 ! 運(yùn)算符和括號(hào)。(請(qǐng)注意,構(gòu)建標(biāo)記并不總是有效的 Go 表達(dá)式,即使它們共享操作符,因?yàn)闃?biāo)記并不總是有效的標(biāo)識(shí)符。例如:”go1.1"。)

          新語法可以使用 Go spec 的 EBNF 標(biāo)記來表示:

          BuildLine      = "http://go:build" Expr
          Expr           = OrExpr
          OrExpr         = AndExpr   { "||" AndExpr }
          AndExpr        = UnaryExpr { "&&" UnaryExpr }
          UnaryExpr      = "!" UnaryExpr | "(" Expr ")" | tag
          tag            = tag_letter { tag_letter }
          tag_letter     = unicode_letter | unicode_digit | "_" | "."

          采用新語法后,一個(gè)文件只能有一行構(gòu)建語句,而不是像舊版那樣有多行。這樣可以避免多行的關(guān)系到底是什么的問題。

          Go1.17 中,gofmt 工具會(huì)自動(dòng)根據(jù)舊版語法生成對(duì)應(yīng)的新版語法,為了兼容性,兩者都會(huì)保留。比如原來是這樣的:

          // +build !windows,!plan9

          執(zhí)行 Go1.17 的 gofmt 后,變成了這樣:

          //go:build !windows && !plan9
          // +build !windows,!plan9

          如果文件中已經(jīng)有了這兩種約束形式,gofmt 會(huì)根據(jù) //go:buid 自動(dòng)覆蓋 // +build 的形式,確保兩者表示的意思一致。如果只有新版語法,不會(huì)自動(dòng)生成舊版的,這時(shí),你需要注意,它不兼容舊版本了。

          另外,Vet 工具現(xiàn)在能夠檢測出兩種語法的不一致。所以,建議大家在編輯器中保存文件時(shí)自動(dòng)執(zhí)行 gofmt。

          早在 Go1.16 時(shí)就新增了一個(gè)包:go/build/constraint,專門處理新版構(gòu)建約束。

          關(guān)于新版約束的設(shè)計(jì)文檔請(qǐng)移步:https://go.googlesource.com/proposal/+/master/design/draft-gobuild.md。

          04 總結(jié)

          新版本的構(gòu)建約束可讀性更強(qiáng),更容易書寫,不容易出錯(cuò)。有興趣的可以自己針對(duì)構(gòu)建約束,同時(shí)書寫兩種形式,體會(huì)下新版的好處。

          最后提醒一點(diǎn),新版約束中,一定要注意 // 和 go 之間不能有空格!




          往期推薦


          我是 polarisxu,北大碩士畢業(yè),曾在 360 等知名互聯(lián)網(wǎng)公司工作,10多年技術(shù)研發(fā)與架構(gòu)經(jīng)驗(yàn)!2012 年接觸 Go 語言并創(chuàng)建了 Go 語言中文網(wǎng)!著有《Go語言編程之旅》、開源圖書《Go語言標(biāo)準(zhǔn)庫》等。


          堅(jiān)持輸出技術(shù)(包括 Go、Rust 等技術(shù))、職場心得和創(chuàng)業(yè)感悟!歡迎關(guān)注「polarisxu」一起成長!也歡迎加我微信好友交流:gopherstudio


          瀏覽 76
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一区二区操穴TⅤ | 屄网| 日韩无码高清免费 | 日日夜夜精品视频 | 欧美15p色图 |