C-style conditional compilation in golang
Asked Answered
I

2

33

Does golang support

#define DEBUG 

#ifdef DEBUG 
  fmt.Println("Debug message..."); 
#endif 

So I can build a debug version with zero runtime overhead?

Inspirit answered 15/8, 2016 at 7:26 Comment(2)
Strictly spoken no. There is no preprocessor, and therefore no preprocessor magic.Pilocarpine
like in Java there is not any embedded preprocessor in GoLang but also like Java it is possible to use 3th side similar tools. for instance I use Java Comment Preprocessor + mvn-golang and it makes good resultsGranicus
S
51

Go does not have a preprocessor or a macro system. What you could do is pass in tags to go build through the -tags flag and use build constraints. To do this you would need two versions of the same source and only one would get build depending if the tag is present or not.

Look at build constraints in https://golang.org/pkg/go/build/

main_debug.go

// +build debug

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Debug build")
}

main_release.go

// +build !debug

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Release build")
}

Here go build would compile with main_release.go and go build -tags debug would compile with main_debug.go

Snipes answered 15/8, 2016 at 8:2 Comment(4)
If it's not obvious. You can declare a constant in these files as either true or false since they are mutually exclusive. You can then use that constant in an if-statement. Go will recognize that the if statement is always true or false depending on build tags and remove the code from non-debug builds, or vice versa.Tera
An example of what @JohnLeidegren was talking about can be found herePetroglyph
I want to hide the debug string when I do a release build. Any easier solutions?Fleshy
@Fleshy as a non-idiomatic solution, you can use this preprocessor: github.com/pijng/go-ifdef But it is better to use build tags anywayCalumniate
K
6

if you work on linux or Mac , you can try the "m4" command.This command is a macro processor which just fits this issue.

Writing a Makefile to run the m4 command before "go build" can do the same as using "go build -tags ..." and support more customization and of course, save your work.

for example:

write these within your go file(such as main.go):

define(DEBUG)
ifdef(`DEBUG',
    fmt.Println("Debug message..."); 
)

write these within your Makefile file:

all:*.go
    mv main.go main.go.bak
    m4 main.go.bak > main.go
    go build
    mv main.go.bak main.go

then run "make".

Disadvantage:

  1. You can't write a go function named "define" or "ifndef" etc which will be translated into Macro by m4.
  2. If you have a lot of files you may want to improve your Makefile.
  3. You may want to study m4 which is a little difficult and complicated.
Kushner answered 20/8, 2018 at 11:36 Comment(1)
This is something I have always wanted to do but the major downside that makes it impractical is the fact that linters don't understand m4 and will be terribly confused. Writing code without any linters giving real time feedback is obviously possible, but is rather unpleasant.Countdown

© 2022 - 2024 — McMap. All rights reserved.