
Generating code - dctrwatson
http://blog.golang.org/generate
======
codemac
What's so confusing from this post, is the complete lack of motivations for
why anyone would want this over a shell script at the root of their project.
I'd rather it even blindly rerun the command every `go build` than this half
hearted attempt.

This looks much like my team's `make update` rule (that merely runs
./mk/update.sh). Well, except now the dependencies on external tools are
scattered throughout your project. Oh and build failures wouldn't even tell
you that you need to run go generate.

What a mis-step. Then again, maybe I'm somehow mistaking a build system with a
compiler[0]?

[0]:
[https://news.ycombinator.com/item?id=8733493](https://news.ycombinator.com/item?id=8733493)

~~~
TheDong
Worse yet, a shell script would work whereas go generate does not.

Go generate is probably the most half-assed thing the go team has done yet.

Now, I know the above line is harsh, but I don't say that without proof. Run
the following and bear witness to its terrible implementation.

    
    
        curl http://pastebin.com/raw.php?i=fhu14iwk > main.go
        cat main.go
        go run main.go
        go generate -v main.go
        go generate -help
        go generate -x -v -run ".*(echo|one).*"
    

Yeah...

If you don't feel like looking at the above, the implementation of go generate
is a hack of substring matching, not language parsing, and it also doesn't
implement, in its production release, the "-run" flag documented in "-help".

~~~
bluesign
I don't think this is a valid test case, as far as I understand, //go:generate
works like "preprocessor directive".

Maybe I can agree that // prefix is a bad choice, as coming from C world I
would prefer #

~~~
TheDong
Here's a corresponding C program in which I use a #define that is not
processed by the pre-processor since it's not a dumb string matcher.
[http://pastebin.com/raw.php?i=dE7QsTgS](http://pastebin.com/raw.php?i=dE7QsTgS)

Define might be. But actual directives are not. In go, the directives are.

------
slashnull
[http://c2.com/cgi/wiki?CodeGenerationIsaDesignSmell](http://c2.com/cgi/wiki?CodeGenerationIsaDesignSmell)

Obligatory

~~~
enneff
Once again, the c2 wiki brings the goods. A nice discussion of the reasons you
do and do not want to do code generation. Thanks for the link.

~~~
slashnull
TVTropes (to a certain, ludic, extent) and especially c2 convinced me that the
conventional wiki + opinions formula occasionally works really, _really_ well.
In the pretty eerie context where everybody's passionate about the subject,
that a mature level of discussion and a reasonable level of mind-share ensure
that conflicting POVs are expressed, discussed without ever stuff falling down
into wedge politics and flame warfare.

I can't read the wikipedia these days, there aren't _enough opinions_.

------
dilap
I have a lot of faith in the Go folks, as I've found the language to be a
pleasure to work with in practice -- basically very well-thought-out.

But man, I don't know...having to manually run a generate command when eg
changing string constants seems pretty weird. And if you change the constants
without rerunning go generate (manually!) you may get nonsense values. It
seems pretty creaky!

Maybe it will end up working out well in practice. (As Go tends to do.)

~~~
dsymonds
It doesn't really happen all that often in practice, and when you're hacking
on a package that relies on this it's easy enough to have `go generate && go
test` sitting in your shell history for that iteration cycle.

~~~
dilap
Well, I think the jury's still out, since there hasn't been a lot of use in
the wild yet. I realize it can be quite frustrating to get negative feedback
from people who haven't even used a feature yet, so I hope I'm not coming
across as overly negative. I am overall a huge fan of Go :)

And I do appreciate the minimalistic nature of the approach...

I expect we'll start to see people do a lot of generics-type stuff with this
-- e.g., add an go:generate annotation to get a customized Foo collection or
whatever.

It'll be interesting to see how it shakes out.

~~~
blakecaldwell
I imagine most of the complaining is by people that haven't even spent much
time in the language, let alone this new tool.

I'm would wager that generics were a driving force behind this. They don't
want to add them to the language (fair), but are willing to offer a way for us
to add them at precompile time.

~~~
lomnakkus
How would that work? AFAIU the idea is that library authors _check in_ the
generated code -- so a consumer of your code wouldn't be able to (or at least
would be actively discouraged from) generate new code for a library. And thus
wouldn't be able to generate "instances" for generic code.

~~~
blakecaldwell
I haven't spent much time looking into this, and haven't used it yet, but from
the Stringer example, they're providing us with a tool to generate strings for
enum values. That same approach could be used to generate support for typed
collections for your types. I could make the collection-generating code, and
you could generate the collections for your types.

~~~
lomnakkus
Yeah, for _your_ types, but if I'm a provider of a library of generic data
structures (which is what the people asking for generics are probably thinking
about), you're out of luck since I have no way of letting _you_ generate
appropriate instances.

------
zupa-hu
What upsets me about go generate is that it is orthogonal to the language, yet
it comes baked in. It unnecessarily increases the footprint of the language,
while essentially killing any alternative approaches. Feature creep comes one
feature at a time, I guess.

[ps. yet thank you big time for being able to program in golang]

~~~
dsymonds
Why does it upset you that it comes baked in? If you don't care for it, don't
use it. It's for package authors, so you won't be exposed to it unless you
want to.

~~~
zupa-hu
This is valid about any feature. It's like adding 10.000 pages to the docs and
saying you don't need to read them unless you want to.

------
wes-exp
Greenspun's tenth rule rears its ugly head. Go reinvents Lisp macros, poorly.

~~~
4ad
Lisp macros are runtime code generation. This is not runtime code generation,
it's code generated at some arbitrary time by the author, it's not even build-
time code generation. This feature has a completely different use-case than
Lisp macros, the comparison is completely unwarranted.

~~~
lispm
Lisp macros are not really 'runtime' code generation. There is a reason one
might say that it is, but that's because a full Lisp is available during
compilation.

In a typical Common Lisp project, Lisp macros generate the code at compile
time. Since a full Common Lisp is available at compile time, this looks
similar to runtime, but it isn't. For that the macro itself and the code it
needs to run needs to be available during compilation.

During development the compile-time and runtime code often run inside the same
Lisp system. But that's a certain style of development and not necessary. It's
also possible that the generated code will form an application, which then
runs outside of the compile environment.

To take a typical data structure declaration and to generate compile-time code
for it is quite typical. What Lisp typically not do is to dump the generate
code as source to a file, but to feed the generated code to the compiler and
then create compiled code.

------
Animats
I'm a bit surprised that the Go team did this. They already have a Go code
generator for Google protocol buffer marshaling code.
([https://github.com/golang/protobuf](https://github.com/golang/protobuf))
This new generator scheme doesn't seem to be suitable for integration with
that.

(Why does every language now have to come with its very own build/packaging
environment, with its very own directory structure conventions? Go has one,
Rust has a different one, Java has several, and a new one for Python was
discussed here yesterday.)

~~~
twotwotwo
I'd guess Go has one to avoid ending up with several like Java, to do Go-
specific things like extract the dependency graph from the source code, and to
have one fewer dependency on the platform--I don't know much about how you
build on plan9 or Solaris, I know go build is the same program on each.

That said, go tools are canonical but not mandatory. If switching to this
doesn't work for the protobuf foks, it's simple enough not to switch.

~~~
twotwotwo
(and as dsymonds points out, go generate is not a _replacement_ for a code
generator, so "switch" isn't even the right word.)

------
zak_mc_kracken
Little by little, the Go team is reinventing a build system.

~~~
stefantalpalaru
Those who ignore Autotools are condemned to reinvent it. Poorly.

~~~
dilap
This can't be true, because it is impossible to create a build system that is
worse than autotools.

~~~
crpatino
You can always emulate all autotools' shortcomings, you know, for backwards
compatibility. And then add a bunch of defects of your own making on the top.

------
bfrog
This is a pretty simple little thing, not even sure what it really brings new
to the Go table except saying to the community "this is how we think it should
be done, and how we now do it"

------
ankurpatel
Does go support meta programming? I feel that this seems more like Macros
replacement or build tasks that generate files which are included compile
time.

------
geoka9
I think the article (and the command itself) is a bit of misnomer. It can be
used to run any shell command, which doesn't have to generate anything.

~~~
dsymonds
It's true that it's more general, but the name is chosen to indicate what its
intended use is, namely generating code.

------
uaygsfdbzf
Committing generated code is just a recipe for badness. I never commit the
output of cpp/yacc/etc to git, why would I do that for go stuff?

~~~
4ad
You should definitely commit the output of yacc to git. This way not only you
don't require your users to have yacc, but you make sure they are using the
correct yacc version; you know, the one you tested against. And when you
change the yacc version, you'll know because it's in your history; otherwise
it's hard to remember at which particular time you decided to upgrade the yacc
version used by the project.

Committing cpp output makes no sense because cpp output is specific to the
machine which ran cpp.

~~~
uaygsfdbzf
Ick...

------
wtf_is_up
I'm surprised that people actually like make and autotools.

------
Zenst
TL;DR Go has its own version of make in the toolset now.

~~~
dsymonds
`go generate` is not at all like `make`. I don't think you read the article
carefully enough.

~~~
enneff
To expand on why it's not like make: it doesn't do dependencies.

Think of 'go generate' as a codified 'gen.sh'.

~~~
dsymonds
Well, it's more than just dependencies. `go generate` isn't meant to be
involved at all if you're just building a package or command for using it,
which is quite a bit different to `make`.

~~~
jerf
Now put those two together, and you can understand what the idea here is: It
doesn't do dependencies and it isn't meant for end users, only package
authors.

The Go philosophy is that if you truly need a make file or other such system,
use it. It's always been that way, actually; if you poke hard enough you can
still find old Go tutorials which require you to use make (or some other build
tool). But if you need it for just this simple little thing, you shouldn't
have to pull in make, just as the developing Go philosophy is that it is silly
to pull in entire packages for one little function. The purpose of "go
generate" is not to replace make; it is to close out another 80% of the uses
of make (my made-up number) by offering a simple, high bang-for-the-buck
addition that can be depended on in the base language.

Some projects will still need make. This expands the set that don't. There's
no interest in trying to make this grow to include all things that use make.
It fits the pragmatic philosophy of Go.

