Go 知识点(18)— 条件编译(编译标签、文件后缀)
1. 條件編譯
Go 能根據(jù)所處環(huán)境選擇對(duì)應(yīng)的源碼進(jìn)行編譯。讓編譯器只對(duì)滿足條件的代碼進(jìn)行編譯,將不滿足條件的代碼舍棄,這就叫做條件編譯。
在 Go 中,也稱之為 Build Constraints 編譯約束,添加編譯約束的以下 2 種:
- 編譯標(biāo)簽(
build tag) - 文件后綴
2. 編譯標(biāo)簽
?編譯標(biāo)簽是一種通過(guò)在源碼文件頂部添加注釋,來(lái)決定文件是否參與編譯的約束方式。其格式如下:
// +build <tags>
注意:
// +build的下一行必須是空行,否則會(huì)被解析為包注釋。
// +build linux// main package comment
package main
Go 語(yǔ)言在構(gòu)建一個(gè)包的時(shí)候會(huì)讀取這個(gè)包里的每個(gè)源文件并且分析編譯標(biāo)簽,這些標(biāo)簽決定了這個(gè)源文件是否參與本次編譯。
tags 說(shuō)明:
- 以空格分開表示
OR - 以逗號(hào)分開表示
AND !表示NOT- 一個(gè)文件可以有多個(gè)
+build構(gòu)建標(biāo)記,它們之間的關(guān)系是邏輯與的關(guān)系
標(biāo)簽可以指定為以下內(nèi)容:
- 操作系統(tǒng),環(huán)境變量中
GOOS的值,如:linux、darwin、windows等; - 操作系統(tǒng)的架構(gòu),環(huán)境變量中
GOARCH的值,如:amd64、x86、i386等; - 使用的編譯器,
gc或者gccgo; - 是否開啟
CGO,cgo go版本號(hào):比如Go Version 1.1為go1.1,Go Version 1.12版本為go1.12以此類推。
其它自定義標(biāo)簽,通過(guò) go build -tags 指定的值。
使用示例:
- 編譯條件為
(linux AND 386) OR (darwin AND (NOT cgo))
// +build linux,386 darwin,!cgo
- 多個(gè)編譯約束,比如條件為
(linux OR darwin) AND amd64
// +build linux darwin// +build amd64
- 也可以使用
ignore標(biāo)簽將一個(gè)文件從編譯中排除。
// +build ignore
linux或者windows amd64
// +build linux windows,amd64package main
多個(gè) +build 構(gòu)建標(biāo)記一般分成每行一個(gè) +build 構(gòu)建標(biāo)記。
在 Gin 框架中,也較多地使用了編譯標(biāo)簽,例如 internal/json 目錄,這個(gè)目錄目前只有 json 包。在 json 包中,這個(gè)包的兩個(gè)文件分別都使用了標(biāo)簽 jsoniter。
jsoniter.go 內(nèi)容
// Copyright 2017 Bo-Yi Wu. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.// +build jsoniterpackage jsonimport "github.com/json-iterator/go"var (json = jsoniter.ConfigCompatibleWithStandardLibrary// 通過(guò)函數(shù)值,Marshal 等函數(shù)都由 Gin 下的 json 包導(dǎo)出Marshal = json.MarshalUnmarshal = json.UnmarshalMarshalIndent = json.MarshalIndentNewDecoder = json.NewDecoderNewEncoder = json.NewEncoder
)
json.go 內(nèi)容
// Copyright 2017 Bo-Yi Wu. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.// +build !jsoniterpackage jsonimport "encoding/json"var (// 通過(guò)函數(shù)值,Marshal 等函數(shù)都由 Gin 下的 json 包導(dǎo)出Marshal = json.MarshalUnmarshal = json.UnmarshalMarshalIndent = json.MarshalIndentNewDecoder = json.NewDecoderNewEncoder = json.NewEncoder
)
Gin使用 encoding/json作為默認(rèn)的 json包,但可以通過(guò)從其他標(biāo)簽構(gòu)建來(lái)改變它。
- jsoniter
$ go build -tags=jsoniter .
上述命令表示使用 jsoniter.go 文件來(lái)編譯生成可執(zhí)行文件。
- go_json
$ go build -tags=go_json .
在 Gin 框架編譯時(shí),可以通過(guò)編譯標(biāo)簽自由選擇性編譯。編譯時(shí)如果指定 -tags=jsoniter,則會(huì)選擇 jsoniter.go 進(jìn)行編譯,默認(rèn)情況下一般都沒(méi)有指定這個(gè)標(biāo)簽,所以使用的是標(biāo)準(zhǔn)庫(kù)的 json 包。
?
由于第三方包 jsoniter 性能上要優(yōu)于標(biāo)準(zhǔn)庫(kù)的 json 包,而且這個(gè)包提供 100% 與標(biāo)準(zhǔn)庫(kù) json 包兼容選項(xiàng),加上主要函數(shù)簽名一致,所以 Gin 這里特意封裝了新的 json 包,通過(guò)編譯標(biāo)簽,程序編譯時(shí)很容易根據(jù)實(shí)際標(biāo)簽來(lái)選擇具體實(shí)現(xiàn)的代碼包。
?
3. 文件后綴
除了編譯標(biāo)簽,第二種添加編譯約束的方法是通過(guò)源碼文件的文件名實(shí)現(xiàn)的,這種方案比構(gòu)造標(biāo)簽方案更簡(jiǎn)單。編譯器也會(huì)根據(jù)文件后綴來(lái)自動(dòng)選擇編譯文件:
$filename_$GOOS.go
$filename_$GOARCH.go
$filename_$GOOS_$GOARCH.go
$filename: 源文件名稱;$GOOS: 表示操作系統(tǒng),從環(huán)境變量中獲取;$GOARCH: 表示系統(tǒng)架構(gòu),從環(huán)境變量中獲取;
后綴的順序記住不要顛倒,后綴中同時(shí)出現(xiàn)系統(tǒng)和架構(gòu)名時(shí),需要保持$filename_$GOOS_$GOARCH.go 的順序。
標(biāo)準(zhǔn)庫(kù) os 源代碼的部分截圖:
構(gòu)建標(biāo)簽和文件名后綴在功能上是重疊的,根據(jù)需要選擇合適的就行。
參考:
https://mp.weixin.qq.com/s?__biz=MzAxNzY0NDE3NA==&mid=2247489316&idx=2&sn=5b556235a63781c852e490da67823f7d&chksm=9be338c5ac94b1d376f94b3d8990ec8062cae9745f1d1e0314b116d6003b48e8bbd72701b249&scene=126&&sessionid=1642228531#rd
總結(jié)
以上是生活随笔為你收集整理的Go 知识点(18)— 条件编译(编译标签、文件后缀)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2022-2028年中国内衣行业研究及前
- 下一篇: 2022-2028年中国实心轮胎行业市场