Disclaimer: This post includes Amazon affiliate links. If you click on one of them and you make a purchase I’ll earn a commission. Please notice your final price is not affected at all by using those links.
Perhaps one of the most anticipated Go releases is here! Superseding Go 1.17, this is Go 1.18, released on March 15, 2022! 💥 🎉 🎊
🎊 Go go1.18 is released!
— Go (@golang) March 15, 2022
📝 Release notes: https://t.co/UFumhMjcOL
⬇️ Download: https://t.co/fnDCVVhJXK#golang pic.twitter.com/uWNSy5V7nv
What is new?
There are lot of brand new language features, in this post I will discuss those I believe are the most relevant and the ones that change the way we use Go.
Updating
Depending on your development platform and the production system you use for running your service you may already have access to start using Go 1.18, however as usual downloading Go is available via the official page.
For more concrete examples:
Type Parameters aka Generics
The code used for this post is available on Github.
Using Types Parameters allows us to implement code that consists of data and behavior where types are not explicitly indicated, the simplest example would be defining a sorting algorithm where it can support any numeric type. For example starting with something like:
6func Sum(n ...int64) int64 {
7 var s int64
8 for _, v := range m {
9 s += v
10 }
11 return s
12}
13
14func main() {
15 fmt.Println(Sum([]int64{1, 2, 3, 4}...))
16 fmt.Println(Sum(1, 2, 3))
17}
We can rewrite it in such a way it can accept more numeric types, in this case floats and integers:
9func Sum[V constraints.Float | constraints.Integer](m ...V) V {
10 var s V
11 for _, v := range m {
12 s += v
13 }
14 return s
15}
16
17func main() {
18 fmt.Println(Sum([]int64{1, 2, 3, 4}...))
19 fmt.Println(Sum(1, 2, 3))
20 fmt.Println(Sum(uint32(1), uint32(3)))
21 fmt.Println(Sum(1.2, 2.3, 3.5, 4.6))
22}
Fuzz Test Support
Another testing option that allows us to introduce inputs to our tests in order to find vulnerabilities or inputs that cause crashes, this requires a full blog post to cover the new feature properly, in the meantime I encourage you to read the official documentation, it’s well explained there.
Multi-Modules Workspaces
It’s a mode to allow working with multiple go modules at the same time, this is useful if you happen to be working on multiple Go modules at the same time, this is another feature that requires a dedicated blog post, in the meantime please refer to the official documentation.
Go version included in binary
The code used for this post is available on Github.
This is a change added to the compiler that allows the binary to include VCS information when building the binary, in order to take advantage of that we must use the full module name when building the binary, for example:
go build -o main github.com/MarioCarrion/videos/2022/03/17/002-versions
Next to request version defined in the binary we could either use the debug/buildinfo package or use the command directly like so:
go version -m <binary>
If the binary is compiled using Go 1.18 the output will be similar to:
main: go1.18
path github.com/MarioCarrion/videos/2022/03/17/002-versions
mod github.com/MarioCarrion/videos/2022/03/17/002-versions (devel)
build -compiler=gc
build CGO_ENABLED=1
build CGO_CFLAGS=
build CGO_CPPFLAGS=
build CGO_CXXFLAGS=
build CGO_LDFLAGS=
build GOARCH=amd64
build GOOS=darwin
build GOAMD64=v1
build vcs=git
build vcs.revision=71f09cdcbcd5379cf695a775680597abc2432991
build vcs.time=2022-03-17T03:06:39Z
build vcs.modified=false
Which happens to include all VCS values as well as the flags used to build the binary, if we recompile the binary using Go 1.17, and the run the same command the output looks like this:
main: go1.17
path github.com/MarioCarrion/videos/2022/03/17/002-versions
mod github.com/MarioCarrion/videos/2022/03/17/002-versions (devel)
Quite a big difference.
New net/netip
package
The code used for this post is available on Github.
This new package defines a new implementation of the IP type that takes less memory, is immutable, and is comparable so it supports ==
and can be used as a map key, a concrete example looks like:
1package main
2
3import (
4 "fmt"
5
6 "net"
7 "net/netip"
8)
9
10func main() {
11 ip := "192.168.0.1"
12
13 fmt.Println(net.ParseIP(ip))
14
15 addr, _ := netip.ParseAddr(ip)
16 fmt.Println(addr)
17}
strings
includes a new “Cut” function
The code used for this post is available on Github.
strings.Cut
in a simplifies other existing functions such as Index
, IndexByte
, IndexRune
and SplintN
; also strings.Title
was deprecated and replaced by golang.org/x/text/cases. An example of this new function looks like this:
1package main
2
3import (
4 "fmt"
5 "strings"
6)
7
8// It can replace and simplify many common uses of Index, IndexByte, IndexRune, and SplitN.
9
10func main() {
11 cut := func(sep string) {
12 s := "hello|world"
13 before, after, found := strings.Cut(s, sep)
14 fmt.Printf("cut(%q, %q): %q, %q, %v\n", s, sep, before, after, found)
15 }
16
17 cut("|")
18 cut("hello")
19 cut("nothing")
20}
Conclusion
Those are the new features I found interesting, I’m pretty sure Go 1.19 will be exciting as this one, when the time comes I will blog about it for sure.
Recommended reading
If you’re looking to sink your teeth into more Go-related topics I recommend the following books: