31

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

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

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

配置.go:

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

config.debug.go:

// +build debug
package build
const DEBUG = true

然后我应该能够使用go buildor构建go build -tags debug,并且标签应该 excludeconfig.go和 include config.debug.go

...但这不起作用。我得到:

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

我究竟做错了什么?

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

4

3 回答 3

30

请参阅我对另一个问题的回答。您需要在该行之后有一个空// +build行。

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

于 2013-03-05T02:03:16.793 回答
23

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

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 的评论。

于 2013-03-05T07:04:59.630 回答
3

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

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

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

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

  • 编译器将拒绝放错位置的指令
  • runninggo 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")
}

另请参阅此答案以获取有关新语法的更改的更多详细信息。

于 2021-06-12T08:07:05.710 回答