Golang: Understand Packages and Modules

Introduction

In this tutorial, we will learn about Golang understand packages and modules. In Golang, packages and modules are really inter related. We use modules for managing the packages. Go module was introduced in Go version 1.11 for better package management that allows dependencies to be located outside of the $GOPATH/src folder. In the upcoming sections, we will understand the usage and implementation of modules and how it manages the packages in your Go code.

 

Golang: Understand Packages and Modules

Golang: Understand Packages and Modules

Also read: Understand Functions in Golang: [7 Best Examples]

Prerequisite

  • Go package installed in Windows
  • Go plugin installed in VS Code
  • Go version must be 1.11 or above

If you have not setup the Go extension in your Windows. You can check out How To Install Go Extension in VS Code: [9 Easy Steps].

Packages

In Golang, packages are collection of go source files that are organized together in a single directory. It is the basic building block of a Go program. Packages are used to encapsulate related codes and  provide a level of organization and modularity to our Go programs.

Create Package

Creating package in Golang is pretty easy and straight forward. We create a go file in a directory. The directory name and the package name must be same.  Let us create a package called ‘mathpackage’ inside the directory ‘mathpackage’. This package will have one function defined called MathCal. This function will return the double of any integer passed to it as input argument. Below is the demonstration.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule\mathpackage> notepad go-package.go
package mathpackage
func  MathCal(a int) int {

  return a * 2
}
In the above code, the very first line is the name of package we are creating preceded by the keyword package. There is only one function defined in this package ‘func MathCal()’. It accept one input argument of type integer and returns the integer value.

 

NOTE:

You can give any name to your go file but package name must be same as directory name inside which you are creating the go file.

 

Use Package

To use any package i.e standard library packages or your own created custom packages, you need to import in your code as shown below.

//Import standard library packages
import "fmt"

//Import custom packages
import "mathpackage"

After importing the packages, you can access their functions by using . operator as shown below.

mathpackage.MathCal()

 

Modules

Modules were introduced in Go 1.11 version to manage dependencies and versioning. A collection of Go source code becomes a module when there is a valid go.mod file in its root directory. In other word, a module is a collection of packages with built-in dependencies and versioning. Modules allow us to specify and manage the external packages that our project relies on.

Create Modules

To create a module in Golang, we will first create a new directory as shown below.

PS C:\Users\linuxnasa\OneDrive\Desktop> mkdir go-project
PS C:\Users\linuxnasa\OneDrive\Desktop> cd .\go-project\

Create a new module directory named mathmodule.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project> mkdir mathmodule
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project> cd .\mathmodule\

Configure and initialize the module using command go mod init <module-name>.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> go mod init mathmodule
go: creating new go.mod: module mathmodule

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> ls
Directory: C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---l 02-09-2023 00:25 29 go.mod

 

A new file go.mod will be created. Open the file and check its content. It contains two lines. First line contains the module name . It tells the Go to search mathmodule in this module only and not anywhere else whenever this module is imported in any Go program. Second line specifies the Go version used in creating the module.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> cat .\go.mod
module mathmodule
go 1.21.0

We will now write a simple Go program and save it as main.go to test our module as shown below.

package main
import "fmt"

func main() {
    fmt.Println("This is math module")
}
Now, there are two ways to execute this program as shown below
  • go run <go-file-name>
  • go build <go-file-name>

When we execute program using first method, it will directly prints the output on console without generating any binary as shown below.

OUTPUT
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> go run main.go
This is mathmodule
When we execute program using the second method, a binary will get generated. Using that binary we can execute the program as shown below.

 

OUTPUT
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> go build .\main.go
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> .\main.exe
This is mathmodule

 

NOTE:

Name of the project directory and the module are usually same.
go.mod file will expand when dependencies get added to the project.

 

Add Package to Module

We will now add a package to our module mathmodule. In Golang, we can add multiple packages to a module. we can also add a package inside another package. Let’s create a new package inside the module mathmodule directory as shown below.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> mkdir mathpackage
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> cd .\mathpackage\

Next, we will create a new file called go-package.go inside the package mathpackage as shown below.

package mathpackage
import (
    "fmt"
)

func MathPackageMessage() {
    fmt.Println("mathpackage is the first package added in the module mathmodule")
}
Next, go back to the module directory and import the package mathpackage in main.go file as shown below.
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule\mathpackage> cd ..
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule\mathpackage> notepad main.go
package main
import (

  "fmt"
  "mathmodule/mathpackage"
)

func main() {

  fmt.Println("This is math module")
  mathpackage.MathPackageMessage()
}
Execute the main.go file as shown below.
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> go run .\main.go
This is math module
mathpackage is the first package added in the module mathmodule

 

Add Remote Module 

We will now look at how remote modules are added as dependencies. We will add a very common Go testing framework called Ginko from github using the command go get <module-path> as shown below.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> go get github.com/onsi/ginkgo
go: downloading github.com/onsi/ginkgo v1.16.5
go: downloading github.com/nxadm/tail v1.4.8
go: downloading golang.org/x/sys v0.0.0-20210112080510-489259a85091
go: downloading gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
go: downloading github.com/fsnotify/fsnotify v1.4.9
go: added github.com/fsnotify/fsnotify v1.4.9
go: added github.com/nxadm/tail v1.4.8
go: added github.com/onsi/ginkgo v1.16.5
go: added golang.org/x/sys v0.0.0-20210112080510-489259a85091
go: added gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7

 

As you see above go get command downloads the latest Ginko version from github as we have not specified any version to download. The moment we add any external module as dependencies, these gets added in the go.mod file. It also creates a new file called go.sum which contains the hashes and versions of all installed dependencies. Check the go.mod file as shown below.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> cat .\go.mod
module mathmodule

go 1.21.0

require (
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
golang.org/x/sys v0.0.0-20210112080510-489259a85091 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
)

 

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> cat .\go.sum
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
..........................................
..........................................
.........................................

 

Remove Dependencies

We can also delete unused dependencies from the go.mod file by executing a simple command as shown below.

PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> go mod tidy
PS C:\Users\linuxnasa\OneDrive\Desktop\go-project\mathmodule> cat .\go.mod
module mathmodule
go 1.21.0

 

As you notice, all the dependencies has been delete from go.mod file. It is because we had installed these dependencies but were not using it anywhere.

Bonus

Below are the some useful and handy go module commands:
go mod why :   used to explain why a particular package or module is needed in your project.
go mod vendor :   used to create a local “vendor” directory containing a copy of all the project’s dependencies.
go mod init :   used to initialize a new Go module in your project.
go mod tidy :   used to remove any dependencies from go.mod file.
go mod verify :   used to verify the checksums of the downloaded module files.
go mod download :   used to download the dependencies specified in your go.mod file.
go mod graph :    used to display a graph of module dependencies.

 

Below is the hierarchy of all the files created for this tutorial.

 

Summary

We learnt about basic concepts of packages and modules in Golang. Packages helps you organize code while modules facilitate dependency management, making Go code more maintainable and sharable.

Leave a Comment