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.