Go build tag 实现条件编译

更新日期: 2022-05-30 阅读次数: 352 字数: 526 分类: golang

今天遇到了需要使用条件编译的场景,于是查了一下 golang 是如何支持条件编译的。

条件编译简介

go 文档里称之为,Build Constraints,即,编译限制。 也称为 build tag。

//go:build tag_name

其决定了当前文件是否会被当前 package 所包含。

重点:

用于限制一整个文件是否应该被编译入最终的二进制文件,而不是一个文件中的部分代码片段 (block)

build tag 的一些使用场景

  • 测试环境使用 mock 服务;而正式环境使用真实数据
  • 免费版、专业版和企业版提供不同的功能
  • 不同操作系统的兼容性处理。通常用于跨平台,例如 windows,linux,mac 不同兼容处理逻辑。
  • go 低版本的兼容处理

低版本兼容场景示例

例如,我之前就看到 gin 框架下有个 any.go 文件,由于 any 是 go 1.18 引入的别名, 所以其对低版本的兼容处理就是通过 build tag 实现的。

// Copyright 2022 Gin Core Team. All rights reserved.
// Use of this source code is governed by a MIT style
// license that can be found in the LICENSE file.

//go:build !go1.18
// +build !go1.18

package gin

type any = interface{}

使用方法

例如 pro.go 在 main.go 的基础上新增了两个收费版功能:

//go:build pro

package main

func init() {
  features = append(features,
    "Pro 功能 #1",
    "Pro 功能 #2",
  )
}

编译时,加参数

go build -tags pro

go:build 与 +build 的区别

//go:build

是 Go 1.17 中引入的新条件编译指令格式。它旨在替换

// +build

指令。为何要采用新的格式呢?

对比一下新旧格式的区别就知道了:

//go:build linux && amd64 || darwin
// +build linux,amd64 darwin

显而易见的优势:

  • go:build 这种格式,对 coder 来说,更容易理解其逻辑组合
  • 与 //go:embed 和 //go:generate 这些命令相比较,格式上进行了统一

实战案例

go build tag 实现开发环境与生产环境采用不同的 embed.FS 策略

参考

  • https://github.com/golang/go/issues/44484
  • https://www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags
  • https://appliedgo.com/blog/what-s-new-in-go-1-17

爱评论不评论