首页 > 其他分享 >golang编译tag学习

golang编译tag学习

时间:2022-12-12 17:11:54浏览次数:78  
标签:race name golang 编译 tag build go true

官方资料

官方解释: 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 -racerace.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 = falseprintln("hello word")里面得常量字符串都不会编译到可执行程序中,所以我们可以放心使用编译优化这个功能完成条件编译。那些编译时就能计算出结果的if表达式大家可以放心编写相关逻辑,这个if是绝对不会在运行时去执行的。

只是麻烦的是代码中出现得函数,在两份条件编译文件里面都必须有声明,可以参考race.gonorace.go这两个文件的写法。

image

总结

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

标签:race,name,golang,编译,tag,build,go,true
From: https://www.cnblogs.com/janbar/p/16976563.html

相关文章

  • DataGear 制作自定义柱状图条目颜色的数据可视化看板
    DataGear看板提供了dg-chart-options图表选项配置功能,可自定义样式、位置、显示内容等图表选项,其中的processUpdateOptions回调函数配置项,可以在图表更新数据前以编程方式......
  • DataGrid CRUD(MVVM模式)
    引用程序包:MvvmLight实体类:publicclassStudent:ViewModelBase{privateintid;privatestringname;publicintId{......
  • golang的chan用法与fatal error: all goroutines are asleep - deadlock!
    例子1:funcmain(){ch:=make(chanint)ch<-1fmt.Println("发送成功")}上面这段代码能够通过编译,但是执行的时候会出现以下错误:为什么会出现deadlock错误呢?......
  • x64dbg 2022 最新版编译方法
    x64dbg调试器的源码编译很麻烦,网络上的编译方法均为老版本,对于新版本来说编译过程中会出现各种错误,编译的坑可以说是一个接着一个,本人通过研究总结出了一套编译拳法可以完......
  • wsl下docker的ubuntu20.04环境配置mysql、nginx、编译php、编译swoole
    1、docker的ubuntu镜像不识别命令 apt-getupdate #更新 2、aptinstallvim#安装vim编辑器 !!!!!wsl2不用换源,会导致安装依赖时出现版本不对应的情况!!!!! ......
  • 你应该知道的17个Golang包
    前言随着时间的推移,语言爱好者已经构建和共享了许多Go框架和库。这些包执行不同的功能,从开发微服务到制作discord机器人,一直到构建Web应用程序!在本文中,我将尝试让您熟......
  • go-dongle 0.2.1 版本发布,一个轻量级、语义化的 golang 编码解码、加密解密库
    dongle是一个轻量级、语义化、对开发者友好的Golang编码解码和加密解密库Dongle已被awesome-go收录,如果您觉得不错,请给个star吧github.com/golang-module/dong......
  • Spring 6 源码编译和高效阅读源码技巧分享
    一.前言SpringBoot3RELEASE版本于2022年11月24日正式发布,相信已经有不少同学开始准备新版本的学习了,不过目前还不建议在实际项目中做升级,毕竟还有很多框架和中间件......
  • centos源码编译postgis3.2.1
    前言介绍CentOS8源码编译PostGIS3.2.1版本安装官网官方网站​​https://www.postgis.net/​​​源码下载地址​​https://www.postgis.net/source/​​依赖必须PostgreS......
  • golang error 使用
    前言在Go的编程中,error的使用场景数不胜数,主要就是用来处理各种异常情况.长久以来,我的使用方式都是这样的:err:=errors.New("fail")iferr!=nil{//dosom......