My story of publishing a Go package
Tags: go, package, documentation
Published: 2020-05-09 23:46:34

I recently transferred to a new team at work and the tech stack was Golang. Python has been my language of choice for the past 5 years and so the thought making a change to Go, made me apprehensive. I was no stranger to the language. I had been learning different aspects of the language in the past year and also taught a beginners workshop at the Google Dublin office over a weekend in one of the Google Developer Group events.

But all the learning is of no use unless you actually put it into practice. When the rubber meets the road, you really know the extent to which your learning process has prepped you. I had look into adding REST endpoints to an existing web application that was serving mobile clients. There was also a new requirement for adding 3rd party integration. All of these are crucial to the smooth working of the application. So having automated tests are key to reliably shipping code.

So I started on the path of writing unit tests and learnt quite a bit in the process. Mitchell Hashimoto has an excellent talk about advanced testing in Go which I highly recommend to write scalable and easy to extend tests. I did adopt some of the recommendations and found it to be easy to follow. There was also the case of having the same set of boilerplate code repeated in multiple places which brings up the case of using packages to abstract repeated functionality.

I wrote a set of helper functions for encapsulating common operations that I came across in tests but thought I should extend it further and deploy it as a package so that I can get some feedback from the community as well. So started on the journey of publishing a package over the weekend and expected the process to be hard based on what I heard in the past from package publishers in other languages.

Published Go packages can be searched for in `pkg.go.dev` and is a good way to get yourself recognised. The initial step is to create a Github repository preferably with the prefix `go-` which is a convention. Next is to create a package hierarchy that you deem fit and start writing your code along with tests. In my case, the package was about creating unit test helpers. So I created a single package and added the helper functions I had in mind to different files under the same package.

Once I was done with coding and tests, the next step was to add documentation so that others can read and adopt my code. I started with the default comments for functions to add some context and then added a `doc.go` for package level documentation. Running `godoc` is a good way to make sure that your package documentation will render correctly when accessed by others. I had `godoc` running while I was adding documentation to that I can keep watching on the fly for changes.

I wanted to add code examples for the different functions that I created, in a way that it would be part of the documentation rather than forcing users to read through tests and figure it out themselves. Fortunately the Go authors already thought of this and it is built into `godoc`. In your test files (`*_test.go`) add functions that start with `Example` and do not take any arguments. For a function, it would be named `ExampleFunc`, for a function with a struct receiver it would be `ExampleStructName_Func`. In the function body, add the code snippet and finish off with `// Output:` followed by the expected output in one or more lines. When you trigger `go test ./...`, the test tool will run the example functions and then compare the output with the output mentioned in the comments. If it doesn't match, then an error will be shown in the documentation as well as in the console. I found this process of self-documenting tests very interesting and sped through all the example test functions.

I recommend using a separate package name for your tests `package abc_test` where `abc` is the intended package. This is to make sure that your tests are not accessing any private information and to replicate what users of your package will actually see.

Last step is tagging. Make all your changes available on the `master` branch and then create a release tag following semantic versioning. This will make sure that the correct versions are pulled down by Go when there are new releases.

And that is all it takes to publish your Go package. Here is my first package : https://pkg.go.dev/github.com/allentv/go-testhelpers@v0.1.1/unithelpers