Go Local Modules and Packages - Understand How to Create and Use Them
Introduction
When building applications in Go, modularizing your code into separate modules and packages is essential for maintaining clean and reusable code. In this tutorial, we’ll walk through creating two local Go modules: restapi01/backend and restapi/maincaller. The backend module will serve as a basic HTTP server that outputs a simple HTML view, while the maincaller module will call functions from backend.
We shall look into:
- Initializing Go modules and packages.
- Using
go mod editandgo mod tidyto set up local imports without publishing packages. - Testing the interaction between these modules and calling one from the other.
Let’s get started!
Project Structure
We’ll set up the following structure:
restapi/
├── backend/
│ ├── go.mod
│ ├── server.go
├── maincaller/
│ ├── go.mod
│ ├── main.go
Each module (backend and maincaller) will live in its own directory and act independently.
Step 1: Initializing the Backend Module
The backend module will serve as an HTTP server. Let’s set up restapi/backend to listen for requests and return a simple HTML response.
Create the
backenddirectory:mkdir -p restapi/backend cd restapi/backendInitialize a Go module:
go mod init restapi01/backendYour
restapi/backend/go.modfile should look like this with your current go version:module restapi01/backend go 1.20Write the
server.gofile:package backend import ( "fmt" "net/http" ) func StartServer() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "<h1>Hello from Backend!</h1>") }) fmt.Println("Starting server on :8080") http.ListenAndServe(":8080", nil) }Here,
StartServeris an exported function that starts an HTTP server on port8080. When accessed, it will return a simple HTML message.Initialize and tidy dependencies:
go mod tidy
Step 2: Initializing the Maincaller Module
Next, let’s set up restapi/maincaller, which will call the backend module to start the server.
Create the
maincallerdirectory:mkdir -p ../maincaller cd ../maincallerInitialize a Go module:
go mod init restapi/maincallerYour
restapi/backend/go.modfile should look like this with your current go version:module restapi01/maincaller go 1.20Write the
main.gofile:package main import ( "fmt" "restapi01/backend" ) func main() { fmt.Println("Calling backend server...") backend.StartServer() }Here, the
maincallerpackage imports therestapi01/backendpackage and calls itsStartServerfunction.Edit go.mod to Reference
backendLocally: Sincerestapi01/backendis a local module, we need to tell Go to look for it locally instead of remotely.Run the following command to add a local replace directive:
go mod edit -replace=restapi01/backend=../backendIt should add a line like:
replace restapi01/backend => ../backendUse
go mod tidy:go mod tidyThis command will update your
go.modandgo.sumfiles to ensure dependencies are managed correctly and the replace directive is respected. After running it, yougo.modfile in themaincallerdirectory should have an extra line like:require restapi01/backend v0.0.0-00010101000000-000000000000
Step 3: Run the Application
Now, let’s run maincaller to see everything in action.
Navigate to the
maincallerdirectory:cd maincallerStart the application:
go run main.goYou should see the output:
Calling backend server... Starting server on :8080Test the Server: Open your browser and navigate to
http://localhost:8080. You should see:Hello from Backend!
What is go mod edit -replace
The go mod edit -replace directive tells Go to look for restapi01/backend in the local ../backend directory rather than remotely. This is useful for testing and development, allowing us to manage dependencies without publishing modules to a repository.
Summary
Using local modules and packages helps you organize code efficiently, especially in larger projects. With the replace directive, you gain the flexibility to structure projects without worrying about dependency management issues. Happy coding!
