in pkg/util/reflect.go [59:122]
func (r *Reflector) Load(obj interface{}) *ReflectObject {
r.mux.RLock()
itab := *(**uintptr)(unsafe.Pointer(&obj))
t, ok := r.types[itab]
r.mux.RUnlock()
if ok {
return t
}
r.mux.Lock()
t, ok = r.types[itab]
if ok {
r.mux.Unlock()
return t
}
t = new(ReflectObject)
v := reflect.ValueOf(obj)
if !v.IsValid() {
r.mux.Unlock()
return unknown
}
switch v.Kind() {
case reflect.Ptr:
fallthrough
case reflect.Interface:
r.mux.Unlock()
if v.IsNil() {
return unknown
}
e := v.Elem()
if e.CanInterface() {
return r.Load(e.Interface())
}
return unknown
default:
t.Type = reflect.TypeOf(obj)
switch v.Kind() {
case reflect.Func:
r.mux.Unlock()
f := runtime.FuncForPC(v.Pointer())
if f == nil {
return unknown
}
t.FullName = f.Name()
return t
case reflect.Struct:
if fl := t.Type.NumField(); fl > 0 {
t.Fields = make([]reflect.StructField, fl)
for i := 0; i < fl; i++ {
f := t.Type.Field(i)
t.Fields[i] = f
}
}
fallthrough
default:
t.FullName = t.Type.PkgPath() + "." + t.Type.Name()
}
}
r.types[itab] = t
r.mux.Unlock()
return t
}