Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> In go, if you want a macro, you write a separate go program that generates code, write a "//go:generate" comment, and then have no way of knowing when to run it

You run it every time you do a commit (at least), and then you check in the changes.

Also, you probably run it during development by using a Makefile that will automatically run it whenever the input changes.

This means that downstream packages never have to run it. They don't even have to have the code generation tool installed. This means a package maintainer can use any code generation tool they like.

It was probably done that way due to experience with Bazel, where doing a build means you need to build and run code generators written in multiple programming languages. It does indeed slow things down.



I think the Bazel style is to never check in the generated code, and to generate it at build time (potentially hitting a cache based on the declared inputs, of course). For cases where I use "go generate", I tend to check in the generated file so that you can install the resulting package with "go install". (It's also nice when someone who just wants to work on another part of the code doesn't have to install the generation tool just to run the application/module.)

In this case, you know to run "go generate" because the feature you just added doesn't work. (Though I tend to add a CI rule to make sure that the generator in CI produces the file that is checked into the repo. Because, yeah, you can forget, and it's nice for the computer to double check that.)


> I think the Bazel style is to never check in the generated code

Not necessarily; there is plenty of checked in generated Go code at Google (as well as other PLs, but probably not as much), and other projects (e.g. Entgo) seem to encourage checking in generated Go code as well.


I don't really understand how this approach would work well with IDEs/autocompletion though.

For example, suppose I'm writing some mocked unit tests in Go and want to use mockgen to generate some mocks on an interface...

    //go:generate mockgen (N.B. This generation is done by Bazel)

    type Object interface {
        Thing() string
    }

Then I need to use the generated mocked type in my test:

   mockThing := NewMockObject(ctrl)
   mockThing.EXPECT().Thing().Return("Foo")
But NewMockObject doesn't exist as far as my IDE knows, because the generated code is only generated at build-time and only exists in the Bazel sandbox.

The code will compile and run successfully, but the developer experience is terrible because you lose the ability to use your IDE's code lens, syntax checks, autocompletion. Everything that's generated shows a red squiggly this-doesnt-exist line.

Maybe I'm just fundamentally misunderstanding how Bazel is supposed to be used. My setup is pretty typical. I develop in VS Code, and build using Bazel, but I do not allow Bazel to automate code generation because the generated sources do not appear in my local environment - just in the bazel sandbox.

Maybe someone can suggest a better approach?


Bazel in theory maintains its own directory of generated code that your IDE should refer to. Back when I last used Bazel, there was a bug open to make gopls properly understand this ("go packages driver" is the search term). Nobody touched this bug for a couple years, so I gave up.

Here's the bug: https://github.com/bazelbuild/rules_go/issues/512

I basically wouldn't use Bazel with Go. Go already has a build system, Bazel is best for languages that don't ship a build system, like C++.


This is exactly what I needed. However, the tooling around IDEs and the go packages driver still isn't up to scratch. For example, I can't get code lens to use Bazel for testing individual functions.

I think I agree that Bazel is poor for Go code, sadly it's what our SREs decided to use for our monorepo.


Good IDEs for Java, C# and Rust will handle generated code no problem. I have no idea how VS Code handles this but I’d image it’s a job for the language server. Whether or not Go’s server does it is a different matter - most Go I edit these days is in IntelliJ and built with Bazel, and everything works ok.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: