'What's the difference between `//go:build` and `// +build` directives?
for example, https://github.com/golang/sys/blob/master/cpu/cpu_gccgo_x86.go#L5 :
//go:build (386 || amd64 || amd64p32) && gccgo
// +build 386 amd64 amd64p32
// +build gccgo
package cpu
In my eyes, as a build tag, // +build ... can work well.
Why is //go:build still explicitly specified?
Btw, it is hard to find the mannual of //go:build, but // +build is easy(https://pkg.go.dev/cmd/go#hdr-Build_constraints)
Solution 1:[1]
Go 1.18
The new directive //go:build is now preferred and the toolchain will actively remove old directives; as mentioned in Go 1.18 release notes:
In Go 1.18,
go fixnow removes the now-obsolete// +buildlines in modules declaring go 1.18 or later in their go.mod files.
Due to the above, if you attempt to build a module with go.mod at 1.17 or lower that requires a dependency at 1.18 or above, the build may fail if the dependency is missing // +build lines.
Go 1.17
//go:build is the new conditional compilation directive used to specify build constraints. It was introduced in Go 1.17.
It is meant to replace the old // +build directives; the use case is still same: it "lists the conditions under which a file should be included in the package". The new syntax brings a few key improvements:
- consistency with other existing Go directives and pragmas, e.g.
//go:generate - support for standard boolean expression, e.g.
//go:build foo && bar, whereas the old// +buildcomment has less intuitive syntax. For example AND was expressed with commas// +build foo,barand OR with spaces// +build foo bar - it's supported by
go fmt, which will automatically fix incorrect placement of the directive in source files, thus avoiding common mistakes as not leaving a blank line between the directive and the package statement.
The two build directives will coexist over a few Go releases in order to ensure a smooth transition, as outlined in the relevant proposal document (in the quote below N is 17, emphasis mine):
Go 1.N would start the transition. In Go 1.N:
Builds will start preferring
//go:buildlines for file selection. If there is no//go:buildin a file, then any// +buildlines still apply.Builds will no longer fail if a Go file contains
//go:buildwithout// +build.Builds will fail if a Go or assembly file contains
//go:buildtoo late in the file. Gofmt will move misplaced //go:build and // +build lines to their proper location in the file.
Gofmtwill format the expressions in//go:buildlines using the same rules as for other Go boolean expressions (spaces around all&&and||operators).If a file contains only
// +buildlines,gofmtwill add an equivalent//go:buildline above them.If a file contains both
//go:buildand// +buildlines,gofmtwill consider the//go:buildthe source of truth and update the// +buildlines to match, preserving compatibility with earlier versions of Go.Gofmtwill also reject//go:buildlines that are deemed too complex to convert into// +buildformat, although this situation will be rare. (Note the “If” at the start of this bullet.Gofmtwill not add// +buildlines to a file that only has//go:build.)The
buildtagscheck ingo vetwill add support for//go:buildconstraints. It will fail when a Go source file contains//go:buildand// +buildlines with different meanings. If the check fails, one can rungofmt -w.The
buildtagscheck will also fail when a Go source file contains//go:buildwithout// +buildand its containing module has a go line listing a version before Go 1.N. If the check fails, one can add any// +buildline and then rungofmt -w, which will replace it with the correct ones. Or one can bump thego.modgo version to Go 1.N.
More info about syntax changes: Golang conditional compilation
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
