Introduction
Welcome to this post, where we'll discuss the Work command in Go, which was released in Go version 1.18.
In my case, my Go version is 1.21; however, you can use whatever latest version of 1.18
If we must make changes to a package that we are using in our project, with this functionality, we can use our local package, test it in our project without the necessity of uploading it to a repository, and import it. And without the necessity of using 'replace' in our go.mod file either.
Go Work
With this command, we can work with our locally imported package in our project instead of uploading our changes to our repository and then importing them into our project.
Go Work Init
With this command:
$ go work init
We created our go.work, which contains our local modules.
Go Work Use
With the use command, we can define the local modules imported into our project. For example, we can import our project into the go.work file.
$ go work use .
Our go.work file will look like
go 1.21.0
use (
.
)
And we can add new modules (which are imported into our project)
$ go work use .../my-package
Our go.work file will look like
go 1.21.0
use (
.
../my-package
)
In this way, we are going to use our local my-package package instead of the remote package.
Example
External package
We have the following package called domain, wherein we have a user struct with its tags.
package domain
type User struct {
ID string `json:"id"`
FirstName string `json:"first_name"`
}
The repository of this package is blog_go_work_pkg , the latest tag is v0.0.1, and its folder structure is:
blog_go_work_pkg/
├─ domain/
│ └─ user.go
└─ go.mod
Project
We are going to create our project (in my case, I called it 'blog_go_work_project'). The first thing that we are going to do is initialize our go.mod file
go mod init
and import our external package
go get github.com/beeblogit/blog_go_work_pkg
we create our main.go file, import our package and use our User struct
We instantiate a user variable and perform 'Marshal' to display the user entity in JSON.
package main
import (
"encoding/json"
"fmt"
"github.com/beeblogit/blog_go_work_pkg/domain"
)
func main() {
u := domain.User{
ID: "1231",
FirstName: "Nahuel",
}
value, _ := json.Marshal(u)
fmt.Println(string(value))
}
and the result is
{"id":"1231","first_name":"Nahuel"}
But how can we perform changes in our package and import it without the need to upload the changes to the repository? In this way, we can use the 'work' functionality to perform this action.
Work functionality
As a clarification, it is necessary to have our Go path configuration set correctly and to respect our project structure.
my folder project struct from the GOPATH is
src/
└─ github/
└─ beeblogit/
├─ ...
├─ blog_go_work_pkg/
├─ blog_go_work_project/
└─ ...
We are going to make some changes to our package, adding the 'LastName' and 'Country' fields (without uploading it to the repository).
type User struct {
ID string `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Country string `json:"country"`
}
In our project, we are going to execute the following command to create our go.work file
go work init .
A go.work file should have been generated with this content.
go 1.21.0
use .
We are going to add our locally external package to our go.work file; for this, we execute the following command.
go work use ../blog_go_work_pkg
Our go.work would look like this:
go 1.21.0
use (
.
../blog_go_work_pkg
)
In our project, we are going to define the values for the 'LastName' and 'Country' fields.
func main() {
u := domain.User{
ID: "1231",
FirstName: "Nahuel",
LastName: "Costamagna",
Country: "Argentina",
}
value, _ := json.Marshal(u)
fmt.Println(string(value))
}
we execute the program and see the result
{"id":"1231","first_name":"Nahuel","last_name":"Costamagna","country":"Argentina"}
In this way, we obtain our 'blog_go_work_pkg' local package instead of the remote package on GitHub.
We can remove the external package from our project using the following command.
go work edit -dropuse ../blog_go_work_pkg
and we see the content of our 'go.work' file.
go 1.21.0
use .
Of course, we can remove it directly from our 'go.work' file without the need to execute a command.
We run the program again and can see the error because we are using the externally hosted package instead of the local one.
# command-line-arguments
./main.go:13:3: unknown field LastName in struct literal of type domain.User
./main.go:14:3: unknown field Country in struct literal of type domain.User
Conclusion
With this functionality, we can use our imported package locally without the need to upload it to the repository or use replace in our go.mod file. For more information, you can refer to the official documentation