What's new in Go 1.17

The Go 1.17 release comes with a couple of interesting updates.

Go 1.17 is out

Go 1.17 was released on August 16, 2021 and includes a couple of noteworthy changes. The full changelog is here, and I will not look into all changes in detail but rather take a closer look at the most interesting ones. This includes changes that have an noticeable impact on everyday work.

Let's start by looking at changes to the tool chain, especially those these might have an impact on current projects.


The Go Module system observes a couple of enhancements, most notably module graph pruning and lazy builds.

Module graph pruning

Up to Go 1.16, a module graph might contain module requirements that have no impact on building the main module. (Side note: "main module" refers to the module in which the go command is invoked. In other words, it is the module for that you are about to run go buildgo test, or similar commands.)

Go 1.17 prunes the module graph from those "impact-less" dependencies, except for cases that require backward compatibility to module files created with Go 1.16 or earlier.

In turn, the go.mod file contains more direct dependencies. This change enables another feature: lazy module loading. The gotool does not have to download go.mod files of dependencies anymore that have no impact on the current build.

What this means for your projects

If you re-create a go.modfile with Go 1.17, its contents may change, as require directives may be added if the dependencies include modules that provide transitively-imported packages.

Module deprecation

Developers can mark a module as deprecated by first adding a // Deprecated: comment to go.mod and then tagging a new version. If go get finds a deprecated module that is needed for a build, it prints a warning.

Tip: To find deprecations of all dependencies of a module, use

go list -m -u

go mod download

When go mod download is invoked without arguments, sums are no longer saved for downloaded module content.

Use go mod download all to save sums for all modules.

Go Get

Two updates to go get:

No more -insecure flag

go get has no -insecure flag anymore. If you need to download modules via plain HTTP (for example, from a private repository inside your company), use the GOINSECURE environment variable instead.

go get outside main module is deprecated

Using go get for installing commands outside the main module is deprecated.

Use go install [email protected] instead, where @version is either a valid SemVer tag, or the string @latest.

From Go 1.18 onwards, the -d flag ("dowload only") will always be enabled, hence making installing via go get impossible.

Conditional builds

//go:build preferred over // +build

Go 1.17 introduces a new syntax for conditional build comments.

A build comment like

// +build linux,amd64 darwin

can now be written as

//go:build linux && amd64 || darwin

which is definitely less confusing, especially for developers who do not use conditional build tags every day. ("What's the AND operator again? Comma or space?")

Moreover, the //go: syntax is in line with other comment-based directives like //go:embed or //go:generate, making the comment directive syntax more consistent.

The old syntax continues to be recognized (at least during a migration phase), and gofmt and go fmt automatically synchronize build comments of the new syntax with existing build comments of the old syntax.

In addition to that, go vet warns about unmatched //go:build and // +build lines.

Language change: conversions from slice to array pointer

An enhancement to the language itself now allows to convert an expression s of type []T ("slice of type T") to an array pointer type *[N]T, where N must be equal to, or larger than, len(s). (In other words, the array must be declared as large enough so that it can refer to all elements of the slice.) Otherwise the conversion panics.

Standard library changes

The standard library received quite a number of changes but most of them are rather small and address some edge case only, or are speed enhancements (especially for some of the crypto packages).

Noteworthy changes:

Package unsafe has two new convenience functions

Package unsafe now comes with two functions that make common operations simpler.

unsafe.Add(ptr, len) implements unsafe.Pointer(uintptr(ptr) + uintptr(len)).

unsafe.Slice(ptr, len) returns a slice whose elements are of the same type as ptr. (Not surprisingly, the slice's underlying array starts at ptr and has a length and capacity of len.)

URL query parsing: no more semicolons as setting separators

The new/url and net/http packages do not accept semicolons in URL query strings anymore, except if they are percent-encoded. Previously, semicolons were accepted as settings separators besides ampersands (&).

Package testing provides new flag -shuffle

If you want to ensure that your tests only succeed because they run in a certain order, the new testing flag -shuffle is for you.

More info and download

See the Go 1.17 changelog for the full list of changes.

As always, the latest Go release is available at golang.org/dl.

Happy coding! ʕ◔ϖ◔ʔ


Applied Go Courses helps you getting up to speed with Go without friction. Our flagship product, Master Go, is an online course with concise and intuitive lectures and many practices and exercises. Rich graphic visualizations make complex topics easy to understand and remember. Lectures are short and numerous, to help planning and saving your precious time, as well as serving as quick reference material after the course. Learn more at https://appliedgo.com.


Photo by Fabien BELLANGER on Unsplash


Categories: Releases