What I worked on for Go 1.21
Go 1.21 has been released! For past releases, I wrote up my notes on what’s new in Go 1.18 (part 1, part 2), 1.19, and 1.20 (part 1, part 2, part 3), but I thought I would sit this round of blogging out, in part because there have been some good roundups of what’s new elsewhere already, and in part because I’ve been on family vacation until recently and haven’t had time to write much. However, I didn’t want to let 1.21 go totally by without talking about what I contributed, because if I don’t talk up my own contributions, who else will?
The background to the first thing I worked on is that @fnxpt on Github proposed adding a variation on flag.Func to the flag package that would work even without an argument.
To review, the flag package parses command line flags, like myprogram -verbose -input file.txt -output out.txt
. Some flags have arguments (like -input file.txt
or -output out.txt
) and some do not (like -verbose
). The flag package makes it pretty fast and easy to whip up a simple command line application that reads in flags. The flag.Func
method lets you add a callback that gets called whenever a certain flag is present on the command line. For example, if -input
were configued by flag.Func
, it might add a callback that would use os.Open
on whatever argument is after -input
.
I had previously proposed and implemented flag.Func and had written my own flagx.BoolFunc in my personal flag utilities library, so when I saw that the proposal for flag.BoolFunc had been approved, I went ahead and did the implementation.
It works like this:
flag.BoolFunc("log", "logs a dummy message", func(s string) error {
fmt.Println("dummy message:", s)
return nil
})
$ myprogram -log
dummy message: true
$ myprogram -log=0
dummy message: 0
Simple enough, but someone had to write it, so why not me? 😉
Second, I want to talk about a featured that I helped keep out of Go.
During the planning for adding generics to Go, it was proposed that there should be a constraints package to contain common generic type constraints, like Ordered
or Numeric
. The main sticking point for the package was the name. No one really loved the name “constraints” because it is too long. (Perhaps call it c8s?) Other names were proposed, but in the end, the decision was made to just move the constraints package out of the standard library and into golang.org/x/exp to get experience using it before it was added into the standard library itself.
Then after Go 1.18 came out, I made my own counterproposal:
Most of the remaining constraints after #48424 [a pre-generics proposal that made constraints shorter to type] are purely numeric: Complex, Float, Integer, Signed, Unsigned. They can all just be added to package math. Ordered is the exception because it also involves strings. It can be added to package sort. There’s no longer any need for a top level constraints package.
Well, my proposal wasn’t quite accepted as is, but I feel like I won the war because with Go 1.21 it’s clear: There’s no longer any need for a top level constraints package.
Go 1.21 adds a slices package and slices has slices.Sort
, which in the exp version required constraints.Ordered. For the standard library, however, slices.Sort
relies on cmp.Ordered in the brand new cmp package (not quite sort.Ordered
, as I had proposed, but close enough).
The numeric constraints haven’t been added anywhere in the standard library yet, but it’s clear that even if they do, it won’t be in a package called “constraints”.
There’s a longstanding rule of thumb in Go to avoid utility packages:
These packages contain an assortment of unrelated functions, as such their utility is hard to describe in terms of what the package provides. This often leads to a package’s name being derived from what the package contains—utilities.
The proposed constraints package was going to be a utility package for type constraints: it contained type constraints, but there was no unity to the constraints it contained. The only thing all the constraints did that was the related was constraining generic types. I wrote in my issue, “‘Constraints’ is like ‘utils’ but for types. It’s better to have something specific than a bunch of general stuff crammed in one place.”
Now the Go standard library has avoided adding it, and I’m going to take a least partial credit. 😉
So, that’s what I worked on for this cycle: one addition and one non-addition. Please, enjoy using Go 1.21 with more func and without constraints.