2021 iThome 鐵人賽


"GoDevOps": Learn DevOps Tools with Go系列 第 8

[Golang] Modules

Within a small application, we can just use the main package and functionalities imported from Go’s core library packages. However, The code base could become bigger and more complex as time goes on. We might import massive third party packages from internet. Or, we might want to divide the complicate code base into semantic groups of functionality and unify them into a customized shared package within our project.

At this point, we can use Go Modules to manages these dependencies and the customize packages.

Basic Usage of "go mod" toolchain

go mod init <ModuleName>

This command is used to generated a go.mod file in the current directory, which will be viewed as the root directory of a module called.

$ go mod init brandon/go-example
go: creating new go.mod: module brandon/go-example
go: to add module requirements and sums:
	go mod tidy

go mod tidy

Adds missing and remove unused modules dependencies by analyzing all the source code of the current project. Let's update the main.go to use a third party package as following

package main

import (


func main() {
	fmt.Println(stringutil.Reverse("!selpmaxe oG ,olleH"))

Then we can run go mod tidy to fetch the missing dependencies.

$ go mod tidy
go: finding module for package
go: found in v0.0.0-20210811190340-787a929d5a0d

This command update go.mod with the dependencies and generate 'go.sum' file which maintains the checksum so that when you run the project again
, it will not install all dependencies packages again.

$ cat go.mod
module brandon/go-example

go 1.17

require v0.0.0-20210811190340-787a929d5a0d

$ cat go.sum v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= v0.0.0-20210811190340-787a929d5a0d h1:VYLNvPLNayyBk9XOnsTk5jh7vZarEfiJe7/S15vri2g= v0.0.0-20210811190340-787a929d5a0d/go.mod h1:+yakPl5KR9J+ysfUNADYwEU5qeqjUO473wDktD4xMYw= v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= v0.0.0-20210112183307-1e6ecd4bf1b0/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

go mod vendor

This command making a copy of the third-party packages defined in go.mod and places it inside the /vendor in your root.
There are cases when we want to ensure the robustness of the packages builds without having to rely on external services like github or
To build a package with the dependencies from the vendor directory, you need to specify -mod in the comand, for example go build -mod vendor.

$ go mod vendor
$ ls vendor/	modules.txt

Create Shared Packages Within A Module

Until now, We have only written code in the main package.
Let’s create a project that has customized shared package and see how to imports and use the functions in the shared package.

├── deck/
│   └── cards.go
├── go.mod
└── main.go

First, we implement the shared package deck/cards.go as following:

package deck

func GetStandardDeck() [52]string {
	cards := [52]string{}

	i := 0
	for _, s := range getSuits() {
		for _, r := range getRanks() {
			cards[i] = s + " " + r
			i += 1

	return cards

func getSuits() [4]string {
	return [4]string{"Clubs", "Diamonds", "Hearts", "Spades"}

func getRanks() [13]string {
	return [13]string{"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}

Then we can import the shared pakcage with path <Module_Path>/<package> in main.go file .
In this example, I init this module with command go mod init brandon/poker
so I need to import the deck pakcage with path brandon/poker/deck

package main

import (


func main() {
	a := deck.GetStandardDeck()
	for _, x := range a {

Exported vs Unexported names

Exported name: Anything (variable, type, or function) that starts with a capital letter is exported (public), and accessable outside the package.
Unexported name: Anything that does not start with a capital letter is not exported (private), and is accessable only inside the same package.
When you import a package, you can only access its exported names.

for example, in the main package, we can not call getSuits() and getRanks() functions because they are unexported. Only the exported GetStandardDeck() function can be accessed.

[Golang] Introduction of Functions
[Golang] Custom Type Declarations and Struct
"GoDevOps": Learn DevOps Tools with Go11