30

Does golang support

#define DEBUG 

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

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

tink
  • 14,342
  • 4
  • 46
  • 50
can.
  • 2,098
  • 8
  • 29
  • 42
  • 1
    Strictly spoken no. There is no preprocessor, and therefore no preprocessor magic. – lofcek Aug 15 '16 at 07:37
  • 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](https://github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/mvn-golang-examples-preprocessing) and it makes good results – Igor Maznitsa Feb 12 '17 at 13:02

2 Answers2

47

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

aebudak
  • 641
  • 6
  • 8
  • 19
    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. – John Leidegren Jun 04 '19 at 09:09
  • 2
    An example of what @JohnLeidegren was talking about [can be found here](https://www.reddit.com/r/golang/comments/a8xb0x/conditional_compilation_and_omission_of_certain/ecenc1c/?utm_source=reddit&utm_medium=web2x&context=3) – Marco A. Sep 29 '21 at 10:48
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.
  • 2
    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. – Roflcopter4 Nov 21 '18 at 03:50