Write self-sufficient, agnostic packages

Whenever I approach the task of setting up the barebones of a web server, I ensure separation of concerns to the highest degree possible. I always have multiple small packages that are created for a purpose, and they contain all logic related to that purpose encapsulated within themselves.

Here’s a great tutorial to help you setup a basic golang web server well, and write unit tests for the same.

A package, for me, typically includes -

Data types relevant only to that package, if any. This includes structs I would like to create to handle mutex locks on particular local resources.

2. Interface(s) to define behaviour, and functions for logic execution, most likely called on the data structs mentioned. Feel free to follow design patterns such as the Builder Pattern to help you lay out the basics in terms of data types and interfaces.

3. Functions that implement the core logic (obviously). Expose selectively the functionality that will allow others to use this package’s features.

One of the functions is often the package’s init() function, that does basic setup necessary for the package to perform its chores. Setup default values, refresh tokens, launch background go-routines, etc. Works great with the Singleton Pattern for doing one time tasks.

Package structure for a project I‘m working on.

Let’s take the given project structure for example. It belongs to a REST service I’m currently writing. The main.go file (not shown in image) is the start of execution and imports the server from service package.

As you can see, each concern is separated into a package — rethink for connecting/reading/writing from a rethink database, auth for performing all authentication and jwt token based logic, a config package for reading/manipulating your configurable files, and so on.

Each of these packages can now be tested independently. Note the service_test.go file in the service package. You can have a test file for each package to ensure thorough unit testing.

Bottom line, always try to ensure that nobody in your service is doing something they’re not meant to do, or that they’re having to repeatedly do across multiple places.