# gotk4 generates GTK4 bindings for Go from the GIR files

> gotk4 is a generator plus a set of generated packages that give Go programs access to GTK4 through the GObject introspection data. It ships both GTK 4.14 and 4.16 branches, warns openly about leaks and missing API in places, and licenses its three directories differently.

**diamondburned/gotk4** — Autogenerated GTK4 bindings for Go

- Repository: https://github.com/diamondburned/gotk4
- Stars: 706 · Forks: 31
- Language: Go
- License: AGPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/diamondburned-gotk4

## Two directories: the generator and the packages it produces

gotk4 is not a hand written binding library, and understanding that shapes everything else about it. The project is split in two. The generation code lives in gir/girgen/, and every package it produces is checked into pkg/. The input is the GObject introspection data that GTK itself ships, and the project links its own GIR documentation for reference. That architecture has a clear benefit and a clear cost. The benefit is breadth: a whole toolkit surface appears in Go without anyone typing thousands of wrappers by hand, and the binding follows the introspection metadata of the GTK version you point it at. The cost is that the generated code is only as complete as the introspection data, and its quality is the generator's quality. A binding that is missing is missing because the generator did not emit it, and a binding that leaks is leaking because the wrapper does not release a reference. The repository root holds the module definition in go.mod, a small gotk4.go, the gir and pkg trees, and a set of tooling files including a flake.nix, a shell.nix and a Dockerfile.

## A branch for each GTK version you target

The version table in the README is short and it answers the first question any adopter asks. GTK 4.14 is served by the branch named 4, and GTK 4.16 is served by the branch named 4.16, with the default branch being 4. This is the practical constraint that shapes adoption, because a Go program compiled against one branch of generated bindings expects a matching GTK runtime on the other side. A distribution packaging GTK 4.16, or a user on a rolling release, will not run a binary built from the branch that targets 4.14 without surprises. The project notes also state that most of pkg/gtk/v4 and pkg/gtk/v3 are ready to be used for most purposes, which is worth parsing carefully. Both the GTK 4 and GTK 3 package trees exist inside gotk4, so a codebase that must still speak to GTK 3 can find a package for it here,, and the gotk3 organization is credited in the licence section for maintaining the Cairo package. The examples live in a separate repository, diamondburned/gotk4-examples, which is where the getting started instructions are documented.

## The module requires Go 1.24 and keeps its packages in a second module

The go.mod at the repository root defines the module as github.com/diamondburned/gotk4 and pins the language version.

```
module github.com/diamondburned/gotk4
go 1.24.0
```

The direct requirements are a small set of general purpose libraries, the assert helper from alecthomas, go-spew for dumping values, fatih/color for terminal output, and golang.org/x/sync, with the remaining entries marked as indirect. Two things stand out for a consumer. The first is the Go floor: 1.24.0 is recent, so a build pinned to an older toolchain will not build this module. The second is structural, and it is easy to miss. The generated packages are not part of the root module. The Dockerfile copies go.mod and go.sum separately for the root and for pkg/, and runs go mod download in both, which means pkg/ is a module of its own that you import by its own path rather than through the parent. Anyone vendoring or replacing a dependency in a Go project needs to handle that second module explicitly, because a go.mod edit in the root has no effect on the package you actually import.

## The Dockerfile gives you a Nix shell, not a compiled binary

The Dockerfile in the repository is a development environment rather than a packaging recipe, and it is built on Nix.

```dockerfile
FROM nixpkgs/nix
WORKDIR /gotk4
ENV NIX_PATH="nixpkgs=channel:nixos-unstable"
```

It then installs a Nix profile with the nix-command and flakes experimental features enabled, initialises a docker-env wrapper, and sets that wrapper as both the shell and the entrypoint, so commands inside the container run through the environment it prepares. The Go module files are copied and downloaded as a separate layer before the rest of the source, which is ordinary Docker layer caching and nothing more. The final instruction drops into bash. The image is a developer tool, so the useful question is what it gives you. It gives a consistent shell with the Nix packages the flake defines, which matters for a project whose generator depends on the GTK development files and the introspection tooling, and where the versions of those tools decide what the generated output looks like. The base channel is nixos-unstable, so the toolchain that produces your bindings can change underneath you between builds, which is a real consideration for reproducible output.

## The project admits leaks, crashes and missing API

This is the section that should decide whether you adopt the project, and it is unusually candid. The project notes state that as of the time they were written, most of pkg/gtk/v4 and pkg/gtk/v3 are ready to be used for most purposes, but that memory leaks and sometimes crashes may occur in certain parts of the API, while other parts might be completely missing. The instruction for that case is to open an issue. That is an honest description of generated bindings, and it comes with a practical consequence for anyone shipping a desktop application. A missing method is a compile error, which is a cheap failure. A leak in the wrapper layer is not, because it shows up as memory growth over a long session rather than as a stack trace. If your application keeps a window open for hours, the parts of the API that the project flags as leaky are exactly the ones you want to know about, and the project notes do not tell you which parts those are. The Progress tracker issue in the tracker list is where the wider state of coverage is discussed, so that is the place to look before committing to the library.

## Three directories under three different licences

The licensing is unusual enough to be worth reading line by line, because a single repository here carries three licences. The gir directory, which holds the generator, is licensed under the GNU Affero General Public License v3, and the licence section adds the important qualifier that this licence does not apply to the code the generator produces. The pkg directory, the generated bindings you actually import, is licensed under the Mozilla Public License v2. The pkg/cairo package is under the MIT licence, originally written by Conformal Systems and later maintained by the gotk3 organization. The practical reading is that consuming the bindings carries the MPL v2 obligations, and that modifying the generator itself puts you under the AGPL v3. The MPL is file-level copyleft, so the obligations attach to the files you modify rather than to your application as a whole, but that is a legal question and not an engineering one, so treat it as a matter for your own review. The project also credits small snippets taken from tinyzimmer's go-glib, which implements type subclassing, and the art assets have their own terms: the logo is CC0 derived from the gophers artwork, the gopher itself is Creative Commons Attribution 4.0, and the GTK logo is Creative Commons Attribution-ShareAlike 3.0 taken from the GNOME project.

## Release rhythm, upgrade notes and where to ask questions

The project is small and moves in a regular way. The last push was on 2026-08-09, the same day that produced both the v0.4.1 tag and the pkg/v0.4.1 tag, which reflects the two module layout rather than two different features, and v0.4.0 came a little earlier on 2026-07-30. Two files in the repository root are directly relevant to adopting a version. CHANGELOG.md records what changed, and UPDATING.md is the one to read before moving a project between releases, since a generated binding changing shape is exactly the kind of break that shows up as a compile error in your own code. The repository also carries a Dockerfile, a flake.nix and a shell.nix, so the toolchain for regenerating or testing bindings is defined in the tree. Questions and discussion go to the gotk4 Matrix room rather than to the issue tracker, with contributions following the guidelines in CONTRIBUTING.md. The version pairs here, a root tag and a pkg tag for the same release, are the detail to internalize before you script anything against the tags.

## Conclusion

Adopt gotk4 when a Go program needs a real desktop toolkit and you would rather consume generated bindings than maintain cgo glue by hand, and when you can target the GTK version on the branch you need. Skip it if the parts of the API your application uses are among the missing or unstable ones, since the project itself asks you to open an issue when you hit them, or if your distribution model cannot live with the Mozilla Public License on pkg/. Before you build against it, check which branch matches your system GTK, read UPDATING.md when you move between releases, and confirm that the specific GTK classes you need are present in pkg/gtk/v4 rather than assuming coverage from the existence of the package.

## FAQ

### What is gotk4 and how is it structured?

gotk4 is a GTK4 bindings generator for Go. The generation code lives in gir/girgen/, and all the generated packages are in pkg/, with GIR documentation linked from the project.

### Which GTK version does a gotk4 branch target?

The branch named 4 targets GTK 4.14 and the branch named 4.16 targets GTK 4.16, with 4 as the default branch. A binary built against one branch expects the matching GTK runtime.

### Is gotk4 stable enough for a desktop application?

The README says most of pkg/gtk/v4 and pkg/gtk/v3 are ready to use for most purposes, but that memory leaks and sometimes crashes may occur in certain parts of the API and that other parts might be completely missing, in which case an issue should be opened.

### What licence applies to the gotk4 packages?

The repository carries three licences: gir is under the AGPL v3, which does not apply to the code it generates, pkg is under the Mozilla Public License v2, and pkg/cairo is under the MIT licence. The README also credits snippets from tinyzimmer's go-glib for type subclassing.

## Sources

- [diamondburned/gotk4 on GitHub](https://github.com/diamondburned/gotk4)
- [Issues](https://github.com/diamondburned/gotk4/issues)
- [License: AGPL-3.0](https://github.com/diamondburned/gotk4/blob/4/LICENSE)
- [README](https://github.com/diamondburned/gotk4/blob/4/README.md)
- [Releases](https://github.com/diamondburned/gotk4/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/diamondburned-gotk4
