英文:
How to properly use build tags?
问题
我需要能够构建不同版本的go应用程序;一个是“debug”版本,一个是普通版本。
这很容易做到;我只需要一个控制应用程序行为的常量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: DEBUG在此块中重新声明(<0>),之前的声明在src/build/config.debug.go:3中
我做错了什么?
还有其他更合适的#ifdef风格的方法可以使用吗?
英文:
I need to be able to build different versions of a go application; a 'debug' version and a normal version.
This is easy to do; I simply have a const DEBUG, that controls the behaviour of the application, but it's annoying to have to edit the config file every time I need to swap between build types.
I was reading about go build (http://golang.org/pkg/go/build/) and tags, I thought perhaps I could do this:
config.go:
// +build !debug
package build
const DEBUG = false
config.debug.go:
// +build debug
package build
const DEBUG = true
Then I should be able to build using go build
or go build -tags debug
, and the tags should exclude config.go
and include config.debug.go
.
...but this doesn't work. I get:
> src/build/config.go:3: DEBUG redeclared in this block (<0>) previous
> declaration at src/build/config.debug.go:3
What am I doing wrong?
Is there another and more appropriate #ifdef style way of doing this I should be using?
答案1
得分: 32
请参见我对另一个问题的回答。在// +build
行之后需要一个空行。
另外,你可能想要在config.go中使用!
,而不是在config.debug.go中;并且你可能想要其中一个为"DEBUG = false"。
英文:
See my answer to another question. You need a blank line after the // +build
line.
Also, you probably want the !
in config.go, not in config.debug.go; and presumably you want one to be "DEBUG = false".
答案2
得分: 22
你可以使用编译时常量来实现:如果你使用以下命令编译你的程序:
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)
}
英文:
You could use compile time constants for that: If you compile your program with
go build -ldflags '-X main.DEBUG=YES' test.go
the variable DEBUG
from package main will be set to the string "YES". Otherwise it keeps its declared contents.
package main
import (
"fmt"
)
var DEBUG = "NO"
func main() {
fmt.Printf("DEBUG is %q\n", DEBUG)
}
Edit: since Go 1.6(?) the switch is -X main.DEBUG=YES
, before that it was -X main.DEBUG YES
(without the =
). Thanks to a comment from @poorva.
答案3
得分: 4
从Go 1.17开始,可以使用新的//go:build
语法来指定构建标签。
至于//go:build
指令的放置位置,新的设计规定:
> 约束条件可以出现在任何类型的源文件中(不仅限于Go),但它们必须出现在文件的顶部附近,仅在空行和其他//
和/* */
注释之前。这些规则意味着在Go文件中,构建约束条件必须出现在包声明之前。
因此,在//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")
}
<hr>
有关新语法的更多详细信息,请参见此答案。
英文:
As of Go 1.17, build tags can be specified with the new //go:build
syntax.
As for the placement of the //go:build
directive, the new design states:
> Constraints may appear in any kind of source file (not just Go), but they must appear near the top of the file, preceded only by blank lines and other //
and /* */
comments. These rules mean that in Go files a build constraint must appear before the package clause.
So you still need to leave a blank line between the //go:build
directive and the package statement, otherwise it could be parsed as package documentation, however now:
- the compiler will reject misplaced directives
- running
go fmt
will automatically fix misplaced directives
For example running go fmt
on (no blank line):
//go:build foo
package main
import "fmt"
func main() {
fmt.Println("Hello world")
}
gives (with blank line):
//go:build foo
package main
import "fmt"
func main() {
fmt.Println("Hello world")
}
<hr>
See also this answer for further details about what changes with the new syntax.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论