Understanding packages in Golang

Nikasulo
Geek Culture
Published in
5 min readAug 1, 2021

The fundamentals

Whether you’re an experienced Golang developer or you’re just starting out with Golang, you’ve probably heard the words package and module thrown around a lot or you’ve at least come across them in some reading material.

Initially, I struggled with these two concepts, not with regards to what their definitions are but what they mean for the ecosystem you’ll find yourself working in while building/writing programs in Golang.

In this piece, we will talk a little bit about what a package is and a few important concepts around packages.

Packages

A package is a file or a group of files with a namespace and some code or related code. This means that a package could live in a file such as math.go or across multiple files such as add.go , subctract.go , multiply.go , this would many files or the singular file will be namespaced as package math for example.

A package will have a surrounding directory like so:

The math package with both styles we spoke about above

The content of math.go may look something like:

Having all the code for our math package in one file

If we decided to split this math package into multiple files, we can make three files add.go , subctract.go , multiply.go , with the following content

add.go from the math package
subtract.go from the math package
multiply.go from the math package

Looking at all three resulting files, you may have already noticed the common denominator — they all share the same package namespace math . Of course, you’ll likely never find anyone doing something like this, unless they are splitting very large files into multiple files. It is essential to understand this concept of the shared namespace for what we will discuss next 👌

Exported and Local functions/methods

The idea behind writing packages in Golang is to create modularized pieces of code that can be shared across your projects or with other developers for use in their own projects, way to go Golang! I love your generous nature 💌.

Now for this to happen, and for it to happen securely, we may want to expose some parts of our code as external APIs to be consumed further down the line as well as keeping some aspects of the package more hidden and not so accessible. Some languages provide constructs like public , private , protected to help with this, but in Golang, the concepts of public and private APIs are implied from the way we name our functions, methods, and properties. Let’s look at an example 👇🏽

Illustrating exported and local functions

Looking at the illustration above, we have two functions, named identically, with one difference, one is lowercased multiply and the other starts with a capital letter Multiply , this subtle difference is the distinction between a local and an exported function in Golang. You can go ahead and guess which is which 😂 you may get it right from the way they are structured but nonetheless, in Golang, when you name something in full lowercase, it is localized and cannot be accessed outside of this package(remember what a package is? Take another look? 😉 ). On the other hand, anything that starts with a capital letter can be accessed from within and outside of the package where it was defined/declared.

So if we published our package today(we will look at publishing packages shortly 👌), we can import this math package and access Multiply , but attempting to access multiply will definitely throw an error! 👇🏽

Trying to access an exported and an unexported Function from the math package

Whereas, we can access multiply under the same name space, even in another file! 👇🏽

These concepts can be the difference between some beautifully and creatively structure Go code and some messy programs. One thing to note here is that math here was used as an illustrative package name, DO NOT USE THIS in any real or playground applications, as Golang already has a built-in math package, and this will for sure lead to some unintended behavior (you can try it out if you are curious 😉).

In Summary

  • A package can be thought of as a file that is namespaced(at the top) containing some related code
  • It can also be a bunch of files with the same package namespace, containing related code
  • Don’t prematurely split packages into multiple files unless extremely necessary, e.g. file is becoming unmanageable, or you have some dynamically generated code at run time(we will discuss code generation shortly 😉), etc. Also, even if you split packages into different files, they must live in the same directory or you will mess up your imports down the line.
  • In Golang, the concepts of private and public functions, methods, and types are implied based on how you name the constructs. If you start with a capital letter, packages outside of the current one can access them, if you lowercase them, they become “private” and inaccessible/untouchable from outside the current package.

That’s it! Go, go, go 🏃‍♂️ you learned a little Golang today 🎉, thank you so much for following along! In my next article, we will go over modules and how they tie in with the concepts of packages, see you soon 👋

--

--

Nikasulo
Geek Culture

I build for the web. I teach people to build for the web. You can follow me closely here https://twitter.com/nervousrubyist, ask me questions about code 😉