如何正确使用构建标签?

时间:2013-03-05 01:51:53

标签: build go

我需要能够构建不同版本的go应用程序; 'debug'版本和普通版本。

这很容易做到;我只是有一个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 build”或“go build -tags debug”进行构建,标签应该排除config.go并包含config.debug.go。

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

  

src / build / config.go:3:在此块(< 0>)之前重新声明的DEBUG   声明在src / build / config.debug.go:3

我做错了什么?

我应该使用另一种更合适的#ifdef样式吗?

3 个答案:

答案 0 :(得分:29)

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

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

答案 1 :(得分:21)

您可以使用编译时常量:如果使用

编译程序
go build -ldflags '-X main.DEBUG=YES' test.go

来自包main的变量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的评论。

答案 2 :(得分:0)

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

至于 //go:build 指令的位置,新设计指出:

<块引用>

约束可以出现在任何类型的源文件中(不仅仅是 Go),但它们必须出现在文件顶部附近,前面只能有空行和其他 ///* */ 注释。这些规则意味着在 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 以了解有关新语法的更改的更多详细信息。