2023-08-28
Go 1.22's (likely) new reflect.TypeFor()
generic function
I'm always interested to see what the Go developers are doing with
generic types in the standard library. One such development I've
noticed recently is a new generic function in the 'reflect' package,
reflect.TypeFor()
;
this will likely appear as part of Go 1.22. What TypeFor() does is
relatively straightforward; it returns the reflect.Type
of its type, which you can
then use either for further reflection or to compare it to some
other type (which you will likely have obtained through reflection).
The reflect package already had a
reflect.TypeOf()
function,
but because it wasn't generic the usage was more awkward. A good
example of how the change improves the readability is in
net/rpc/server.go,
where net/rpc needs to check to see
if a method returns an error
, which requires knowing the type of
'error
' for reflection purposes. The old code to do this with
TypeOf() was:
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
The new code using TypeFor() is simpler and more obvious:
var typeOfError = reflect.TypeFor[error]()
The old code is awkward partly because of interfaces. Because
reflect.TypeOf()
is passed an 'interface{}
' (these days also
known as 'any
'), it can't directly give you the reflect.Type
of an interface, because that interface type will be lost when it's
converted to 'interface{}
'. Instead reflect.TypeOf()
returns
the underlying non-interface type (or nil). As we've seen in the
context of 'nil
' being only sort of typed,
to get around this you must pass a pointer to the interface (well,
a value of the interface), get back the type 'pointer to <some
interface type>', and then dereference
to the original type through reflect
again, which is what the
original code is doing.
You might reasonably wonder how reflect.TypeFor()
works, and if
it has some special internal trick to access the type of interface
types. The answer turns out to be no. In fact the current version
in reflect/type.go is
simply what the TypeOf()
version was doing, generalized:
func TypeFor[T any]() Type { return TypeOf((*T)(nil)).Elem() }
In Go, sometimes there is no trick, even in the reflect
package.
Link: quoting strings and breaking strings across multiple lines in YAML
This StackOverflow answer (alternate link) is an excellent, readable, all in one place answer to the twin questions of how you quote strings in YAML and how you break them across multiple lines. I learned something new about quoting strings from reading it, and I'm definitely going to want this link for future reference the next time I have something complicated to put in YAML. I'm also probably going to use '...' quoting more now that I know how simple it is to quote any stray 's I want in it.