Go 1.22's (likely) new reflect.TypeFor() generic function

August 28, 2023

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.

Written on 28 August 2023.
« Link: quoting strings and breaking strings across multiple lines in YAML
Experiencing the increase in web bandwidth usage for myself »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Mon Aug 28 22:41:16 2023
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.