Go 1.18 was [just released](https://go.dev/blog/go1.18), bringing with it generics, fuzzing, and workspaces. Those are major features people have been asking about for years, but my last post about the [minor features of Go 1.18](/post/2021/golang-118-minor-features/) was an unexpected hit, so I'm following up on popular demand by bring you three _even more minor_ features of Go. Get excited for some very small improvements to Go! ## 1. The `any` type Okay, so I lied, this one is kind of a headlining feature, although it is also quite minor in terms of implementation. In Go, the universal type has been traditionally written as `interface{}`, as in `json.Unmarshal(data []byte, v interface{}) error`. Since [the introduction of type aliases in Go 1.9](https://go.dev/doc/go1.9), it has been possible to write your own local alias for this to save typing, such as `type jsonvalue = interface{}`. This was never idiomatic though because `interface{}` was the standard name, and there was no good reason to just make up your own name for it. In Go 1.18, however, `type any = interface{}` has been added to the predeclared identifiers list to make it easier to write out generics (every generic type needs an interface metatype, which in most case is just `interface{}`, and writing this out takes a lot of space). Now you can use it anywhere you would use `interface{}`, even non-generic code. If nothing else, it's easier to type a n y than to create curly braces with shift-[ shift-] on a US keyboard, and God knows what combination of keys on various European keyboards. ## 2. `log.Logger` optimizes for `io.Discard` To make up for the last feature being well known, this feature is so minor, it is not even mentioned in the release notes! The story is that there was [a Github issue](https://github.com/golang/go/issues/47164) about making ignoring log messages more efficient and it was decided to specially test for `io.Discard` and short-circuit the logging to ensure that [there are no extra allocations](https://github.com/golang/go/blob/db3045b4be5b91cd42c3387dc550c89bbc2f7fb4/src/log/log_test.go#L183-L192). Now when you can switch off `log.Logger` by setting output to `io.Discard` and pay less of a price for calling it. ## 3. `bufio.Writer.AvailableBuffer()` In Go, you can think about there being three ways of handling bytes of data or text. The normal way is to use strings. Strings are very convenient to use, but because they are immutable, they can put pressure on the garbage collector to keep track of their creation and freeing. To reach a higher level of efficiency, you can instead use the `io.Reader` and `io.Writer` interfaces to work with copies of bytes through smaller buffer sized windows as though working with a file-like object. This is an extremely powerful idiom and makes it possible to glue together bits of Go code like Unix pipes. It is, however, less convenient than working with strings on the one hand, and still not maximally efficient on the other. Finally, the lowest level idiom for manipulating bytes is the "AppendX" idiom. You can see this used at various places in the standard library, like [`strconv.AppendInt(dst []byte, i int, base int) []byte`](https://pkg.go.dev/strconv#AppendInt). In this idiom, instead of just using an immutable string or using a byte slice to copy to and from file-like objects, there is a slice of bytes _with an existing excess capacity_ and the desired data gets appended to that byte slice. Go 1.18 actually introduces another AppendX function, `unicode/utf8.AppendRune`, and there are some new `fmt.Append` functions [planned for Go 1.19](https://github.com/golang/go/issues/47579). Go 1.18 adds the `bufio.Writer.AvailableBuffer()` method to the standard library to make working efficiently with these byte slices more convenient. The docs give this example: ```go w := bufio.NewWriter(os.Stdout) for _, i := range []int64{1, 2, 3, 4} { b := w.AvailableBuffer() b = strconv.AppendInt(b, i, 10) b = append(b, ' ') w.Write(b) } w.Flush() ``` In this case, the user borrows a buffer from the `bufio.Writer`, appends some data into it, and the copies that into the underlying `io.Writer` (which in this case is stdout). This makes it possible to do very low level text wrangling without allocating memory, and makes using the AppendX idiom about as convenient as using a normal `io.Writer`. - - - - So, what are your favorite features of Go 1.18 that won't make headlines? Sound off in the comments or on Twitter.