Go build tag 实现条件编译

文章目录

    今天遇到了需要使用条件编译的场景,于是查了一下 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

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式