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 thereflect.Typetype descriptor of the interface typeerror. Usingreflect.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 typednilpointer value of type*error, passing it toreflect.TypeOf()to get thereflect.Typedescriptor of the type*error, and usesType.Elem()to get the type descriptor of the element (base) type of*error, which iserror.reflect.TypeOf()expects aninterface{}value:Basically whatever value you pass to
reflect.TypeOf(), if it's not already an interface value, it will be wrapped in aninterface{}implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed asinterface{}.So if you try to pass an
errorvalue to it, sinceerroris an interface type, the concrete value stored in it will be "repacked" into aninterface{}value. The interface typeerrorwill not be retained / transferred!If you pass a
nilvalue of typeerror, e.g.error(nil), since the interface value itself isnil, it contains no concrete value and type, anilinterface{}value will be passed, that will result innilreflect.Typereturned. Quoting fromreflect.TypeOf():If you pass a value of type
*error(which may be anilpointer), it's not an interface value, it's a pointer value (a pointer to interface). So it will be wrapped in aninterface{}value, and the concrete value stored in it will be of type*error. UsingType.Elem()you can access the pointed type, that iserror.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