首页IT科技golang编译器用什么写的(golang编译tag学习)

golang编译器用什么写的(golang编译tag学习)

时间2025-08-06 05:36:22分类IT科技浏览4796
导读:官方资料 官方解释: https://pkg.go.dev/cmd/go#hdr-Build_constraints ,go help buildconstraint 也能看到描述...

官方资料

官方解释: 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这两个文件的写法              。

总结

有关条件编译的用法网上有很多资料,所以我这里主要研究条件编译原理                     ,以及条件可以填写的所有值                     ,和一些特殊的规则,这样在我编写相关条件时可以更加的心应手

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
多层神经网络主要包括(基于Halcon的MLP(多层感知神经网络)分类器分类操作实例)