Packages in Go

Package in Go language is nothing but a directory with some code files. They are used to organize Go source code for better reusability and readability. Packages help in making code organized which in turn makes the code more modular and easier to maintain.

In the previous tutorial, we have seen one Go source code example, mainly with the main package and all the source code inside that main package file only. While this approach gets the job done in small cases, it is not very suitable for large use cases. In real-world scenarios, the approach of writing all source code in a single file is not scalable and is also not recommended. The reusability and code maintenance is very difficult in this approach. This is where the packages come into the picture.

Let's consider an example of a bank application used to calculate the loans in Go language. As calculating loans includes different steps, one such step is calculating the interest. There might be different interest types that we may want to calculate, like, compound interest, simple interest, etc. We can make different modules(packages) for calculating different interest type and then if we want to calculate the compound interest we can simply import the package and use it. This approach of making packages for different functionalities helps in the case where we want to make changes to a certain section of code, we can easily do that, without affecting other parts of the application.

In simple words, its like dividing a home into different rooms, where each room is meant to serve a different purpose, and each room has different furniture. If we want to use anything in any room, we can just go to that room. But imagine the hall house as one big hall without walls. It would be weird, right!

Types of Packages in Go

There are mainly two types of Packages that exist in Go. These are:

  • Executable Packages: The packages that will result in a binary executable.

  • Utility Packages: These packages are not executable and are mainly used to enhance the functionality of an executable package. This can have functions used in the executable packages.

Syntax for Go Packages:

The syntax that defines a package in a Go lanaguage looks something like this:

package <packagename>

The above package declaration done using the package keyword must be the first line in every go program. There are different cases in which a <packagename> is decided, we will look at each of them.

main package in Go Language

The main package is used to denote the entry point of the application. Every executable Go application must contain the main function inside the main package. This main function is called the entry point of the application.

Now let's create a main package with the main function and try to build the executable of the package so that we can run it later.

First, let's create a directory inside the GOPATH of our machine. Inside the GOPATH/src directory, let's create a folder named app.

mkdir app

The directory app that we just created will contain our main package, let's move inside the directory and create a simple Go file named main.go

cd app
touch app.go

Note: The touch command works only for Linux(Create a file in Linux), in windows you can use fsutil command.

Now, open the main.go file inside the editor and write the following Go code.

package main

import "fmt"

func main(){
    fmt.Println("Inside the main function")
}

Now we have a main package in our Go file with the main function inside it. To convert this file into an executable, we just need to run the following command into the terminal.

NOTE: In the code above, fmt is a standard Go language package which has the Println() function used for printing any output.

Go to the GOPATH/src directory, and run the below command:

go install app

The above command is used when we want to build an executable file for the main package. The output of the above file will result in creation of a binary executable inside the bin directory of the GOPATH.

Now, run the following commands into the terminal and you will see the output.

cd bin/
./app


Inside the main function

The go install <packagename> command that we used earlier looks for any go file with main package declaration inside the given package. If it finds the main package then it knows that the Go code needs to be converted into an executable and so it does. In case, it doesn't find the main package, it will create a package archive(.a) file inside the pkg directory.

Now, change your Go code that you had before. Just write package app instead of package main.

package app

import "fmt"

func main(){
    fmt.Println("Inside the main function")
}

Now, if we run the go install command from the src/ directory again, we won't get an executable instead we will get a package archive(.a) file inside the pkg/ directory. We cannot execute this .a file like we could a normal binary executable.

Package naming convention

The naming convention for packages in Go is quite simple, just avoid using under_score, hy-pens or mixedCaps. Some of the package names of the Go standard library are:

  • net/http

  • fmt

  • strconv

  • time

  • reflect

Creating a Package

We know that there are two types of packages in Go. We learned how to create an executable with an executable package above. Now let's create a utility package and learn few simple ways of using it.

Inside the GOPATH/src directory create a folder named sample, and inside that folder create a utility package file named hello.go

mkdir sample
cd sample/
touch hello.go

Now, open the hello.go file and write the below-mentioned code in it:

package sample

var name string = "StudyTonight"

In the above code, the package is a utility one so we cannot create an executable of it, neither can we run it as a stand-alone program. Though, what we can do is, use this package code inside the app/ directory which contains the executable code.

Importing a Package

We can use a package and its code inside another package by importing the package using the import statement. We will use this in all the examples below.

What are Exported variables in Go Packages?

We can export variables from one package to another.

Let's consider the sample package again if we look at the hello.go file inside the sample/ folder, this is what our code looks like:

package sample

var name string = "StudyTonight"

It contains a name variable that holds the string value "Studytonight". The variable is not exported and Go language will tell this to us when we try to import the sample package inside our app/ directory and try to use the name variable.

Now open the app/app.go file and change the package name again to package main, and make the below changes as well.

package main

import (
    "fmt"
    "sample"
)

func main(){
    fmt.Println(sample.name)
    fmt.Println("Inside the main function")
}

It should be noted that we imported the package sample using the import statement and we are also trying to access the name variable of the hello.go file of package sample inside our app.go file. If we run the above code, by using the go run app.go command, we will encounter an error.


# command-line-arguments
./app.go:9:14: cannot refer to unexported name sample.name
./app.go:9:14: undefined: sample.name

The error is quite easy to understand, it says that the variable we are trying to use is not exported and hence we aren't allowed to use the same.

To make any variable or functions available in different packages we simply need to capitalize the name of them. If we change the name of the variable name to Name inside our hello.go file of sample package we will be able to use it inside the app.go file of package main.

The hello.go file of the package sample will look like this:

package sample

var Name string = "StudyTonight"

Now if we make use of the Name variable again inside our app.go file of package main, it should work.

The app.go containing the package main:

package main

import (
    "fmt"
    "sample"
)

func main(){
    fmt.Println(sample.Name)
    fmt.Println("Inside the main function")
}


StudyTonight
Inside the main function

Nested Packages

There are cases where we might have nested packages. A nested package is a package inside a package.

In the above example, we had a package named sample and inside that package, we had a hello.go file. Now let's create another package inside the sample package to make a nested package.

Run the below commands inside the sample package directory:

mkdir sm
cd sm/
touch hello.go

The directory structure of the sample/ folder will look something like this now:

sample/
---- hello.go
---- sm/
---------hello.go

Now, let's write some code inside the hello.go file of the newly made sm package. The hello.go file should look like this:

package sm

import "fmt"

func CalculateSum(a,b int) {
    fmt.Println("sum is:", a + b)
}

In the above hello.go file, we are exporting a function name CalculateSum() which we will make use of inside the app.go file of package main.

NOTE: As the name of the function starts with a capital letter, so its an exported function.

Let's import the newly made sm package in our app.go file. Now, our app.go file should look something like this.

package main

import (
    "fmt"
    "sample"
    "sample/sm"
)

func main(){
    sm.CalculateSum(2,3)
    fmt.Println(sample.Name)
    fmt.Println("Inside the main function")
}

Please note how we imported the sm package, by specifying it as sample/sm.

Another point to be noted is that when we have nested packages the name of the package that we make use of to call a function is the last package in the nested packages. Like we can see in the example above, the first line inside the main function - sm.CalculateSum().


sum is: 5
StudyTonight
Inside the main function

Package aliases

It is also possible to use aliases names instead of using the name of the package that we are importing into our code.

Consider the example shown below:

package main

import (
    "fmt"
    "sample"
    sum "sample/sm"
)

func main(){
    sum.CalculateSum(2,3)
    fmt.Println(sample.Name)
    fmt.Println("Inside the main function")
}

The above is the same app.go file of package main. The only change is that we used an alias name sum in place of the package name that we imported. Later inside the main function, we made use of the alias name to invoke the CalculateSum() function.


sum is: 5
StudyTonight
Inside the main function

Conclusion

In this article we learned about what packages are in Go, how many different types of packages are present in Go, followed by how to create a package in Go, then, we learned how to import a package, then we learned how Exported members of a package work in Go, following that we saw an example of a Nested Package in Go, and lastly, we saw how package aliases work in Go.