Organize your code with Go packages — Master Tricks

Let’s learn the master tricks about how to properly design your system with Go packages.

Inanc Gumus
Learn Go Programming
5 min readSep 26, 2017

--

Keep your packages small

I found it better to keep my packages small. It allows you to change or reuse your packages better this way.

Let them solve the specific problems and do not put a strain on them to solve many things at once.

Follow the exact same Unix philosophy when creating your packages. Smaller things to build bigger things.

Put related packages into sub-directories

Go Standard Library uses this style. Look at http package for example. It’s in the net package. Http things belong to network things, so, they put it under the net package. However, that doesn’t mean that http package can use net package’s internals, it cannot.

Each go package is a different beast on its own, so there’s no relationship between net and http package in stdlib other than the organization purposes.

Create your packages as related clusters

Try to depend on things from the same group of packages instead of reaching to the outer group of packages.

Try hard to group your packages into smaller units of related groups.

Hide almost everything

Expose only the things that you want to be re-used by the external packages and try to hide all the things which are internal to the package.

In my own projects, all the private code that is specific to my projects lives inside internal directories. Internal directories allows me to hide my package’s internals only to a sub-group of packages. I create a cmd folder to keep entry-point commands of my application, then I do dependency-injection and other orchestration code there.

Depend on things that don’t change often

When importing packages try to depend on packages that don’t change often to solidify your code-base.

When importing packages, use your own code as a library inside your executable commands.

Assume that your code is a library and design its API as reliable as you can.

Go has no sub-packages

When you want to split your packages to organize your BIG package, you may make some of the internals of your package visible to the outside world, and so, anyone can import them. You may not want this.

Internal package convention prevents your packages to be imported from unwanted parties. I explain internal packages here in this post.

Put tests into the same directory

Do not put your testing code into separate test directories.

Keep them together like: miner.go and miner_test.go into the same directory, they live happily there together.

Put the data needed for testing into testdata directories as a sub-directory. Go tools will respect that convention.

miner/
miner.go
miner_test.go
testdata/
hashes.data
.

Don’t put your code into ./src folders

New gophers who are beginning to Go, create, src/ folders, you don’t need to do that.

Just put your source files into your project’s root. It’s better that way.

Do not use src folders inside your inner package directories as well.

Put external packages into the vendor folder

I’m using the vendor folders in my own projects to lock in the dependencies, and not saving them into $GOPATH to lock the specific versions to the specific projects.

There is no package versioning and locking in Go

go get always fetches the recent version of a repository’s HEAD from a git repository. However, there are some workarounds.

You can save a package you want manually by cloning it from its repository directly into your program’s vendor directory, so that you can use and lock whatever version you want.

Also, you can use tools like dep, glide, gpm, gopkg.in or other tools. These tools are mostly using semantic versioning to get and lock the package versions.

More tips here.

Don’t export from the main

Main packages are not importable packages and you don’t need to export things from main package. Unless you want to use something like cgo.

Smaller programs may not need many packages

For smalller programs, you probably don’t need to define another package other than the special package: main.

For bigger programs, you might need to define your own packages to organize your code.

For people who work on the same code to create many programs, they may need to define their own libraries and import these to their own programs.

Naming packages

Use simple names

Like: http, zip, and time. You and other people are going to use and recall them with this name. Keep the naming short, simple, concise and to the point.

Do not use double or more words in names

Not like this: net_http. Do it like: net/http. Different packages, but because http package is inside the net directory, if there was another package which was also named as http, there will be no problem, because they live in separate directories.

Let the package path speaks for what the package does

net/http. It’s clear, isn’t? http package is a package that does things related somehow with networking. If it was inside security/http package it’d imply different meanings.

Don’t repeat the package names

Instead of:miner.MinerInfo, use: miner.Info. Or, instead of: weather.WeatherTemperature, use: weather.Temperature.

Use common abbreviations

Only if they’re familiar to the programmers (or to the programmers in the domain of the application you’re building). For example: Instead of formattedIO, stdlib uses fmt.

Avoid generic package names

Not like this: api, models, common, utils, helper etc.

For example: Instead of a model package, define a package that does user things named as user. Or, define another package for a client order as order.

Do not put everything inside a models folder, split them into more smaller packages.

However, this goes to some extent. If your separate packages need some relationship between them, you may cluster them together depending on your goal.

Do not use underscores or camel-casing

Just use lowercase letters.

Note: Names can contain Unicode characters

However, I don’t recommend using this.

More on the naming: Look at here and here.

If you have a different experience about organizing Go packages, please send your comments below.

Alright, that’s all for now. Thank you for reading so far.

Let’s stay in touch:

--

--