Writing your own gofix tools

The Go programming language and tool stack have been designed to combine manual and automated software development in novel ways, paving the path for how software will be written in the 21st century:

Humans will be slow-rolling the creative parts while automated tools (cobots) take over the repetitive parts like upgrades, maintenance, and keeping it all working.

The Go makers have laid out their powerful vision for this in a post on the Go blog a few years ago. They also made a tool called gofix that updates existing Go code bases to new language features of the Go language. This has helped use early versions of Go in meaningfully large code bases while remaining able to evolve the language.

Library and framework authors can (and should) do the same for their users. If your API changes or you introduce new features, spend a few hours creating a fix that can safely update the millions of places where your library is (or will be) called in code bases all over the world. This helps not only your users but also you, the author. By making it easier for everybody in the world to move to the newest version of your library or framework, you can introduce breaking changes easier and at the same time have to provide less support for older versions.

The existing go-fix code base is not a fully generic framework for writing custom fixes, but it is a good start for writing your own fix tool. Here are some pointers for how to go about that using the existing state of the art in Go land:

  1. Copy-and-paste the source code of the gofix tool into your own code base. You only need two files:
    main.go is the "outer framework". It parses CLI arguments, locates source code files or IO streams to convert, parses them into an AST, provides that AST to the inner framework, and serializes the changed AST back into files.
    fix.go is the "inner framework". It allows to walk the AST, modify its nodes, and it provides helper functions for typical modifications.
  2. Look at some of the existing fixes in that code base, for example the printerconfig fix.
  3. The framework you have now allows you to change properties of existing nodes, so if that is all you need you are good to go. Replacing a node with a different one is not supported at this time, however. Fortunately, Robert Griesemer (one of the three inventors of Go), is working on an improved version that provides this ability. It is planned to hopefully become a part of the upcoming Go 1.10 release. Here is an easier to copy version of it. Copy-and-paste it into your code base as well. Now you have an Apply function that allows replacing AST nodes.
  4. Write your custom fixes.
  5. Name your fix tool specific to what it does. The gofix tool fixes Go-specific things. If yours fixes things for your acme library, a suitable name for it would be acmefix.

To see all of this together in a working example, check out the exitfix tool for Originate’s exit library. It also contains tests via examples.

Happy hacking!