实例讲解go build tag 标签在交叉编译时的应用
事情是这样的,在一个项目中,我需要读取系统中的某个文件的创建时间,根据时间做不同的处理,如超过一定时间后就删除掉。 查询了一下,获取文件创建时间可以使用标准库中的os 和 syscall 来完成,但是syscall库在不同的系统中的接口是不一样的,如在Mac下是这样使用的
使用FileInfo.Sys() 返回的是一个接口类型,这个接口类型在不同的系统是不一样的,func (fs.FileInfo).Sys() interface{}
在Linux和Mac中是 *syscall.Stat_t
,在windows中是*syscall.Win32FileAttributeData
,
之后再获取属性的时候参数也不一样。。。
上面的代码是linux中是这样的
如果要画一个图表示
上面的其实还不是麻烦的,如果你在Mac上开发的,将来你的程序如果要在windows上运行的话,那么开发的时候写上适合windows的代码,就会在ide上直接报错了,也无法直接编译运行。
此时需要使用交叉编译,比如需要编译一个运行在x64位的windows上,则可以使用以下编译命令
GOOS=windows GOARCH=amd64 go build main.go
就可以正常编译了。
但是一个新的问题就来了,如果我想要在linux上使用,则我需要修改代码,改成可以在linux上运行的,然后使用linux上的交叉编译命令GOOS=linux GOARCH=amd64 go build main.go
,Mac下还要修改代码,这样如果要生成不同的系统可执行文件,则需要不停的修改代码,有没有一种只编写一次的,不用反复修改的?
答案是有的,我们可以使用go:build 标签的方式
我们可以在文件头部添加 //go:build
标识来表示该文件在哪些系统和架构上进行编译
如我们可以单建一个util.go 文件,将获取文件创建时间函数单独抽出来写到这个util.go文件中,假设这里面的函数适用于Mac系统
在最上面的添加一个tag, //go:build darwin
表示这个文件是在darwin 系统上编译使用的
此时我们就可以再创建两个文件,分别为util_linux.go, util_windows.go 文件 然后给它们设置build 标签
go:build 的逻辑关系¶
go:build 标签可以有逻辑关系的,比如我想要设置某个文件在darwin和liunx系统同时编译,可以使用
也可以是且(AND)和或(OR)的关系混合
自定义标签¶
除了GOOS和GOARCH,我们也可以自定义一些标签,如dev,release
那么在编译文件的时候,就可以使用 go build -tags "dev" .
, 则就可以使用带有dev 编译标签的文件进行编译了。
