-
Notifications
You must be signed in to change notification settings - Fork 13
/
inspect.go
63 lines (54 loc) · 1.36 KB
/
inspect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package di
import (
"fmt"
"reflect"
"runtime"
)
// Func is a function description.
type function struct {
Name string
reflect.Type
reflect.Value
}
var errorInterface = reflect.TypeOf(new(error)).Elem()
// isError checks that typ have error signature.
func isError(typ reflect.Type) bool {
return typ.Implements(errorInterface)
}
// isCleanup checks that typ have cleanup signature.
func isCleanup(typ reflect.Type) bool {
return typ.Kind() == reflect.Func && typ.NumIn() == 0 && typ.NumOut() == 0
}
// InspectFunc inspects function.
func inspectFunction(fn interface{}) (function, bool) {
if reflect.ValueOf(fn).Kind() != reflect.Func {
return function{}, false
}
val := reflect.ValueOf(fn)
typ := val.Type()
funcForPC := runtime.FuncForPC(val.Pointer())
return function{
Name: funcForPC.Name(),
Type: typ,
Value: val,
}, true
}
// Interface is a interface description.
type link struct {
Name string
Type reflect.Type
}
// inspectInterfacePointer inspects interface pointer.
func inspectInterfacePointer(i interface{}) (*link, error) {
if i == nil {
return nil, fmt.Errorf("nil: not a pointer to interface")
}
typ := reflect.TypeOf(i)
if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Interface {
return nil, fmt.Errorf("%s: not a pointer to interface", typ)
}
return &link{
Name: typ.Elem().Name(),
Type: typ.Elem(),
}, nil
}