A Quick Look at Go Workspaces in Go 1.18
Go version 1.18 is coming out soon, and in the mass consciousness it will most likely be associated with Generics. But besides them, there are a few more tasty features. For instance, Go Workspaces.
What gives Go Workspaces?
Go Workspaces allows you to work with multiple modules at the same time. Theoretically, this could have been done before, but Go Workspaces adds a bit of comfort.
Previously, when working with several modules at the same time, they had to be “linked” through the directive replace
v go.mod
-file.
The replace approach go.mod
has a number of significant disadvantages:
each module lives its own independent life and some development tools can only work with one module at a time.
replace
-s are not transitive. That is, if you addgo.mod
newreplace
, then it must be added to all modules that use it. Even with a small number of modules, this causes noticeable inconvenience.run the utility via
go run
is possible only from the directories of those modules that either contain this utility or “see” it through replace (it must also be declared asrequire
).
Go Workspaces adds some comfort:
gopls
provides information on all used modules at once;are common
replace
-s can be declared in one place, and are visible to all declared modules;local edits with directive
replace
no need to write insidego.mod
files that are in the repository;assembly and launch of utilities for all declared modules can be from the directory that contains
go.work
and its child directories;command is added
go work sync
which allows you to update the dependencies of multiple modules to the most recent shared version.
How does it work?
Using go.work
-file Go collects a common list of dependencies from all those listed in go.mod
-files, taking into account replace
– directives. Based on all the listed dependencies, a single dependency graph is formed, which is applied to all used modules. If for one module it is specified in different go.mod
several conflicting replace
-directives – there will be an error.
For example, if one module requires a dependency on github.com/davecgh/go-spew versions v1.1.1
and another module requires a dependency on github.com/davecgh/go-spew versions v1.1.0
then both module will be executed with an older version v1.1.1
.
This works for all modules of the same Go Workspace, even if there is no dependency between the modules.
What doesn’t give Go Workspace?
If you want to use multiple go.mod
-files within one (mono)repository, then go.work
will not help you in any way: within one Go Workspace, common dependencies are used, collected on the basis of all used go.mod
-files. That is, such an approach will not fundamentally differ from the use of one go.mod
-file, except for the increase in complexity due to the greater number of files used.
The actual link to neighboring modules through tags or the commit ID also remains behind the scenes of Go Workspace.
How to start using Go Workspaces?
A group of commands has been added to use Go Workspaces go work
.
First you need to call the command go work init
at the root of the workspace.
Let’s say we have a workspace like this:
Then to use Go Workspaces you need:
Create
go.work
file:go work init
Add modules there:
go work use shared go work use tools
As a result, a file will be created go.work
with content like:
go 1.18
use (
shared
tools
)
And then, for example, you can call the assembly from any subdirectory inside the workspace:
go run github.com/bozaro/go/go-work-play/tools/hello
If in go.work
add replace
-s, they will also have an effect on all modules of the workspace.
What other problems are there?
It is important to understand that using Go Workspaces changes the behavior of some commands, for example:
go run
stops working for modules that are not declared ingo.work
;go list
can’t changego.mod
files:
go list -mod=mod -m -json
go: -mod may only be set to readonly when in workspace mode, but it is set to "mod"
Remove the -mod flag to use the default readonly value,
or set -workfile=off to disable workspace mode.
Some utilities may not be ready for this change.
Summarizing
I made the following conclusions for myself.
Using Go Workspaces greatly simplifies the execution of any utilities due to the ability to call them from anywhere in the workspace without unnecessary squats.
You can not add parasitic
replace
directives ingo.mod
files in order to edit several related projects at the same time.Using
go.work
you can get a situation where the code being run will not be executed with the dependencies that are specified ingo.mod
file, and you need to remember this. Fortunately, dependencies can be reduced through the commandgo work sync
.The problem with multiple
go.mod
within the same repository using Go Workspaces is not solved in any way.