Conditional compilation in Go language is a very nice feature but what if we want to know at runtime what modules we just compiled (do not confuse with the new Go modules!). We can define a file as a particular module of our application. So, knowing that if the files are compiled or not can be interesting but we haven't a standard mechanism to do this at runtime.
Let supose we have three dummy files main.go
, module1.go
and module2.go
doing nothing and part of package main
.
main.go
file
package main
func main() {
}
module1.go
file
//+build module1
package main
module2.go
file
//+build module2
package main
Build arguments are given at compile time as tags
, eg.:
go build -tags="module1 module2" -o test
Unfortunately the build args are no more accesible after the compiling process, nowhere are writen what was compiled and what not. If we want for example at runtime to print the efective compiled files we simply can't.
Here it come the tricky part. In Go runtime
package we have the Caller() function who knows the current invocation file and can be used to identify if the file is compiled or not. So, our dummy program become like following.
main.go
file
package main
import (
"fmt"
"path/filepath"
"runtime"
"strings"
)
var mods []string
// include this in every init() function to detect linked modules
func _init() {
_, file, _, _ := runtime.Caller(1)
mods = append(mods, strings.TrimSuffix(filepath.Base(file), ".go"))
}
func init() {
_init()
}
func main() {
fmt.Println(mods)
}
module1.go
file
//+build module1
package main
func init() {
_init()
}
module2.go
file
//+build module2
package main
func init() {
_init()
}
We has defined _init()
function which we will include in every init()
functions from every module. At runtime init()
functions will update an array of names which can be easy printed. The Caller()
parameter mean the nesting level.
Running again.
go build -tags="module1 module2" -o test
./test
[main module1 module2]
go build -tags="module1" -o test
[main module1]
This technique suppose that you will have a consistency between the file name and build tags, so, be care to this aspect to avoid confusion.
Enjoy.
Top comments (0)