This article is shared by Huawei Cloud community “Take a look at the Multi-module Workspace mode of Go 1.18 new features” by: One of the universe su.

The introduction

In 2022, the Go team released Go 1.18. As a major release change, Go 1.18 certainly included a lot of new features. The Go team also mentioned that it was the biggest change to Go since the language was released, and the performance improvements were significant.

One of these features is to provide a multi-module workspace pattern. The official blog explains:

The Go module has been almost universally adopted, and Go users give it very high satisfaction scores in our annual survey report. In our 2021 user survey, users working across multiple modules identified the most common challenges for different modules. In Go 1.18, we solved this problem with the new Go Workspace pattern, which makes it easy to use multiple modules.

Go’s dependency management, or Go Module, has been around for several years, but has been the subject of much criticism and improvement. With the launch of the Multi-Module Workspaces mode in Go 1.18, which supports multiple Workspaces for modules, let’s take a look at what makes it special.

A prerequisite for

  • Install Go 1.18 or later.
  • Tools for editing code. Any text editor you have will work fine. This article uses VSCode.
  • A command terminal. Go works fine on any terminal on Linux and Mac as well as on PowerShell or CMD in Windows. This article uses Ubuntu.

Workspace mode

There are two classic questions that are particularly boring when dealing with Go projects every day:

  • Depends on the local replace module
  • Depends on locally unpublished modules.

replace module

Scenario 1: For example, in a Go project, we would use Replace to resolve some local dependencies or custom code. We will do this using replace in the go.mod file.

The following code:

replace golang.org/x/net => /Users/eddycjy/go/awesomeProject
Copy the code

This allows for accuracy when linking to local development. But at the same time, there are problems:

  • Local path: The replacement setting essentially translates to a local path, which means that everyone is different.
  • Remote dependencies: File changes are uploaded to the Git repository, so if you accidentally upload a file, it will affect other developers, or you will have to change it back every time you upload.

Unpublished modules

Scenario 2: When you are working on a local Go project, you may be working on multiple libraries (project library, tool library, third-party library) at the same time.

Look at the following code:

package main

import (
    "github.com/eddycjy/pkgutil"
)

func main() {
    pkgutil.PrintFish()
}
Copy the code

If you run Go Run or Go Mod Tidy at this point, it will not work and will fail.

The following error is thrown.

fatal: repository 'https://github.com/eddycjy/pkgutil/' not found
Copy the code

This exception because library github.com/eddycjy/pkgutil on the lot is not available, so we can not pull.

Solution: Prior to Go 1.18, we either replaced or uploaded directly to Github, where dependencies would be pulled by the Go tool chain.

Many users question this: Do all Go dependencies have to be uploaded to GitHub and strongly bound?

The new couple are very unfriendly.

Workspace model

After several rounds of feedback from the community, Michael Matloob put forward a Proposal: Multi-module Workspaces in CMD/GO. After extensive discussion and implementation, GO 1.18 was officially implemented.

One of the core concepts of the new proposal is the addition of the Go Work workspace concept, which addresses the Go Module dependency management model.

You can set a series of dependent module local paths in the go. Work file of the local project, and then combine the Modules under the path into the workspace of the current GO project, that is, N go Modules into 1 go work, and the workspace has the highest read priority.

We can see this with Go Help, as shown below.

$ go help work Work provides access to operations on workspaces. Note that support for workspaces is built into many other commands, not just 'go work'. See 'go help modules' for information about Go's module system of which workspaces are a part. See https://go.dev/ref/mod#workspaces for an in-depth reference on workspaces. See https://go.dev/doc/tutorial/workspaces for an introductory tutorial on workspaces. A workspace is specified by a go.work file that specifies a set of module directories with the "use" directive. These modules are used as root modules by the go command for builds and related operations. A workspace that does not specify modules to be used cannot be used to do builds from local modules. go.work  files are line-oriented. Each line holds a single directive, made up of a keyword followed by arguments. For example: 1.18 use the go.. /foo/bar use./baz replace example.com/foo v1.2.3 => example.com/bar v1.4.5 The leading keyword can be factored out of adjacent lines to create a block, like in Go imports. use ( .. /foo/bar ./baz ) The use directive specifies a module to be included in the workspace's set of main modules. The argument to the use directive is the directory containing the module's go.mod file. The go directive specifies the version of Go the file was written at. It is possible there may be future changes in the semantics of workspaces that could be controlled by this version, but for now the version specified has no effect. The replace directive has the same syntax as the replace directive in a  go.mod file and takes precedence over replaces in go.mod files. It is primarily intended to override conflicting replaces in different workspace modules. To determine whether the go command is operating in workspace mode, use the "go env GOWORK" command. This will specify the workspace file being used. Usage: go work <command> [arguments] The commands are: edit edit go.work from tools or scripts init initialize workspace file sync sync workspace build list to modules use add  modules to workspace file Use "go help work <command>" for more information about a command.Copy the code

Simply execute go Work Init to initialize a new workspace, followed by the parameters for the specific submodule mod to be generated.

The command is as follows:

go work init ./mod ./tools
Copy the code

The project structure is as follows:

├── ├─ ├─ all exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercisesCopy the code

The content of the generated go.work file is as follows:

Go 1.18 use (./mod./tools)Copy the code

The new go.work has the same syntax as go.mod and can also be used with the replacement syntax.

1.18 use the go (...). Replace golang.org/x/net => example.com/fork/net v1.4.5Copy the code

A total of three directives are supported in the go.work file.

  • Go: Declare the GO version number, which is mainly used for subsequent version control of new semantics.
  • Use: Declares the specific file path of the module on which the application depends. The path can be absolute or relative, and can be outside the application’s destiny directory.
  • Replace: States that the import path dependent on the module is replaced, taking precedence overgo.modIn thereplaceThe instructions.

If you want to disable the workspace mode, you can specify it using the -workfile=off command.

That is, execute the following command at run time.

go run -workfile=off main.go

go build -workfile=off
Copy the code

The go.work file doesn’t need to be committed to a Git repository, otherwise it’s a bit of a hassle.

As long as you set go.work in the Go project, you will be in workspace mode at run time and compile time, and workspace configuration will be given top priority to meet your local development needs.

That concludes the core knowledge of the workspace.

How do I create and use a workspace

Following the official tutorial, take a look at how to use multiple workspace modes.

  1. Open the terminal and get inhomeDirectory:
$ cd
$ mkdir workspace_test && cd workspace_test
Copy the code
  1. The module initialization

Create a new module that relies 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
Copy the code
  1. Add pairs using Go Getgolang.org/x/exampleModule dependencies.
$go get golang.org/x/example go: downloading golang.org/x/example v0.0.0-20220304235025-AD95e7f791d8 go: Added golang.org/x/example v0.0.0-20220304235025 - ad95e7f791d8Copy the code
  1. Create in the Hello directoryhello.goFile, as follows:
package main

import (
	"fmt"

	"golang.org/x/example/stringutil"
)

func main() {
	fmt.Println(stringutil.Reverse("Hello, yuzhou1su"))
}
Copy the code

The final code structure is as follows:

Run the hello program and get an inverted string:

$ go run example.com/hello   
us1uohzuy ,olleH
Copy the code
  1. We’re going to create onego.workFile to specify a workspace with modules.

First, initialize the workspace:

# wade @ wade-virtual-machine in ~/workspace_test [23:02:29] 
$ go work init ./hello  
Copy the code

The go work init command tells go to create a go.work file for the workspace that contains modules in the./hello directory. The syntax of the go.work file is similar to go.mod

The files in the automatically created go.work are as follows:

1.18 use go. / helloCopy the code
  • goThe directive tells Go which version of Go should be used to interpret the file. It is similar to the go directive in the go.mod file.
  • useThe directive tells Go that the module in the Hello directory should be the main module at build time.

Therefore, the module will be active in any subdirectory of the workspace.

Then, run the program in the workspace directory

In the Workspace directory, run:

# wade @ wade-virtual-machine in ~/workspace_test [23:02:48] 
$ go run example.com/hello
us1uohzuy ,olleH
Copy the code

The Go command contains all modules in the workspace as master modules.

This allows us to reference a package in a module, even outside the module. Running the go run command outside of a module or workspace results in an error because the go command does not know which modules to use.

conclusion

Today we introduced a new feature in Go 1.18: the multi-Module workspace model. It remains essentially a solution to local development needs.

Because go.mod files are so project-dependent, they are basically uploaded to a Git repository, making it difficult to do anything with them. So we just built Go.work to be purely local and easy to use.

With the new go.work, you can work with completely local files without affecting the rest of the development team.

For more information about multi-module workspaces, check out the official tutorial.

References:

  • Go 1.18 is released!
  • New in Go 1.18: Multi-Module workspace mode
  • Go 1.18 New feature preview: Go Workspace mode
  • What are go workspaces and how do I use them?
  • Tutorial: Getting started with multi-module workspaces

Click to follow, the first time to learn about Huawei cloud fresh technology ~