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 add go.mod new replace, 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 as require).

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 inside go.modfiles 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 syncwhich 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.1and another module requires a dependency on github.com/davecgh/go-spew versions v1.1.0then 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:

  1. Create go.workfile:

    go work init
  2. 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 in go.work;

  • go list can’t change go.modfiles:

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 in go.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 in go.mod file, and you need to remember this. Fortunately, dependencies can be reduced through the command go work sync.

  • The problem with multiple go.mod within the same repository using Go Workspaces is not solved in any way.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *