Go Workspaces (multi-module)
Muhammad Hamza Hameed
Posted on November 21, 2022
Workspace Deserves a Spotlight
A new feature in Go 1.18 go workspace mode
which makes it simple to work with multiple modules. With multi-module workspaces, you can tell the Go command that you’re writing code in multiple modules at the same time and easily build and run code in those modules.
Why Workspace?
In short, the workspace makes the multiple-module dependency and switch easier in local development.
You must have encountered such an issue: The multiple modules in the repo reference each other directly. But your local changes to a module A
fail to reflect in the module B
that depends on A
. What we take to overcome this is
- Push the modified code of module
A
to GitHub, and pull the update in moduleB
. - Replace the module
B
go.mod file’s dependency onA
to a local absolute path.
replace github.com/hamza/a v0.1 => /Users/hamza/workspace/repo/module-a
Both solutions have their own cons, which bring us pain in developing in multi-module mode somehow.
The first method is not designed in the way you like it if you try to avoid releasing new versions before more tests. Besides, after you publish it on Github, more releases and more versions are required for fixing the bug once they occur.
For the second method, you should always remind yourself to revert the changes in the local go.mod
file before submitting; otherwise, you might drag your co-developers into trouble.
In light of this, Go released the go worspace mode
in its version 1.18
.
Set Up Workspace
Let’s test whether the workspace can ease the above-mentioned issues. Make sure that you’ve installed Go
at Go 1.18
or later using the links at go.dev/dl.
Create a module for your code
To begin, create a module for the code you’ll write.
- Open a command prompt and create a directory for your code called workspace.
$ mkdir workspace
$ cd workspace
- Initialize the module
In this example, I will create a new module hello
that will depend on the golang.org/x/example
module.
$ mkdir hello
$ cd hello
$ go mod init example.com/hello
go: creating new go.mod: module example.com/hello
Add a dependency on the golang.org/x/example module by using go get.
$ go get golang.org/x/example
Create hello.go in the hello directory with the following contents:
package main
import (
"fmt"
"golang.org/x/example/stringutil"
)
func main() {
fmt.Println(stringutil.Reverse("Hello"))
}
Now, run the hello program:
$ go run example.com/hello
olleH
Create the workspace
In this step, we’ll create a go.work
file to specify a workspace with the module.
Initialize the workspace
In the workspace directory, run:
$ go work init ./hello
The go work init command tells go to create a go.work
file for a workspace containing the modules in the ./hello
directory.
The go command produces a go.work file that looks like this:
go 1.18
use ./hello
The go.work
file has similar syntax to go.mod
.
The go
directive tells Go
which version of Go
the file should be interpreted with. It’s similar to the go
directive in the go.mod
file.
The use
directive tells Go
that the module in the hello
directory should be main modules when doing a build.
So in any subdirectory of workspace the module will be active.
Run the program in the workspace directory
In the workspace
directory, run:
$ go run example.com/hello
olleH
The Go command includes all the modules in the workspace as main modules. This allows us to refer to a package in the module, even outside the module. Running the go run
command outside the module or the workspace would result in an error because the go command wouldn’t know which modules to use.
Next, we’ll add a local copy of the golang.org/x/example
module to the workspace. We’ll then add a new function to the stringutil
package that we can use instead of Reverse.
Download and modify the golang.org/x/example module
- Clone the repository
From the workspace
directory, run the git command to clone the repository:
$ git clone https://go.googlesource.com/example
- Add the module to the workspace
$ go work use ./example
The go work use
command adds a new module to the go.work
file. It will now look like this:
go 1.18
use (
./hello
./example
)
The module now includes both the example.com/hello
module and the golang.org/x/example
module.
- Add the new function.
We’ll add a new function to uppercase a string to the golang.org/x/example/stringutil
package.
Create a new file named toupper.go
in the workspace/example/stringutil
directory containing the following contents:
package stringutil
import "strings"
// ToUpper uppercases argument string.
func ToUpper(s string) string {
return strings.ToUpper(s)
}
Run the code in the workspace
References
Get the full source code from this github repository.
Posted on November 21, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.