Go语言 reflect.TypeOf((*error)(nil)).Elem()`是什么意思?

cu6pst1q  于 2023-06-03  发布在  Go
关注(0)|答案(1)|浏览(107)
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)
    }
}

reflect.TypeOf((*error)(nil)).Elem()在这段代码中是什么意思?我知道if mType.Out(0) != reflect.TypeOf((*error)(nil)).Elem()正在尝试确定方法的返回类型是否为error而不是not。但对我来说,reflect.TypeOf((error)(nil))直观上也会做同样的事情,但不幸的是不会。当我试着编译这段代码时,它说类型错误不是一个表达式,在这个上下文中它是什么意思?reflect.Typeof()不接受某种类型的参数吗?我发现(*error)(nil)等价于 *error = nil。我对这种表达感到困惑。

tct7dpnv

tct7dpnv1#

TL;DR;reflect.TypeOf((*error)(nil)).Elem()是用于获取接口类型errorreflect.Type类型描述符的表达式。使用reflect.TypeOf(error(nil))不能用于相同的目的(阅读下面的 * 为什么 *)。

reflect.TypeOf((*error)(nil)).Elem()通过使用类型为*error的类型化nil指针值来实现其目标,将其传递给reflect.TypeOf()以获取类型为*errorreflect.Type描述符,并使用Type.Elem()获取*error的元素(基)类型的类型描述符,即error
reflect.TypeOf()需要interface{}值:

func TypeOf(i interface{}) Type

基本上,无论你传递给reflect.TypeOf()的值是什么,如果它还不是一个接口值,它都会隐式地 Package 在interface{}中。如果传递的值已经是一个接口值,那么存储在其中的具体值将作为interface{}传递。
因此,如果您尝试向它传递error值,由于error是一种接口类型,因此存储在其中的具体值将被“重新打包”为interface{}值。接口类型error将不会被保留/转移!
如果传递一个error类型的nil值,例如error(nil),由于接口值本身是nil,它不包含具体的值和类型,将传递nilinterface{}值,这将导致返回nilreflect.Type。引用自reflect.TypeOf()
TypeOf返回表示i的动态类型的反射Type。如果i是nil接口值,TypeOf返回nil。
如果你传递一个*error类型的值(可能是一个nil指针),它不是一个接口值,而是一个指针值(指向接口的指针)。因此它将被 Package 在一个interface{}值中,并且存储在其中的具体值将是*error类型。使用Type.Elem()可以访问指向的类型,即error
这是使用指向接口的指针有意义的罕见情况之一,实际上是不可避免的。
参见相关问题:
获取基于基元类型的类型的reflect
go中的reflect.ValueOf()和Value.Elem()有什么区别?
隐藏nil值,理解为什么golang在这里失败

相关问题