Go Modules Part 1: Introduction
The Go modules is a new dependency management system that makes managing dependency much more easier. This block post is the first part of a series about modules in Go in which I will present you what are modules in Go, developing and publishing modules, managing dependencies, modules release, and versioning workflow.
What are Go modules
Creating a new module
Let’s create a new module from scratch. Create a directory “greeting” and inside it create a “cmd”:
mkdir greeting
cd greeting
mkdir cmd
cd cmd
Then inside the cmd directory create a new file “main.go”
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello!")
}
Now the directory “greeting” contains a package “cmd”, but not a module because we don’t have a “go.mod” file. Let’s create it. Execute this command from the directory “greeting”
$ go mod init greeting.com/hello
go: creating new go.mod: module greeting.com/hello
Done! You have a new module. The command above creates a file “go.mod” in the “greeting” directly:
$ cat go.mod
module greeting.com/hello
go 1.19
Now if you create a new directory “api” it will automatically be recognized as part of the “greeting.com/hello” module. If you want to use the code from your “api” folder you can import it by typing the name of the module “greeting.com/hello ” + the name of the package “api” => import “greeting.com/hello/api”. Let’s see an example. Create a new directory “api” in the root directory “greeting”
mkdir api
cd api
Then create a new file “http_handler.go” with the following content:
package api
import "net/http"
func HandleGreetingRequest() http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("Hello!\n"))
}
}
Now we will import this package in the “cmd” package. Update the code in the “main.go” file that we created early:
package main
import (
"net/http"
"greeting.com/hello/api"
)
func main() {
http.HandleFunc("/greeting", api.HandleGreetingRequest())
http.ListenAndServe(":8080", nil)
}
Note how we import the “api” package (“greeting.com/hello/api”). The package “api” is part of the module “greeting.com/hello” and for that reason, the import path looks like that. Now we can run the server by executing this command from the “cmd” directory:
$ go run main.go
Open a new terminal and send a request to the server:
$ curl -X GET http://localhost:8080/greeting
Hello!
The server return “Hello!”.
Adding a dependency
We created a module, and we have a simple HTTP server program, but we still don’t have external dependencies. Let’s add some new dependencies and see how the Go module will help us with the management of this dependency. Update the “main.go” file:
package main
import (
"net/http"
"github.com/gorilla/mux"
"greeting.com/hello/api"
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/greeting", api.HandleGreetingRequest())
http.ListenAndServe(":8080", r)
}
Here we added an external dependency (github.com/gorilla/mux). Gorilla is a web toolkit for the Go programming language that provides useful, composable packages for writing HTTP-based applications.
Now your code doesn’t compile but doesn’t worry this is normal. Execute the following command:
$ go get github.com/gorilla/mux
go: added github.com/gorilla/mux v1.8.0
“go get” command is the standard way of downloading and installing packages and related dependencies. It automatically gets the latest stable version (in our case v1.8.0). Now if you see the go.mod file it will contain this dependency:
module greeting.com/hello
go 1.19
require github.com/gorilla/mux v1.8.0
Let’s run the program again to be sure that we don’t break something:
go run main.go (don't forget to stop the previous running server, before running this command)
$ curl -X GET http://localhost:8080/greeting
Hello!
Congratulations! You have created your first module.
Conclusion
The Go modules are very useful and easy to use. They make it easier for developers to maintain various dependencies of their projects. In the next part, of the series for go modules, you will see how to release, versioning, and publish your module.