Go Modules

Ritwik MathRitwik Math
5 min read

Go modules are the building blocks of modern Go projects. Go modules were introduced in Go version 1.11 in 2018. Before that, all projects were managed using GOPATH. Managing different versions of the same dependency for various projects was hard. Go modules were introduced to work as a dependency manager and a version manager for Go projects. Go modules provide the following benefits over the legacy approach

  1. A developer can declare a project anywhere. There is no restriction on creating the project in GOPATH anymore.

  2. Your project will use the exact version of the dependencies anywhere you want.

  3. Use of multiple versions of dependencies in various projects on a local machine.

  4. Managing dependencies using go get and go mod tidy has become very easy.

Initialize Go Module

It is the first step before you create a new Go project. Go provides a lot of commands for managing Go Modules. There is one to initialize the Go module as well. Make sure you are in the root directory of your project.

go mod init github.com/ritwikmath/dummyproject

To initialize a Go module, you will need to provide a module name. This name has to be unique in the context of what you want to do with it. If you want to deploy the module in GitHub, give a module name similar to the above example. Make sure the project name is unique to your GitHub repositories.

If you want to use the module locally only, you can give any name that is unique to your local machine.

# This is a valid name for local use
go mod init example.com/dummyproject

# This is also a valid name for local use
go mod init dummyproject

After initializing the Go module, you will see a new file go.mod in your project root directory. This file contains two main information for now, the name of the module and the Go version.

Other than these two information, GO uses the go.mod file to track direct or indirect dependencies, and their version.

Mod and Sum Files

Go provides the go get command to add dependencies to your project. Let’s add Gorilla Mux dependency to your project.

go get github.com/gorilla/mux

After successfully running this command, you will see a new file, go.sum, in your project root directory.

The purpose of the go.sum file is to maintain cryptographic checksums or hashes of the exact version of dependencies your module uses. These hashes are the content of the dependencies and their go.mod file. It ensures code security and integrity. Whenever, project is initialized, Go will make sure the same version and content is downloaded that has been used by you. It prevents malicious code downloads. go.sum follows a specific pattern to store the information of dependencies.

module_path version HASH
module_path version/go.mod HASH

If you take the example of Gorilla Mux, the go.sum file stores the dependency in the same format.

github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=

github.com/gorilla/mux is the module path. v1.8.1 is the version. h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= is the hash of all contents of this module.

The go get command updates the go.mod file too. Go primarily uses the go.mod file to track its direct and indirect dependencies. So, it is mandatory to put the Gorilla Mux module information in the mod file as well. The command updates the mod file.

module github.com/ritwikmath/learnmodules

go 1.22.5

require github.com/gorilla/mux v1.8.1

You must add both the mod and sum files to your git repo.

Mod Tidy

The go mod tidy command is used to sync go.mod and go.sum files with imports in your project code. It can both add and remove dependencies to and from your project module. Tidy command goes through all your .go files and matches dependencies with mod and sum files. If any unnecessary dependency exists, it will be removed from the module. Similarly, if an import exists but the dependency is not added, tidy will update the mod and sum files to add the dependency. The command is fairly simple,

go mod tidy

Run this command in your root directory.

Let’s see an example,

package main

import (
    "encoding/json"
    "fmt"
    "net/http"

    "github.com/go-playground/validator"
    "github.com/gorilla/mux"
)

type Payload struct {
    Name string `json:"name" validate:"required"`
}

func main() {
    router := mux.NewRouter()
    validate := validator.New()
    var data Payload

    router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        err := json.NewDecoder(r.Body).Decode(&data)
        if err != nil {
            http.Error(w, "Invalid JSON", http.StatusBadRequest)
            return
        }
        if err := validate.Struct(data); err != nil {
            errors := err.(validator.ValidationErrors)
            http.Error(w, fmt.Sprintf("Validation error: %s", errors), http.StatusBadRequest)
            return
        }
        w.WriteHeader(http.StatusOK)
        fmt.Fprintf(w, "Processed successfully")
    }).Methods("POST")

    http.ListenAndServe("localhost:8080", router)
}

Put the above code in the main.go file located in your root directory. You have already imported the Gorilla Mux using the go get command. You can verify by looking into the go.mod and go.sum files. But the github.com/go-playground/validator package is missing from your module files. Run go mod tidy in your project root directory. The command will update the mod and sum files to add the github.com/go-playground/validator dependency to your project.

module github.com/ritwikmath/learnmodules

go 1.22.5

require (
    github.com/go-playground/validator v9.31.0+incompatible
    github.com/gorilla/mux v1.8.1
)

require (
    github.com/go-playground/locales v0.14.1 // indirect
    github.com/go-playground/universal-translator v0.18.1 // indirect
    github.com/leodido/go-urn v1.4.0 // indirect
    gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
)

Run the server

go run main.go

Now test the endpoint with inputs to check that validation is working.

Initialize a Cloned Project

Let’s clone a project and initialize it.

Project: Simple Website using Gin

Clone URL: https://github.com/eddycjy/go-gin-example

git clone https://github.com/eddycjy/go-gin-example.git

cd go-gin-example

Now there are two options: either use the download or tidy command. Open a terminal, and the present working directory should be the root of the project.

# Preferred go mod tidy
go mod tidy
0
Subscribe to my newsletter

Read articles from Ritwik Math directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Ritwik Math
Ritwik Math

As a seasoned senior web developer with a wealth of experience in Python, Javascript, web development, MySQL, MongoDB, and React, I am passionate about crafting exceptional digital experiences that delight users and drive business success.