4

Chris's Wiki :: blog/programming/Go122ReflectTypeFor

 1 year ago
source link: https://utcc.utoronto.ca/~cks/space/blog/programming/Go122ReflectTypeFor
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK