Self-hosted service
kubernetes/gengo avatar
kubernetes/gengo

gengo is the code generator Kubernetes factored out of its own tree

gengo library for code generation.

579 stars211 forksGoApache-2.0

At a glance

What is it?
gengo is a Go library for generating code from Go source files, extracted from the Kubernetes code-generator so it could be reused and maintained separately, with a set generator, a deep-copy generator, a defaulter generator, a go-to-protobuf generator and an import rule enforcer. It suits a Go project that wants generated code from type definitions, and it is a v1 line with a v2 module under development.
Who is it for?
Adopt gengo when you are writing a Go code generator that reads Go types, particularly if you want the Kubernetes style of generator rather than a template engine over your own AST, and prefer the v2 module for new work since the v1 line is what the stable releases point at. Skip it if you only need a template pass over a hand-maintained struct, because gengo's type system and parser are the heavy part of the cost.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A package for generating things based on Go files

The project describes itself as a package for generating things based on go files, and the mechanism was first used in the Kubernetes code-generator before being split out here for ease of reuse and maintainability. That origin is the single most useful fact for evaluating it, because it tells you what shape of problem the library was built for. This is not a general purpose templating tool that happens to have a Go binding. It is the code generation framework that Kubernetes uses to produce its own API machinery, extracted so that other projects, and Kubernetes itself, can use it without vendoring a piece of the main repository. The Go module path is k8s.io/gengo, and the README notes that k8s.io/gengo/v2 is the current development module, with the v2/ directory at the root of the tree. That split between a stable v1 and an in-progress v2 is the first thing to check before depending on it, since the go.mod at the root still declares go 1.13.

The type system is modelled on Go's but deliberately not Go's own

The types/ package contains the type system definition, and the README is unusually candid about a design decision that has real consequences. It is modeled after Go's type system, but it is intended that you could produce these types by parsing something else if you want to write the parser or converter yourself. The next paragraph gives the reason: the library does not directly use the Go types in the go typecheck library because those are based on implementing differing interfaces, and a struct-based format is more convenient input for template driven output. In other words, gengo defines its own type representation rather than adapting go/packages output, which buys a stable, template friendly input at the cost of a conversion step. For a generator author this is usually the right trade, since the alternative is a template that has to cope with the type checker interfaces directly. It also means the type model is not locked to Go, and the parser/ package exists separately to parse Go source files and feed it.

The generator interfaces are the extension point, and args handles the flags

The generator/ package defines interfaces for code generators to implement, and the machinery that will execute those code generators. That is the contract a new generator implements, and it is the reason the package is usable at all: the parsing, the type system and the execution model are already handled, so a new generator is largely a template plus a visitor. The args/ package defines common arguments for a generator binary, which is a small but meaningful piece of the design, because it means every generator in the ecosystem takes the same flags for input packages, output base, and the boilerplate directory, and a user does not have to learn a new convention per tool. The namer/ package then handles the naming problem, and its README description lists three jobs: helping you reference go objects in a syntactically correct way, keeping track of what you reference so the right packages are imported, and defining parallel tracks of names so that public interfaces and private implementations can be named differently. A name generator without that third capability cannot produce the public/private split Kubernetes needs.

Four generators ship in the box, and they cover the common API cases

The examples section lists what is included. A set generator, a deep-copy generator, a defaulter generator and a go-to-protobuf generator are included, and import-boss will enforce arbitrary rules about import trees. Each of those is a real, non-trivial generator, and together they cover the four tasks most Kubernetes-style projects need. The deep-copy generator is the classic one, since API types in Kubernetes have to be copyable and hand writing DeepCopy methods for a large API surface is exactly the tedium that motivated a generator in the first place. The set generator produces the set accessor methods for list types, the defaulter produces defaulting logic, and the go-to-protobuf generator produces the protobuf definitions from Go types. The repository has an examples/ directory with a separate project for each, named deepcopy-gen, defaulter-gen, import-boss and set-gen, so each one is a working reference rather than a fragment.

import-boss turns layering rules into a build failure

The import-boss generator deserves separate attention because it solves a different problem from the others. The other generators produce code, while import-boss enforces arbitrary rules about import trees, and the rules live in the .import-restrictions file at the root of the repository. The idea is that a package may not import certain other packages, and violating that is a compile or CI error rather than a code review comment. In a repository like Kubernetes this matters more than it seems, because the API machinery, the client machinery and the internal packages have strict layering rules, and violations are easy to introduce by accident with an IDE autocomplete. For a smaller project the same mechanism gives you the architectural boundaries you would otherwise state in a wiki page and hope people read. The example project is examples/import-boss, and there is a dedicated .import-restrictions file in the tree.

The Makefile builds two trees and verifies the go directive

The build file at the root is short and tells you the structure of the repository. The all target runs go build ./... and then make -C v2 all, so the v1 line and the v2 line are built as separate trees. The test target runs go test -race ./... with the race detector, then tests the generated output of the defaulter-gen example with go -C ./examples/defaulter-gen/output_tests test ./..., and then runs the v2 tests. That second step is worth noting, because it means the generated code is itself under test rather than being compared by eye. The verify target runs hack/verify-examples.sh and hack/verify-go-directive.sh with the argument 1.20, and the Makefile explains why: the maximum version of the go directive is verified as 1.20 because the oldest go directive that exists on the supported release branches in the Kubernetes repository is 1.20. So the compatibility floor is a deliberate, tested property rather than a documentation claim, and the same target is run for the v2 tree.

Where gengo is the wrong choice

Three situations argue against it. The first is a project that only wants to render a struct into a template, because gengo's value is that it reads Go source, builds its own type model from that, and drives a visitor over the types, and all of that machinery is wasted on a fixed shape you already know at compile time. A text or template template is smaller and clearer for that job. The second is a team that wants the latest language features today, because the type model is a reimplementation rather than the compiler's own types, and it tracks the Go version it was written against, with the go.mod here declaring go 1.13 and the tooling pinned to a 1.20 floor. A generator that mis-models a newer language feature will fail in confusing ways, so the version gap between your toolchain and the library's model is a real cost. The third is a project that wants the outputs to look like everything else in its ecosystem, since gengo's outputs carry the Kubernetes style, with its boilerplate directory and its naming conventions, and matching that style in a codebase that has no Kubernetes history means adopting conventions you did not choose. The realistic alternative for a general Go project is to write a generator over the standard library's go/packages and types, which costs more work per generator but keeps your output idiomatic to your repository and your toolchain.

Editorial conclusion

Adopt gengo when you are writing a Go code generator that reads Go types, particularly if you want the Kubernetes style of generator rather than a template engine over your own AST, and prefer the v2 module for new work since the v1 line is what the stable releases point at. Skip it if you only need a template pass over a hand-maintained struct, because gengo's type system and parser are the heavy part of the cost. Verify first which module path you depend on, since k8s.io/gengo/v2 is the current development module while the published releases track the v1 line.

Frequently asked questions

What is the gengo library?

It is a Go package for generating things based on go files. The mechanism was first used in the Kubernetes code-generator and was split out into this repository for ease of reuse and maintainability, and the module path is k8s.io/gengo.

Which generators does gengo include?

A set generator, a deep-copy generator, a defaulter generator and a go-to-protobuf generator are included, and import-boss will enforce arbitrary rules about import trees. The repository has a separate example project for each under examples/.

Should I use k8s.io/gengo or k8s.io/gengo/v2?

The README states that k8s.io/gengo/v2 is the current development module, while the repository publishes no GitHub releases and the root go.mod still declares go 1.13 with dependencies pinned to a release branch. New work is expected to target v2.

How does gengo's type system relate to Go's own types?

It is modeled after Go's type system but is a separate definition, because the library does not directly use the Go types in the go typecheck library, which are based on implementing differing interfaces. A struct-based format is more convenient as input for template driven output, and the types could equally be produced by parsing something other than Go.

Is gengo still maintained?

The repository is not archived and the last push was on 2026-04-08, though it publishes no GitHub releases. The licence is Apache-2.0, the primary language is Go, and the Makefile builds and tests both the root tree and the v2 tree, including a check of the go directive against 1.20.

Official sources

  1. Issues
  2. kubernetes/gengo on GitHub
  3. License: Apache-2.0
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kubernetes-gengo.svg)](https://hysenlabs.com/projects/kubernetes-gengo)

Was this useful?