<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>

          使用 go run 來管理工具依賴

          共 4471字,需瀏覽 9分鐘

           ·

          2022-05-18 14:20

          當(dāng)你在開發(fā)一個(gè)項(xiàng)目時(shí),通常都會(huì)有一些咱們開發(fā)人員依賴的工具。開發(fā)、測試、構(gòu)建或部署過程中運(yùn)行的工具。

          例如,你可以將golang.org/x/text/cmd/gotext結(jié)合使用go:generate來生成需要翻譯的消息目錄,或者`honnef.co/go/tools/cmd/staticcheck`[1]在提交更改之前對(duì)你的代碼執(zhí)行靜態(tài)分析。

          這其中就有幾個(gè)有趣的問題——尤其是在開發(fā)團(tuán)隊(duì)環(huán)境中。你如何保證每個(gè)人的機(jī)器上都安裝了必要的工具?而且他們使用的工具都是同一個(gè)版本呢?

          在 Go 1.17 之前,管理它的慣例是tools.go在項(xiàng)目中創(chuàng)建一個(gè)文件,其中包含import不同工具和//go:build tools構(gòu)建約束的語句。如果您還不太熟悉這種用法,請(qǐng)參閱官方Go Wiki[2]中的描述。

          但是從 Go 1.17 開始,你就可以采用另一種方法。 與該方法相比,它有利有弊tools.go,但很值得了解,并且可能非常適合某些項(xiàng)目。

          現(xiàn)在允許你可以直接go run執(zhí)行特定版本的遠(yuǎn)程包。從1.17 發(fā)布說明[3]可以看出:

          go run 現(xiàn)在接受帶有版本后綴的參數(shù)(例如,go run example.com/[email protected] )。這會(huì)導(dǎo)致 go run 以模塊感知模式構(gòu)建和運(yùn)行包,忽略當(dāng)前目錄或任何父目錄中的 go.mod 文件(如果有的話)。

          換句話說,當(dāng)你在模塊之外或在模塊內(nèi)部時(shí),您可以使用它go run package@version來執(zhí)行遠(yuǎn)程包,即使該包不在go.mod文件中。

          作為無需安裝即可運(yùn)行可執(zhí)行包的快速方法,它也很有用。而不是這樣:

          $?go?install?honnef.co/go/tools/cmd/[email protected]?$?staticcheck?./...?

          你現(xiàn)在可以這樣做(記得只有在1.17之后才可使用):

          $?go?run?honnef.co/go/tools/cmd/[email protected]?./...?

          重要提示:當(dāng)在執(zhí)行go run package@version必要的模塊時(shí),會(huì)將下載并緩存在您機(jī)器上的模塊緩存中。因此,當(dāng)在稍后執(zhí)行相同的go run命令時(shí),將會(huì)使用緩存(而不是再次下載所有內(nèi)容)并且它會(huì)更快地編譯執(zhí)行完成。

          使用 go:generate

          讓我們看一個(gè)例子,我們將`golang.org/x/tools/cmd/stringer`[4]工具與某些iota常量結(jié)合使用go:generate生成String()方法。

          運(yùn)行以下命令:

          $?mkdir?tools?
          $?go?mod?init?example.com/tools?
          $?touch?main.go?

          然后將以下代碼添加到main.go

          文件:main.go

          File:?main.go
          package?main

          import?"fmt"

          //go:generate?go?run?golang.org/x/tools/cmd/[email protected]?-type=Level

          type?Level?int

          const?(
          ????Info?Level?=?iota
          ????Error
          ????Fatal
          )

          func?main()?{
          ????fmt.Printf("%s:?Hello?world!\n",?Info)
          }

          這里重要的是//go:generate這一行。當(dāng)你執(zhí)行go generate在此文件上時(shí),它將會(huì)依次使用go run來執(zhí)行v0.1.10版本的golang.org/x/tools/cmd/stringer

          讓我們?cè)囈辉嚕?/p>

          $?go?generate?.?
          go:?downloading?golang.org/x/tools?v0.1.10?
          go:?downloading?golang.org/x/sys?v0.0.0-20211019181941-9d821ace8654?
          go:?downloading?golang.org/x/xerrors?v0.0.0-20200804184101-5ec99f83aff1?
          go:?downloading?golang.org/x/mod?v0.6.0-dev.0.20220106191415-9b9b3d81d5e3?

          這里看到下載了必要的模塊,然后go:generate命令成功完成執(zhí)行——生成一個(gè)新level_string.go文件和一個(gè)應(yīng)用程序。像這樣:

          $?ls??
          go.mod??level_string.go??main.go?
          $?go?run?.?
          Info:?Hello?world!?

          在 Makefile 中使用

          還可以使用該go run package@version模式在您的腳本或 Makefile 中執(zhí)行。來讓我們創(chuàng)建一個(gè) Makefile,其中包含執(zhí)行特定版本staticcheck工具的任務(wù)。

          $?touch?Makefile?
          .PHONY:?audit
          audit:
          ????go?vet?./...
          ????go?run?honnef.co/go/tools/cmd/[email protected]?./...

          如果運(yùn)行make audit,將會(huì)下載必要的模塊,并且該staticcheck工具會(huì)成功地完成其檢查。

          $?make?audit
          go?vet?./...
          go?run?honnef.co/go/tools/cmd/[email protected]?./...
          go:?downloading?honnef.co/go/tools?v0.3.1
          go:?downloading?golang.org/x/tools?v0.1.11-0.20220316014157-77aa08bb151a
          go:?downloading?golang.org/x/exp/typeparams?v0.0.0-20220218215828-6cf2b201936e
          go:?downloading?github.com/BurntSushi/toml?v0.4.1

          如果你第二次運(yùn)行它,你會(huì)看到模塊緩存被使用了,所以會(huì)更快地運(yùn)行完成。

          $?make?audit
          go?vet?./...
          go?run?honnef.co/go/tools/cmd/[email protected]?./...

          優(yōu)點(diǎn)和缺點(diǎn)

          優(yōu)點(diǎn)

          就積極方面而言,go run package@versiontools.go該方法相比有幾個(gè)很好的優(yōu)勢

          • 它的設(shè)置更簡單,需要的代碼更少——不需要tools.go文件,沒有構(gòu)建約束,也沒有別名導(dǎo)入。
          • 它避免了用二進(jìn)制文件實(shí)際上不依賴的東西污染你的依賴關(guān)系圖。

          缺點(diǎn)

          • 如果go run package@version在整個(gè)代碼庫中的多個(gè)位置都有相同的命令并且想要升級(jí)到較新的版本,那么您需要手動(dòng)更新所有命令(或使用sed或查找并替換)。使用這種tools.go方法,只需要go.mod通過運(yùn)行go get package@newversion來更新文件。

          • 使用這種tools.go方法,可以通過運(yùn)行go mod verify驗(yàn)證模塊緩存中的緩存代碼是否有更改。我不太清楚對(duì)于 go run package@version 是否有類似的檢查(如果你知道這樣做的方法,可以告知我一下)。從我有限的測試來看,似乎可以編輯機(jī)器上模塊緩存中的緩存代碼,并且運(yùn)行go run package@version也會(huì)地使用這個(gè)編輯過的代碼。

          • 如果在脫機(jī)狀態(tài)下工作,運(yùn)行go run package@version可能會(huì)失敗并出現(xiàn)dial tcp: lookup proxy.golang.org: Temporary failure in name resolution錯(cuò)誤,因?yàn)樗鼰o法訪問 Go 模塊鏡像——即使您的本地模塊緩存中已經(jīng)有一個(gè)副本了。

            $?make?audit
            go?vet?./...
            go?run?honnef.co/go/tools/cmd/[email protected]?./...
            go:?honnef.co/go/tools/cmd/[email protected]:?honnef.co/go/tools/cmd/[email protected]:?Get?"https://proxy.golang.org/honnef.co/go/tools/cmd/staticcheck/@v/v0.3.1.info":?dial?tcp:?lookup?proxy.golang.org:?Temporary?failure?in?name?resolution
            make:?***?[Makefile:4:?audit]?Error?1

            其實(shí)當(dāng)使用這些工具時(shí),這并不是一個(gè)問題。你可以通過將GOPROXY環(huán)境變量設(shè)置為direct在脫機(jī)狀態(tài)下來輕松地繞過它。這樣做就可以使go run繞過go模塊鏡像,并直接在你的機(jī)器上使用緩存的模塊。

            $?export?GOPROXY=direct
            $?make?audit
            go?vet?./...
            go?run?honnef.co/go/tools/cmd/[email protected]?./...

          本文由小土翻譯自 Using go run to manage tool dependencies[5],翻譯不當(dāng)之處,煩請(qǐng)指出。

          參考資料

          [1]

          honnef.co/go/tools/cmd/staticcheck: https://staticcheck.io/

          [2]

          Go Wiki: https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module

          [3]

          1.17 發(fā)布說明: https://go.dev/doc/go1.17

          [4]

          golang.org/x/tools/cmd/stringer: https://pkg.go.dev/golang.org/x/tools/cmd/stringer

          [5]

          Using go run to manage tool dependencies: https://www.alexedwards.net/blog/using-go-run-to-manage-tool-dependencies




          往期推薦


          我是 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

          瀏覽 32
          點(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>
                  性欧美性爱豆花视频 | 亲子伦视频一区二区 | 91精品国产综合久久久不卡电影 | 人人尻人人摸 | 一道本无码专区 |