Go v1.23 and older releases
I was using Go v1.23 already for several months. However, I decided to go in the past and check what new feature was added to Go and its ecosystem since I started as a Go developer.
To make it easier, I will mention just those features I have already used and those I would like to start using.
Go v1.23
Released on 2024-08-13.
Already used features of Go v1.23
Introduction of iterators was a big deal for me. However, before using them, I read the
official documentation ot iter package and two articles
before I was able to understand it correctly. I have already used it and I really like it.
It is true that consuming already made iterator is more fun than implementing the brand-new one.
I was as well a bit curious about adding Preorder
iterator into package go/ast.
Here is an example of iterator I have implemented (map-based y/x position sorting):
func (g guideMap) allSorted() iter.Seq[any] {
return func(yield func(any) bool) {
ys := slices.Collect(maps.Keys(g))
sort.Ints(ys)
for _, y := range ys {
row := g[y]
xs := slices.Collect(maps.Keys(row))
sort.Ints(xs)
for _, x := range xs {
if !yield(row[x]) {
return
}
}
}
}
}
Touches on time.Timer
and time.Ticker affected my work life. A possibility to garbage-collect
these unstopped objects before they fire bring some good. But usage of unbuffered channel internally brought guarantee
that for any call to a Reset or Stop method, no stale values prepared before that call will be sent or received
after the call. TL;DR: no more optional receiving of ticks after stopping a ticker/timer.
Not yet used interesting features of Go v1.23
I did not opt in for Go telemetry (using go telemetry command). I felt like possibly exposing something
secret. Better safe than sorry situation for me.
I did not even check generic aliases as it was still an experimental feature.
I did not find any reason to try “canonicalizing” values via unique
package. I know, Lua uses “interning” of strings, so there is always just one instance of each string
in the memory. So using Make[T] generic function and working with
Handle[T] type (two values of that
generic type are considered equal iff the values used for making them are equal) would reduce memory
footprint and comparison might be as efficient as simple pointer comparison.
The new structs package provided types for struct fields that modify
properties of the containing struct type such as memory layout. Not used yet.
The new Encode and
Decode functions of
encoding/binary package became byte slice equivalents to
Read and Write. Also Append allowed marshaling multiple data into the same byte slice.
Etc.
Go v1.22
Released on 2024-02-06.
Already used features of Go v1.22
The most importantly, for loop creates a new variable for each iteration, so accidental sharing bugs are avoided
(aka trying to save pointers into slice for all iterated values will not produce a slice of pointers all pointing
to the only one variable with value from the very last iteration). Also go vet was aligned to this.
I almost immediately, started using for loops ranging over integers (e.g. for range b.N { ... }) not just
in my new benchmarks.
go get could not be used outside a module anymore.
Printing of coverage summaries for packages without own test files on go test -cover is something one might
notice (e.g. mymod/mypack coverage: 0.0% of statements).
Not yet used interesting features of Go v1.22
Enhanced routing patterns used by net/http.ServeMux:
- registering
"POST /items/create"to restrict invocation method (mind that"GET"method also registers for"HEAD"method) - Wildcards in patterns, like
/items/{id}, match segments of the URL path. The actual segment value may be accessed by calling theRequest.PathValuemethod. - A wildcard ending in
..., like/files/{path...}, must occur at the end of a pattern and matches all the remaining segments. - A pattern that ends in
/matches all paths that have it as a prefix, as always. - To match the exact pattern including the trailing slash, end it with
{$}, as in/exact/match/{$}. - If two patterns overlap in the requests that they match, then the more specific pattern takes precedence. If neither is more specific, the patterns conflict. This rule generalizes the original precedence rules and maintains the property that the order in which patterns are registered does not matter.
Vendor directory for workspaces was not used as I am not usually using Go workspaces.
I did not notice that vet complained on slice = append(slice), nor defer log.Println(time.Since(t))
(equivalent of tmp := time.Since(t); defer log.Println(tmp)), nor warnings for mismatched key-value pairs
in log/slog calls.
I did not use math/rand/v2 even though it brought many changes.
Perhaps, one might change this…
Also, I did not face a brand-new package of go/version.
The Null[T] generic type of
database/sql provided a way to scan nullable columns
for any column types.
Etc.
Go v1.21
Released on 2023-08-08.
Already used features of Go v1.21
New built-ins min and max for searching minimum, resp. maximum, value of the given varargs.
Well, that one is not that much useful. Nevertheless, usage of clear is incomparably more
useful either for deletion of all key-value pairs from a map, or for zeroing all elements of a slice
(be careful about that much difference of semantics between the different supported argument types).
As far as I know, usage of init functions to initialize package requirements is discouraged,
as it brings something one might see as way to inject a kind of hidden behavior. Since v1.21,
package initialization order is specified in a more accurate way. The algorithm is following:
- Sort all packages by import path.
- If package list is empty, finish. Otherwise, continue.
- Find the first fully initialized package.
- Initialize that package.
- Remove that package from the list.
- Skip back to the step 2. This reminds me rules of Python’s MRO (aka Method Resolution Order) algorithm.
Improvement in type inference — that hit more deeply also generics — are taken for granted.
Introduced log/slog brought already sufficient logger.
I am still missing some features, but I am trying
to use algorithms provided by slices
and maps packages supporting the basic building blocks of Go.
From package cmp, I have so far used just
Ordered type constraint for a few generic methods.
Just in my small training projects, I found use of functions OnceFunc
and OnceValue
of sync standard package.
However, I might use them more often to help with common lazy initialization use cases.
Extension of context has some useful functions.
To get a context that does not get cancelled on cancelling its parent context might be used
WithoutCancel. One can register a function
to execute after a context has been cancelled via AfterFunc.
Other than that, Background-based and TODO-based contexts might be considered equal.
Not yet used interesting features of Go v1.21
Correct reported error of Go methods on receiver of C type in files that import "C".
Package testing/slogtest for validation of
slog.Handler implementations is something I might give a try.
And to name a few interesting bits:
errors.ErrUnsupported to denote unsupported operations,
encoding/binary.NativeEndian for smart conversions,
math/big.Int.Float64 to get the nearest FP value to the given
multi-precision integer together with indication of rounding error, etc.
Go v1.20
Released on 2023-02-01.
Already used features of Go v1.20
Wrapping of multiple errors using fmt.Errorf with %w verb.
Functions errors.Is and errors.As were extended accordingly. An error can wrap multiple errors
by implementing Unwrap() []error method. Also errors.Join
appeared to return an error wrapping a list of errors.
Package runtime/metrics extended a list of supported
metrics. Time-based histogram metrics are since then less precise, but take up much less memory.
Not yet used interesting features of Go v1.20
Simple conversion from a slice to an array, so [4]byte(slice) (instead of *(*[4]byte)(slice)).
Extended unsafe package with stuff like SliceData, String,
and StringData.
Packages bytes and strings
provides new CutPrefix and CutSuffix functions similar to TrimPrefix and TrimSuffix but also report
whether the value was trimmed.
And to name a few interesting bits:
context.WithCancelCause to cancel context with the given
error and context.Cause to retrieve that error,
a few new methods for atomic updates of sync.Map type
Go v1.19
Released on 2022-08-02.
Already used features of Go v1.19
I used at least some of new atomics types like sync/atomic.Uint64
or sync/atomic.Pointer.
Then time.Duration.Abs is one of methods I have already experience
with.
And I was definitely using pattern-defeating quicksort algorithm introduced by
the sort package in Go v1.19.
Not yet used interesting features of Go v1.19
To be honest, nothing particular seemed important enough to deserve some study time of mine.
Go v1.18
Released on 2022-03-19.
My first production-grade experience with Go and I already might use generics (so to include type parameters
for function and type definitions). And slowly I used experimental packages golang.org/x/exp/slices
and golang.org/x/exp/maps.