Go 高級構建指南

本文將探索 Golang 高級構建技巧,從而有助於創建更高效的二進制文件。原文: Advanced Go Build Techniques[1]

構建選項

以下是 go build 命令最常用的一些選項:

有關 go build 命令的更多信息,可以運行以下命令:

go help build

包含哪些文件

在 Go 中使用 go build 命令時,會編譯當前目錄及其子目錄中的 Go 源文件,以創建可執行的二進制文件。默認情況下只編譯 .go 文件,而忽略目錄中的其他文件類型。不過,值得注意的是,go build 命令的行爲可能會受到構建標籤和構建約束的影響。

go build 通常會忽略以下類型的文件:

1. 擴展名不是 .go 的文件:

目錄中任何沒有 .go 擴展名的文件都將被忽略,包括文本文件、配置文件、圖片等。

2. 子目錄中的文件:

go build 命令編譯當前目錄及其子目錄中所有 .go 文件,其他文件和目錄通常會被忽略。

3. 以下劃線或點號開頭的文件:

go 工具會忽略以 ._ 開頭的目錄和文件名,以及名爲 testdata 的目錄。

4. 被構建約束排除的文件:

Go 支持構建約束,允許根據目標操作系統或體系架構等條件,構建過程中包含或排除特定文件。例如,在爲非 Windows 平臺構建時,帶有 //go:build windows 等構建約束的文件將被忽略。

5. 通過構建標籤排除的文件:

構建標籤是 Go 源文件中的特殊註釋,可用於根據自定義條件指定哪些文件應包含在編譯中。如果文件的構建標記與構建上下文不匹配,則會被忽略。

6."testdata" 目錄中的文件:

testdata 的目錄中的文件將被忽略。該目錄通常用於包含與測試相關的數據,而這些數據並不需要編譯。

構建標籤

Go 的構建標籤提供了一種強大的機制,可在構建過程中包含或排除特定代碼。通過使用構建標籤,開發人員可以定製自己的應用程序,使其適用於不同的構建配置、環境或特定平臺要求。這一功能在處理交叉編譯或爲特定操作系統創建二進制文件時尤爲重要。

構建標籤是放在 Go 源文件開頭的註釋,指定了一組條件,標識在這些條件下,該文件中的代碼應被包含或排除在聯編過程之外。語法是 //go:build 。例如,考慮這樣一種情況:只有在爲應用程序的某個版本構建時,纔會包含一段特定的代碼:

main.go

package mainimport "fmt"

var version string
func main() {
    fmt.Println(version)
}

pro.go

//go:build pro
package main
func init() {
    version = "pro"
}

free.go

//go:build free
package main
func init() {
    version = "free"
}

當使用 -tags=free 時,輸出將是 free,因爲 free.go 文件已包含在內。而使用 -tags=pro 時,輸出將是 pro

構建標籤語法

可以像使用編程中的其他條件語句一樣組合約束條件,如 AND、OR、NOT。

NOT

//go:build !cgo

只有在未啓用 CGO 的情況下,纔會在構建過程中包含該文件。

AND

//go:build cgo && darwin

只有啓用 CGO 並且 GOOS 設置爲 darwin 的情況下,纔會在構建過程中包含該文件。

OR

//go:build darwin || linux

組合使用

//go:build (linux || 386) && (darwin || !cgo)

注意:1.16 及更早版本的 Go 使用了不同的構建約束語法,前綴爲 // +build。當遇到舊語法時,gofmt 命令將添加等效的 //go:build 約束。

構建約束

除了使用構建參數設置自定義構建標籤,golang 也會根據環境變量和其他因素自動設置一些標籤。以下是可用標記的列表:

  1. GOOS 和 GOARCH 環境變量

可以在源代碼中設置限制條件,只有在使用了特定 GOOS 或 GOARCH 時才能運行文件,例如:

//go:build darwin,amd64
package utils
  1. GO 版本限制

可以根據構建整個模塊時使用的 go 版本來約束是否包含文件。例如,要只在使用 go 版本爲 1.12 及以上時構建文件,可以使用 //go:build go1.18。如果 go 的版本是 1.18 或 1.21(截至本文撰寫時的最新版本),則會包含該文件。


你好,我是俞凡,在 Motorola 做過研發,現在在 Mavenir 做技術工作,對通信、網絡、後端架構、雲原生、DevOps、CICD、區塊鏈、AI 等技術始終保持着濃厚的興趣,平時喜歡閱讀、思考,相信持續學習、終身成長,歡迎一起交流學習。爲了方便大家以後能第一時間看到文章,請朋友們關注公衆號 "DeepNoMind",並設個星標吧,如果能一鍵三連 (轉發、點贊、在看),則能給我帶來更多的支持和動力,激勵我持續寫下去,和大家共同成長進步!

參考資料

[1]

Advanced Go Build Techniques: https://blog.stackademic.com/advanced-go-build-techniques-d44cbc0cbeda

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/NYyBVdR5CuIAje51xDVJ8Q