Now that I’ve been writing Golang for a while, when I start a new project, I typically know the sort of layout I’m looking for.

I typically go for something like this:

.
├── cmd
│  └── demo
│     └── main.go
├── go.mod
├── internal
│  └── subpkg
│     ├── subpkg.go
│     └── subpkg_test.go
└── LICENSE

And often there are lots of ascillary files that go along with this, like Makefiles, CI/CD config files, Dockerfiles, docker-compose files, etc.

Re-creating this sort of structure (with all the files) is annoying when starting a new project. In the past, I’ve solved this problem typically one of two ways:

  1. cp -R old_project new_project and then start rm -rf-ing things I don’t need.
  2. Create a repo dedicated to holding a blank project and then cp -R it when I’m ready. This like like option 1 but only contains the bare minimum of what I need.

Option 1 isn’t great because it’s easy to miss files when I’m cleaning it up. It’s also easy to clone the wrong project and get subtle drift between your repos.

Option 2 is much better; it suffers from less drift and as I improve my project layout I can commit those changes back the the master repo. But copying the project and cleaning it up is still annoying and it raises the barrier of entry for sharing a project with others. (For example, you have to remove .git/ and edit the go.mod file to have the right module name and correct Go version.)

I learned yesterday that Go has a tool named gonew for making these sorts of master project repos useful and making them easier to share. It takes much of the tedium out of this process and is super easy to use.

I made a demo project here: https://github.com/jamessimas/gonew-demo All you do is make a repo with the desired layout and files you want. That’s it. 🎉

Using it is as simple as:

$ gonew github.com/jamessimas/gonew-demo example.com/demo-test
gonew: initialized example.com/demo-test in ./demo-test
$ ls demo-test/
cmd  go.mod  internal  LICENSE

It’s nice that the barrier is entry for this is so low and it leverages a pattern (template repos) other devs are probably already using.