In this tutorial, we will look into the concept of packages in Golang with the help of detailed examples. A very important principle of programming is the DRY (Don’t Repeat Yourself) principle. This principle involves not repeating the same piece of code over multiple parts of a program, instead reusing the same code over time for similar purposes. Every programming language provides features that allow you to reuse code. Go provides features like functions, methods and packages to allow you to utilize reusable codes in different parts of your program. In this article, we will learn about importing, using and creating packages.
In order to follow through this article:-
- You need to have a basic understanding of programming.
- You need to download the Go compiler from the official website and follow the directions to install it based on your operating system being either Windows, MacOS or any of the Linux distributions.
- You need a code editor like visual studio, atom or sublime text. Alternatively, you can download an Integrated Development Environment (IDE). An IDE is an improved code editor with added qualities customized to help you write and execute codes easier. Goland is the most popular IDE used for developing Go programs.
- You need to have an understanding of Go data types, functions and methods.
A Complete Guide to Packages in Go [Explained with examples]
Also Read: Concurrency using Goroutines and Channels - Explained with examples
A package is basically a set of source files in a single directory. Packages provide a way for you to import and use types, functions and methods from some other source code. Every Go source code must belong to a particular package, which is declared on the first line of code using the format :-
A very popular package declaration is package main, which describes the main entrance for an executable source code. A main() function always accompanies a main package as a directive to the beginning of execution in an executable source code.
Ubuntu 20.04Linux environment.
From the snippet above, we declared the source file to belong to the package main on the first line of the code. Then we imported a package using import “fmt”, and finally used the package on line 8 by prefixing the function with the package name and a dot. This is the typical way we create, import and use packages in Go. The fmt package is a package in the standard library used for formatting data for input or output.
Importing Packages in Go
From the example above, we imported a package fmt using the import statement. We can import multiple packages in two ways:-
- By using multiple import statements.
- By using a single import statement.
After importing a package as seen above, we must use the package within the program, else the compiler will throw an error. But we can import packages without using them by prefixing the package with the blank identifier ( _ ) . A popular application of using blank identifiers is when writing a program to communicate with a SQL database. After importing the standard database/sql package, you will need to use the blank identifier to import a sql driver that corresponds to the database you will be using.
We can also import packages using a dot identifier ( . ). If you are familiar with C++, using the dot identifier is similar to the expression “using namespace std”. The dot identifier allows you to use packages without referring to the package name on each use. For example, if we import the fmt package using a dot identifier, when calling fmt.Println(), we would omit fmt so that the function can be called with only the function name Println.
It is not advised to use the dot identifier in programs involving multiple packages because different packages may have similar function or type names. For example, the strings and bytes packages both possess a function named Contains(). Therefore importing both packages with a dot identifier will cause Contains() to be available for only the first of the two packages to be imported. Using the dot identifier also reduces code readability.
Using Packages in Go
When creating software in Go, we can use three types of packages:-
- Packages from the standard library
- Third party packages
- Personal packages
Using packages from the standard library
Most of the examples above involve using packages from the standard library. We typically use functions or types within a package by importing it and prefixing each use of the statement with the package name.
All packages from the Go standard library can be found on the Go official website at https://pkg.go.dev/std. We can click on each package to see its documentation explaining the packaging and showing its functions, types, methods and interfaces. Most package documentation contains examples of how to import and use its components.
From the standard library, some packages contain subpackages. For example, the math package contains subpackages bits, big, cmplx and rand. We can import each of these packages using the parent-package forward slash (/) sub-package (math/big, math/cmplx, math/rand and math/bit). Some other packages are also imported using two words separated by a forward slash, but are not sub-packages. For example, database/sql which we used above is not a subpackage because database is not a package that can be imported.
We use subpackages by prefixing a function or type with the last word after the forward slash. Let’s see some examples of using subpackages.
The program above generates a random number between 0 to 10. Within the init() function, we used a function from the math/rand package named Seed(), and within main(), we also used a function Int63n() from math/rand to generate a random number less than 10. Notice that on each function call from, we prefixed the function name with rand. The same principle applies when using types or interfaces from a package.
From the standard library, some subpackages may have the same name. For example, crypto/rand and math/rand can both be referred to with the same name within a program. In a case where both packages are imported in the same source file, we can use an alias to rename one of the packages. This way we can refer to functions within that package with an alias, instead of the default name.
In the program above, we defined an alias (random) to refer to the package crypto/rand to prevent a conflict since it has the same default name as math/rand. Using an alias for importing packages is very popular when writing large programs in Go. A package alias can also be used for convenience when importing third party packages with ambiguous names.
Using Third Party Packages
Third party packages are basically packages that other Go developers have written, and hosted on a server for every Go developer to use. There are a lot of packages developed by the Go community to assist other Go developers. Most third party packages contain documentation to show how to use the packages within your code. A popular third party package used by most developers is the testify package which contains a set of subpackages for simplifying tests.
To use a third party package, you will need to initialize a Go module within your project directory. A module is Go’s tool for managing external dependencies. Let’s work through the process of setting up a Go module and importing the external package.
a) Create a new directory named packages.
b) Change into the packages and run go mod init packages in your terminal. The result should be as seen in the second line below. This command initializes a go module in your project directory. You should now see a go.mod file within your project directory.
Your go.mod file should contain the following :-
c) Create a new file main.go in your project directory and declare it’s package as main.
d) Run go get -u github.com/stretchr/testify to import the third party package into your Go module. You should get the following result below.
Your project directory should now contain a go.sum file, and your go.mod file should contain the following:-
Your project structure should be in the form:-
We are now able to use one of the subpackages from testify within main.go by importing it and using one of its functions as shown below.
Note that the program above is just an example of using a third party package. It is not necessarily the way the third party package (testify in this case) should be used.
Creating Packages in Go
When creating fairly large software, you may need to create a personal package to group related functions together. You can create an infinite number of packages within your project directory by creating different folders, and grouping similar files within them. Let’s work through the process of creating your own package.
a) Create a new directory named personal.
b) Change into the personal and run go mod init personal in your terminal to initialize a Go module.
Your go.mod file should contain the following:-
c) Create a new file main.go in your project directory and declare it’s package as main.
d) Create a new directory math in personal.
e) Change into math and create a new file math.go. Write the following code into math.go.
In the snippet above, we declared math.go to belong to the package math. Then we defined four math functions. Note that each of the functions is exported because their identifiers start with an uppercase letter. We can also declare functions or types that are unexported by beginning its identifier with a lowercase letter; in which case, we won’t be able to call them from other packages.
f) Change directory back into personal and write the following code into main.go.
On line 5 above, we imported the package we just created by using the format module_name/package_name (personal/math). We then called each function defined in math on lines 11, 12, 13 and 14. This is a typical application of creating a personal package within your project to group similar functions together and abide by the DRY principle.
Ability to use and manage packages is very essential to help you write more readable, reusable and maintainable software's. The Go community is very large, and a lot of developers help to build third party packages to help you write more modular and efficient programs. You can also write useful packages and document them to improve the Go community.