【问题标题】:How to properly use build tags?如何正确使用构建标签?
【发布时间】:2013-03-05 01:51:53
【问题描述】:

我需要能够构建不同版本的 go 应用程序;一个“调试”版本和一个普通版本。

这很容易做到;我只是有一个 const DEBUG,它控制应用程序的行为,但是每次我需要在构建类型之间交换时都必须编辑配置文件,这很烦人。

我正在阅读有关 go build (http://golang.org/pkg/go/build/) 和标签的信息,我想也许我可以这样做:

config.go:

// +build !debug
package build
const DEBUG = false

config.debug.go:

// +build debug
package build
const DEBUG = true

那么我应该可以使用go buildgo build -tags debug 进行构建,并且标签应该排除config.go 并包含config.debug.go

...但这不起作用。我明白了:

src/build/config.go:3: 在此块 () 中重新声明了 DEBUG 在 src/build/config.debug.go:3 处声明

我做错了什么?

我应该使用另一种更合适的#ifdef 风格的方法吗?

【问题讨论】:

  • 查看 below 了解 Go 1.17 的更新

标签: go build go-build


【解决方案1】:

从 Go 1.17 开始,可以使用新的 //go:build 语法指定构建标签。

至于//go:build指令的放置,新设计说明:

约束可以出现在任何类型的源文件中(不仅仅是 Go),但它们必须出现在文件顶部附近,前面只能有空行和其他 ///* */ cmets。这些规则意味着在 Go 文件中,构建约束必须出现在 package 子句之前。

所以你仍然需要在//go:build 指令和包语句之间留一个空行,否则它可能会被解析为包文档,但是现在:

  • 编译器将拒绝放错位置的指令
  • 运行 go fmt 将自动修复错位的指令

例如在(无空行)上运行go fmt

//go:build foo
package main

import "fmt"

func main() {
    fmt.Println("Hello world")
}

给出(带空行):

//go:build foo

package main

import "fmt"

func main() {
    fmt.Println("Hello world")
}

另请参阅this answer,了解有关新语法有何变化的更多详细信息。

【讨论】:

    【解决方案2】:

    my answer to another question// +build 行之后需要一个空行。

    另外,你可能想要 config.go 中的 !,而不是 config.debug.go;大概你想要一个“DEBUG = false”。

    【讨论】:

    【解决方案3】:

    你可以使用编译时常量:如果你编译你的程序

    go build -ldflags '-X main.DEBUG=YES' test.go
    

    主包中的变量DEBUG 将设置为字符串“YES”。否则,它会保留其声明的内容。

    package main
    
    import (
        "fmt"
    )
    
    var DEBUG = "NO"
    
    func main() {
        fmt.Printf("DEBUG is %q\n", DEBUG)
    }
    

    编辑:从 Go 1.6(?)开始,开关是 -X main.DEBUG=YES,之前是 -X main.DEBUG YES(没有 =)。感谢@poorva 的评论。

    【讨论】:

    • 非字符串数据可以这样吗?
    • @MattJoiner 没有测试所有内容,但可以使用整数。
    猜你喜欢
    • 2015-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2013-04-11
    相关资源
    最近更新 更多