Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
func (s *service) registerMethods() {
s.method = make(map[string]*methodType)
for i := 0; i < s.typ.NumMethod(); i++ {
method := s.typ.Method(i)
mType := method.Type
if mType.NumIn() != 3 || mType.NumOut() != 1 {
continue
if mType.Out(0) != reflect.TypeOf((*error)(nil)).Elem() {
continue
argType, replyType := mType.In(1), mType.In(2)
if !isExportedOrBuiltinType(argType) || !isExportedOrBuiltinType(replyType) {
continue
s.method[method.Name] = &methodType{
method: method,
ArgType: argType,
ReplyType: replyType,
log.Printf("rpc server: register %s.%s\n", s.name, method.Name)
what does reflect.TypeOf((*error)(nil)).Elem()
mean in this code? I know if mType.Out(0) != reflect.TypeOf((*error)(nil)).Elem()
is trying to determine if the method's return type is error not not. But for me, reflect.TypeOf((error)(nil))
intuitively will do the same, but unfortunately not. When I try to compile this code, it says type error is not an expression, what does it mean in this context? Does not reflect.Typeof()
accepts a argument of certain type? I found that (*error)(nil) is equivalent to *error = nil. I am confused with this expression.
TL;DR; reflect.TypeOf((*error)(nil)).Elem()
is an expression used to obtain the reflect.Type
type descriptor of the interface type error
. Using reflect.TypeOf(error(nil))
cannot be used for the same purpose (read the why below).
reflect.TypeOf((*error)(nil)).Elem()
achieves its goal by using a typed nil
pointer value of type *error
, passing it to reflect.TypeOf()
to get the reflect.Type
descriptor of the type *error
, and uses Type.Elem()
to get the type descriptor of the element (base) type of *error
, which is error
.
reflect.TypeOf()
expects an interface{}
value:
func TypeOf(i interface{}) Type
Basically whatever value you pass to reflect.TypeOf()
, if it's not already an interface value, it will be wrapped in an interface{}
implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed as interface{}
.
So if you try to pass an error
value to it, since error
is an interface type, the concrete value stored in it will be "repacked" into an interface{}
value. The interface type error
will not be retained / transferred!
If you pass a nil
value of type error
, e.g. error(nil)
, since the interface value itself is nil
, it contains no concrete value and type, a nil
interface{}
value will be passed, that will result in nil
reflect.Type
returned. Quoting from reflect.TypeOf()
:
TypeOf returns the reflection Type that represents the dynamic type of i. If i is a nil interface value, TypeOf returns nil.
If you pass a value of type *error
(which may be a nil
pointer), it's not an interface value, it's a pointer value (a pointer to interface). So it will be wrapped in an interface{}
value, and the concrete value stored in it will be of type *error
. Using Type.Elem()
you can access the pointed type, that is error
.
This is one of the rare cases when using a pointer to interface makes sense, and in fact inevitable.
See related questions:
Get the reflect.Kind of a type which is based on a primitive type
What is the difference between reflect.ValueOf() and Value.Elem() in go?
Hiding nil values, understanding why golang fails here
–
–
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.