gen: Type-driven code generation for Go

gen is an attempt to bring some generics-like functionality to Go. It uses type annotations to add “of T” functionality to your packages.

gen generates code for your types, at development time, using the command line. It is not an import; the generated source becomes part of your package and takes no external dependencies.

Source

Quick start

Start by installing Go, setting up paths, etc. Then:

go get github.com/clipperhouse/gen

Create a new Go project, and cd into it. Create a main.go file and define a type.

Now, mark it up with a +gen annotation in an adjacent comment like so:

// +gen slice:"Where,Count,GroupBy[string]"
type MyType struct {}

And at the command line, simply type:

gen

You should see a new file, named mytype_slice.go. Have a look around.

Annotations

The annotation syntax will look familiar to Go users, it is modeled after struct tags.

// +gen [*] tag:"Value, Value[T,T]" anothertag

The annotation is a comment that begins with the +gen directive. It is optionally followed by a *, indicating that the generated type should be a pointer. Then, struct-style tags which include any number of values. In turn, each value can have optional type parameters. Tags can be “naked” (without values), as in anothertag above.

The tags & values are interpreted by TypeWriters.

TypeWriters

gen is driven by “type writers” – packages which are responsible for interpreting the annotated tags and turning them into generated code. Learn more…

Usage

Type gen help:

gen           Generate files for types marked with +gen.
              Optional -f flag (force) to ignore type-check errors
gen list      List available typewriters.
gen add       Add a third-party typewriter to the current package.
gen get       Download and install imported typewriters. 
              Optional flags from go get: [-d] [-fix] [-t] [-u].
gen watch     Watch the current directory for file changes, run gen
              when detected. 
gen help      Print usage.

FAQ

Why?

The goal of gen is not just to offer conveniences, but stronger typing. By generating strongly-typed methods and containers, we avoid having to use interface{}s, type assertions and reflection.

We gain compile-time safety and (perhaps) performance.

Codegen, really?

Yes! It felt a bit dirty to us at the beginning, too. But it turns out that a lot of actual generics implementations look a lot like code generation – you just don’t see it. (Compilers and JITs do it for you.)

Code generation removes mystery. It’s just code, right there in your package. Read it. The history goes in your repo like everything else.

You get all the usual compiler checks and optimizations, of course, so gen won’t introduce surprises in production.

gen is a tool that helps the developer produce code on their local workstation, alongside their text editor and utilities.

Is there a video?

Glad you asked, yes.

Wait, is this go generate?

No, that’s different (and very cool). go generate will run any command and is intended to obviate make files and such. gen is specifically about codegen for types.

The two tools are complementary.

Can I run gen on the server?

Like as part of the build? Sure, but that’s not what it’s designed around so we don’t recommend it.

It’s a local dev tool, not a platform or (shudder) a framework. Run it locally, test it, and commit the generated code to the repo.

What if my code is incorrect?

gen parses and type-checks your source code. Having correct, buildable source code before you begin is important.

That said, there are classes of errors that gen can optionally tolerate, via the -f (force) flag. Learn more…

Published January 1, 0001