The Go 1.18 update is massive. Generics, Fuzzing, and Workspaces are perhaps the most prominent new features. What else changes with the new release?
In contrast to almost all other Go updates, this one includes a rather large addition to the language - generics. I will not go into much detail in this post, as there is already a truckload of Generics articles out there—including two from myself where I turned a binary search tree into its generic counterpart and discovered generic interface functions after coming across this proposal that generics made superfluous (or so I would guess—it is still open at the time of this writing).
I am pretty sure that with this single feature, Go will win a lot of new fans.
Some people would certainly want to see this one as #1. Fuzzing adds a new approach to Go unit tests. (To be honest, there have been fuzzing packages available long before, but this is now an integral part of Go.)
What’s the reason for fuzzing, and how does it work?
Well, no matter how busy you collect test cases for your table-driven tests, you can never be sure that you have not overlooked one or more subtle corner cases that might come back to haunt you when the code is deployed to production. Fuzzing cannot close that gap entirely but can help to narrow this gap drastically.
Fuzzing works by receiving some seed test cases from the developer—YOU!—and generating new test cases from these with a good dose of randomness involved. Chances are that one of these generated test cases will run into a subtle bug of your code where you expected it the least!
An interesting consequence of generating the test cases is that neither you nor the Fuzzing code can provide an expected output to test against. Instead, you need to test against more general attributes of the expected result. For example, a function that reverses a string could be tested by running the function twice and verifying that the result is the same as the original input.
Consider you have two modules A and B, and A imports B. If module B has already been published, the import path would point to the remote repository. Prior to Go 1.18, if you want to work on module B while testing the changes with module A, you had to add and remove replace
directives to module A’s go.mod
file as needed. Just don’t forget to remove it before pushing the changes to the remote repository!
With Go 1.18, local multi-module testing becomes significantly easier.
Create a workspace directory.
Put the first module to modify locally in a subdirectory of the workspace directory.
Add a go.work
file to the workspace directory, typically by calling go work use
.
Then you can add more modules to that workspace by calling go work use
for each of them. Only the first module needs to reside inside the workspace directory, the others can be where you want them to be.
Now you can cd
to a module in your workspace and run a go command like go build
as usual. If that module imports a module with the same module path as any of the other modules in the workspace, the go command will import the module from the local path instead.
An example: your main module imports "github.com/yourorg/somemodule"
, and a module in your workspace has this path in its go.mod
file, like module github.com/yourorg/somemodule
. Then the go command will use the local version of that module instead of the remote one. You can twist and tweak the code of somemodule
, and the main module will pick up the changes immediately.
Lots of interesting changes happened in the standard library. I’ll list only the changes in the “mainstream” packages, skipping the more specialized ones. For the full list, see the Go 1.18 release notes.
The sync
package has new TryLock
methods that do not block if the mutex is locked. They only return a boolean success indicator. I tested the TryLock method already as a possible strategy for avoiding deadlocks.
The new package net/netip
introduces a new IP address type Addr
that takes less memory, is immutable, and is comparable. Plus two other types, AddrPort
and Prefix
, as well as new functions to support the new types.
The bytes
and strings
packages have a new Cut
function for slicing a byte slice or string around a separator.
strings
also has a new Clone
method for copying a string into a different memory area.
In both packages, the Title
function is deprecated and superseded by the golang.org/x/cases
package.
html/template
and text/template
have new {{break}}
and {{continue}}
commands for breaking a loop early or continuing the next iteration, respectively.
text/template/parse
supports these commands for both packages via new constants NodeBreak
and NodeContinue
and new types BreakNode
andContinueNode
.
The compiler now correctly reports an error for variables that are declared inside a function literal but never used.
Passing a rune constant expression like '1' << 32
to the built-in functions print
or println
now correctly reports an overflow.
go get
no longer builds or installs packages in module-aware mode. Use go install
and add a version to the package path, e.g. go install github.com/appliedgocode/goman@latest
.This was only a quick overview. Read more here:
Tutorial: Getting started with generics - The Go Programming Language
Tutorial: Getting started with fuzzing - The Go Programming Language
How I turned a binary search tree into a generic data structure with go2go · Applied Go
Happy coding!
Categories: : Releases