官方資料
官方解釋: https://pkg.go.dev/cmd/go#hdr-Build_constraints ,go help buildconstraint 也能看到描述
根據官方描述,go1.16開始建議使用go:build方式,與+build相比更容易被人閱讀,
有關go:build注釋的決議: src/go/build/build.go#shouldBuild
有關tag匹配規則: src/go/build/build.go#matchTag
下面是代碼片段
func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool {
if allTags != nil {
allTags[name] = true
}
// special tags
if ctxt.CgoEnabled && name == "cgo" {
return true
}
if name == ctxt.GOOS || name == ctxt.GOARCH || name == ctxt.Compiler {
return true
}
if ctxt.GOOS == "android" && name == "linux" {
return true
}
if ctxt.GOOS == "illumos" && name == "solaris" {
return true
}
if ctxt.GOOS == "ios" && name == "darwin" {
return true
}
if name == "unix" && unixOS[ctxt.GOOS] {
return true
}
if name == "boringcrypto" {
name = "goexperiment.boringcrypto" // boringcrypto is an old name for goexperiment.boringcrypto
}
// other tags
for _, tag := range ctxt.BuildTags {
if tag == name {
return true
}
}
for _, tag := range ctxt.ToolTags {
if tag == name {
return true
}
}
for _, tag := range ctxt.ReleaseTags {
if tag == name {
return true
}
}
return false
}
在源檔案go/build/syslist.go中可以找到knownOS表示tag中可以填寫的OS,以及填寫unix標簽時匹配的OSunixOS,還有可填寫的架構knownArch
BuildTags
BuildTags是編譯命令時-tags的引數串列,根據go help build描述-tags為逗號分隔字串,兼容舊版空格分隔字串,具體代碼: src/cmd/go/internal/work/build.go#tagsFlag
因此go build -tags "a,b,c"這種是新版推薦寫法,go build -tags "a b c"這種是舊版兼容寫法
ToolTags
ToolTags是初始化時的工具標簽,原始碼位置 src/cmd/go/internal/work/init.go#ToolTags
在原始碼中我看到ToolTags可以是race,msan,asan,分別對應go build -race,go build -msan``go build -asan,這三種編譯引數,最常見的就是race用來檢查程式是否存在競態,
ReleaseTags
ReleaseTags是go發布版本標簽,原始碼: src/go/build/build.go#ReleaseTags
根據相關注釋發現ReleaseTags最后一個值被認為是當前在用版本,根據這個標簽的原始碼我們發現當使用//go:build go1.18的xxx.go檔案時,使用大于等于go1.18版本的go取編譯都會匹配成功,也就是說使用go1.19去編譯//go:build go1.18的檔案也是會成功的,
編譯優化
- 很多人都知道
C語言可以在代碼里面加上條件編譯,認為Go只能基于檔案進行條件編譯,畢竟一個//go:build xxx將影響一個檔案是否能被編譯,以及檔案命名格式也是影響整個檔案是否被編譯, - 如何做到在某個代碼塊里面嵌入條件編譯呢?實際上
Go原始碼已經有相關方案,可以參考 src/internal/race
race.go內容如下
//go:build race
// +build race
package race
const Enabled = true
norace.go內容如下
//go:build !race
// +build !race
package race
const Enabled = false
然后就會在原始碼中找到大量 if race.Enabled { ,這種代碼,大家都知道執行go build -race時race.Enabled = true那么這部分判斷就會執行,否則就不會執行,
我的問題是如果每次運行時都進行這些if判斷雖然損耗不了多少性能但卻非常不優雅,但實際上Go會在編譯時檢查確定的判斷,當判斷為false時這部分代碼都會被優化掉,不會編譯到可執行程式中,
驗證編譯優化
package main
const enable = false
func main() {
if enable {
println("hello word")
}
}
執行go tool compile -S main.go > a
package main
const enable = true
func main() {
if enable {
println("hello word")
}
}
執行go tool compile -S main.go > b
然后比較a,b的結果,可以明顯看到當const enable = false時println("hello word")里面的常量字串都不會編譯到可執行程式中,所以我們可以放心使用編譯優化這個功能完成條件編譯,那些編譯時就能計算出結果的if運算式大家可以放心撰寫相關邏輯,這個if是絕對不會在運行時去執行的,
只是麻煩的是代碼中出現的函式,在兩份條件編譯檔案里面都必須有宣告,可以參考race.go,norace.go這兩個檔案的寫法,

總結
有關條件編譯的用法網上有很多資料,所以我這里主要研究條件編譯原理,以及條件可以填寫的所有值,和一些特殊的規則,這樣在我撰寫相關條件時可以更加的心應手
<style>.qm_point{color:#6DA47D;font-size:18px}.qm_a{color:#0000FF}</style> 作者:janbar 出處:https://www.cnblogs.com/janbar 本文著作權歸作者和博客園所有,歡迎轉載,轉載請標明出處,喜歡我的文章請 [關注我] 吧, 如果您覺得本篇博文對您有所識訓,可點擊 [推薦] 并 [收藏] ,或到右側 [打賞] 里請我喝杯咖啡,非常感謝,轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539762.html
標籤:其他
上一篇:keepalived 主備使用
