0

go build 构建约束//go:build

 1 year ago
source link: https://studygolang.com/articles/35985
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

go build 构建约束//go:build

123445 · 大约2小时之前 · 69 次点击 · 预计阅读时间 2 分钟 · 大约8小时之前 开始浏览    

在看别人源码的时候有时会看到类似这样打头的注释:

//go:build xxxx

比如gin的gin/internal/json包里面就有。

这到底什么意思呢?

这其实是go里面的构建约束,也叫构建标签,build的时候给编译器的标签,可以决定一个文件是否需要包含在包之中。

比如://go:build (linux && 386) || (darwin && !cgo)

表示执行go build的时候,目标系统是386的linux或者没有启用cgo的darwin时,当前文件会被编译进来。

这个就是编译约束。

  • 可以出现在任何源文件里面,不仅仅是go源文件。
  • 必须写在文件顶部,前面只可以有空白行或其他注释
  • 为了区分构建约束和包文件,在构建约束后面应该有一空白行
  • ||&&!运算符(或、与、非)和括号组成的表达式

可用的标签:

  • 目标操作系统,拼写和runtime.GOOS一致,可以用命令go tool dist list查看可能的值
  • 目标系统架构,拼写和runtime.GOARCH一致
  • unix,标识GOOS是Unix或者Unix-like系统
  • 正在使用的编译器,gc或者gccgo
  • cgo,如果支持cgo命令
  • 每个go主要发布版本的术语,比如:go1.1,满足从go1.1版本开始,go1.12从go1.12版本开始,其他类推
  • 通过-tags标记给出的其他标签,-tags多个标签用逗号分隔列出

//go:build ignore:忽略编译

go 1.16和之前的版本的语法是使用// +build,gofmt命令在遇到旧语法时会自动添加等效的新语法

gin的gin/internal/json就是通过标签来确定使用哪个json库的:

go build -tags=jsoniter

go build -tags=go_json

如果一个文件名称,满足如下条件:

*_GOOS
*_GOARCH
*_GOOS_GOARCH

比如一个文件名称source_windows_amd64.go当目标系统是windows系统amd64架构时会包含编译,GOOSGOARCH分别代表目标系统的类别和架构类型,满足上面规则的文件被认为需要满足这些条件的隐式约束。

例如以下文件名:

dns_windows.go:编译windows包时才会本文件

math_386.s:编译包目标是32-bit x86时包含

这样的好处就是,当同一个方法在不通操作系统下实现是不一样的时候,可以用相同的函数名称分别实现,编译的时候根据目标系统类型编译对应系统的源文件:

// test_windows.go
package pkg

import "log"

func PrintOS() {
    log.Println("windows")
}


// test_linux.go
package pkg

import "log"

func PrintOS() {
    log.Println("linux")
}

//main.go
package main

import (
    "test/pkg"
)

func main() {
    pkg.PrintOS()
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK