6

New in Go 1.21: Toolchains

 9 months ago
source link: https://eltonminetto.dev/en/post/2023-10-18-go121-toolchain/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

New in Go 1.21: Toolchains

Elton Minetto

October 18, 2023

Translations: Pt

The version 1.21 of the language implemented an essential new feature. According to the documentation:

Starting in Go 1.21, the Go distribution consists of a go command and a bundled Go toolchain, which is the standard library as well as the compiler, assembler, and other tools. The go command can use its bundled Go toolchain as well as other versions that it finds in the local PATH or downloads as needed.

I did a proof of concept to validate how this new functionality works, which I will describe in this post.

On my machine, I had the following version of go:

go version
go version go1.21.0 darwin/arm64

I created three libs, each with a different version of go as a requirement. In the commands below, you can see the content of each go.mod of the libs:

❯ cd l1 ; cat go.mod; cd ..
module github.com/eminetto/l1

go 1.19.0

❯ cd l2; cat go.mod; cd ..
module github.com/eminetto/l2

go 1.20.0

❯ cd l3; cat go.mod; cd ..
module github.com/eminetto/l3

go 1.21.1

Starting with version 1.21, the go 1.20.0 line of the go.mod file, in this example of the l2 lib, indicates the minimum language version required we need to use to compile it.

Next, I created a project to import the three libraries. The following diagram shows the dependencies:

toolchain

The main.go of the proj contains:

package main

import (
	"fmt"

	"github.com/eminetto/l1"
	"github.com/eminetto/l2"
	"github.com/eminetto/l3"
)

func main() {
	fmt.Println(l1.Sum(1, 2))
	fmt.Println(l2.Sum(1, 2))
	fmt.Println(l3.Sum(1, 2))
}

The project’s go.mod contains:

module github.com/eminetto/proj

go 1.21.0

require (
	github.com/eminetto/l1 v0.0.0-20231012141607-826d3914801f
	github.com/eminetto/l2 v0.0.0-20231012141624-28120aab8596
	github.com/eminetto/l3 v0.0.0-20231012141624-2810bakab896
)

I ran the project, and it worked without errors:

❯ go run main.go
3
3
3

Next, I simulated the process of updating one of the libs. To do this, I updated the l3 lib to a newer version of Go:

❯ cd l3; cat go.mod
module github.com/eminetto/l3

go 1.21.3

I pushed it to the repository and created a new version (v0.0.1).

According to the documentation:

The Go toolchain refuses to load a module or workspace that declares a minimum required Go version greater than the toolchain’s own version.

To validate this, in the project, I updated the version of l3:

❯ go get github.com/eminetto/[email protected]
go: downloading github.com/eminetto/l3 v0.0.1
go: github.com/eminetto/[email protected] requires go >= 1.21.3; switching to go1.21.3
go: upgraded go 1.21.0 => 1.21.3
go: upgraded github.com/eminetto/l3 v0.0.0-20231012141629-a747d5b44b93 => v0.0.1

What’s new is the following excerpt:

go: github.com/eminetto/[email protected] requires go >= 1.21.3; switching to go1.21.3
go: upgraded go 1.21.0 => 1.21.3

What happened was that the go command updated the version of Go installed on my machine to 1.21.3:

❯ go version
go version go1.21.3 darwin/arm64

And the project’s go.mod has also been updated to version 1.21.3.

❯ cat go.mod 
module github.com/eminetto/proj

go 1.21.3

require (
        github.com/eminetto/l1 v0.0.0-20231012141607-826d3914801f
        github.com/eminetto/l2 v0.0.0-20231012141624-28120aab8596
        github.com/eminetto/l3 v0.0.1
)

And the project continues to run without errors. My machine now has the minimum version necessary to import ALL libs and run without errors. In this case, it was updated to 1.21.3 because it was necessary to run l3 since the others are below the current version I had installed on my machine (1.21.0).

Another fact I noticed is that there is now one version of Go for the project and another for the rest of the operating system:

❯ cd proj

Developer/post-toolchain/proj
❯ go version
go version go1.21.3 darwin/arm64

Developer/post-toolchain/proj
❯ cd ..

~/Developer/post-toolchain
❯ go version
go version go1.21.0 darwin/arm64

The go command identifies that the proj directory requires a specific language version. And all this management is done automatically.

Let’s now think about a slightly more complex example. Let’s suppose that one of the libs, for example, l2, was updated to:

module github.com/eminetto/l2

go 1.24rc1

The go command gets the list of available toolchains and finds that the most recent releases are Go 1.28.3, Go 1.27.9, and Go 1.29rc2. The go command will choose Go 1.27.9 in this situation.

If l2 required Go 1.28 or later, the go command would choose Go 1.28.3 because Go 1.27.9 is too old. If l2 required Go 1.29 or later, Go 1.29rc2 would be chosen because the other options are too old.

When executing the command go get github.com/eminetto/[email protected] (the newest version of the package), it will update the project’s go.mod file, and a new line will be added with the chosen toolchain :

❯ cat go.mod 
module github.com/eminetto/proj

go 1.27.9

toolchain go1.27.9

require (
        github.com/eminetto/l1 v0.0.0-20231012141607-826d3914801f
        github.com/eminetto/l2 v0.0.1
        github.com/eminetto/l3 v0.0.1
)

You can find more details about the motivations behind this feature, the version naming, and advanced behavior settings in the language’s official documentation.

This feature is another example of the language team’s care to maintain compatibility between past and future versions. With this functionality, it will be possible to guarantee the longevity of applications written in Go, which is very important for the future of the language in increasingly complex environments.

Thanks to friends Matheus Mina, Tiago Temporin, and Eduardo Hitek for reviewing the text and suggesting improvements.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK