Go October 9, 2024 Aditya Rawas

Creating Your First Go Module: A Step-by-Step Tutorial

Go makes it easy to create reusable, versioned modules that can be imported into any Go project. In this guide, you’ll build a Math Utilities module from scratch and consume it from a separate application — all locally, without publishing to a registry.


What You’ll Learn

  1. Create a Go module with reusable functions.
  2. Call that module from another Go project.
  3. Link local modules using the replace directive.
  4. Add random number generation to extend the module.

Step 1: Create the Math Utilities Module

1.1 Create the Module Directory

mkdir mathutils
cd mathutils

1.2 Initialize the Module

go mod init example.com/mathutils

This creates a go.mod file that defines the module’s name and tracks dependencies.

1.3 Write the Math Utilities Code

Create math.go inside the mathutils directory:

package mathutils

// Add returns the sum of two integers.
func Add(a, b int) int {
    return a + b
}

// Multiply returns the product of two integers.
func Multiply(a, b int) int {
    return a * b
}

Step 2: Call Your Module from Another Project

2.1 Create the Caller Directory

Navigate back to your workspace and create the consumer app:

cd ..
mkdir calculator
cd calculator

2.2 Initialize the Caller Module

go mod init example.com/calculator

2.3 Write the Caller Code

Create main.go in the calculator directory:

package main

import (
    "fmt"
    "example.com/mathutils"
)

func main() {
    a, b := 10, 5
    fmt.Printf("Add: %d + %d = %d\n", a, b, mathutils.Add(a, b))
    fmt.Printf("Multiply: %d * %d = %d\n", a, b, mathutils.Multiply(a, b))
}

Since mathutils is on your local machine (not published to pkg.go.dev), you need to tell the calculator module where to find it.

3.1 Add a replace Directive

go mod edit -replace example.com/mathutils=../mathutils

Your go.mod will now contain:

module example.com/calculator

go 1.16

replace example.com/mathutils => ../mathutils

3.2 Sync Dependencies

go mod tidy

After running this, the require entry is added automatically:

module example.com/calculator

go 1.16

replace example.com/mathutils => ../mathutils

require example.com/mathutils v0.0.0-00010101000000-000000000000

Step 4: Run Your Application

go run .

Expected output:

Add: 10 + 5 = 15
Multiply: 10 * 5 = 50

You’ve just built and linked two Go modules.


Step 5: Adding Random Numbers (Optional)

Let’s extend mathutils with a Random function to explore Go’s math/rand package.

5.1 Update mathutils/math.go

package mathutils

import (
    "math/rand"
    "time"
)

// Add returns the sum of two integers.
func Add(a, b int) int {
    return a + b
}

// Multiply returns the product of two integers.
func Multiply(a, b int) int {
    return a * b
}

// Random returns a random integer between min and max (inclusive).
func Random(min, max int) int {
    rand.Seed(time.Now().UnixNano())
    return rand.Intn(max-min+1) + min
}

5.2 Use Random in the Calculator

Update calculator/main.go:

package main

import (
    "fmt"
    "example.com/mathutils"
)

func main() {
    a, b := 10, 5
    fmt.Printf("Add: %d + %d = %d\n", a, b, mathutils.Add(a, b))
    fmt.Printf("Multiply: %d * %d = %d\n", a, b, mathutils.Multiply(a, b))

    randomNum := mathutils.Random(1, 100)
    fmt.Printf("Random number between 1 and 100: %d\n", randomNum)
}

Key Takeaways

This pattern scales well: as your project grows, you can extract reusable logic into separate modules and share them across your organization or publish them publicly.