4

The release of the 'generate' tool opens up a whole lot of exciting possibilities. I've been trying to make my tests better. I have a function which queries an external API, the location of that API is defined in a global variable. One piece of the puzzle is replacing that value with a value determined at 'generate time'.

I have:

//go:generate gofmt -w -r "var apiUrl = a -> var apiUrl = \"http://example.com\"" $GOFILE

Running go generate then errors out with:

parsing pattern var apiUrl = a  at 1:1: expected operand, found 'var'

It's not an option to use a place holder like so:

gofmt -r 'API_GOES_HERE -> "http://example.com"' -w

That's because, when I compile production code, the source gets rewritten, so subsequent compiles for testing no longer can replace the place holder (it has been replaced already).

I realise I'm abusing gofmt somewhat but I'd rather not go back to sed. What would be the valid go:generate statement?

harm
  • 10,045
  • 10
  • 36
  • 41
  • After extensive searching, I'm fairly sure this is impossible with just gofmt. The good news is that go generate can, AFAIK, run arbitrary scripts in your $PATH so you should be able to get go generate to run sed or whatever else just fine. – Linear Dec 17 '14 at 10:11
  • I was afraid you'd come to that conclusion. Back to `sed` then. Thanks. – harm Dec 17 '14 at 10:22
  • Yeah, I think the only real way is to write your own generation script and template, using os.Expand or something, and if you can accomplish the same thing with sed you may as well just sed. – Linear Dec 17 '14 at 10:39

2 Answers2

3

You can use a linker flag -X for that. For example,

go build -ldflags "-X main.APIURL 'http://example.com'"

will build your program with APIURL variable set to http://example.com.

More info in the linker docs.


Go 1.5 edit: starting with Go 1.5, it's recommended to use the new format:

go build -ldflags "-X main.APIURL=http://example.com"

(Note the equals sign.)

Ainar-G
  • 34,563
  • 13
  • 93
  • 119
1

In your test file say api_test.go add a generate command that produces another file called api_endpoint_test.go that is in the same package and only defines or inits ( using an init function ) the variable you need. That variable value will only be used during testing.


For the record, I don't quite know understand why you are trying to do it this way, instead of either initiatializing the variable during runtime or using some conventional configuration method.

Emil Davtyan
  • 13,808
  • 5
  • 44
  • 66