-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunc.go
109 lines (102 loc) · 2.19 KB
/
func.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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package www
import (
"fmt"
"reflect"
"github.com/gin-gonic/gin"
)
type Func struct {
inLen int
in *reflect.Type
inIn int
ctx int
ginCtx bool
out *reflect.Type
InterfaceMap gin.H
outLen int
outErr bool
v reflect.Value
}
func (f Func) Call(ctx *Context) (interface{}, error) {
var ins = make([]reflect.Value, f.inLen)
if f.ctx >= 0 {
if f.ginCtx {
ins[f.ctx] = reflect.ValueOf(ctx.Context)
} else {
ins[f.ctx] = reflect.ValueOf(ctx)
}
}
if f.inIn >= 0 {
newIn := reflect.New(*f.in)
err := ctx.Bind(newIn.Interface())
if err != nil {
return nil, err
}
ins[f.inIn] = newIn.Elem()
}
out := f.v.Call(ins)
if len(out) == 2 {
return out[0].Interface(), out[1].Interface().(error)
}
if len(out) == 1 {
return out[0].Interface(), nil
}
return nil, nil
}
func NewFunc(f interface{}) *Func {
check(f)
fff := &Func{ctx: -1, inIn: -1}
fv := reflect.ValueOf(f)
ft := fv.Type()
for i := 0; i < ft.NumIn(); i++ {
in := ft.In(i)
for in.Kind() == reflect.Ptr {
in = in.Elem()
}
fmt.Println("in.PkgPath()", in.PkgPath())
if in.Name() == "Context" {
if in.PkgPath() == "github.com/ltto/T/www" {
fff.ctx = i
continue
} else if in.PkgPath() == "github.com/gin-gonic/gin" {
fff.ctx = i
fff.ginCtx = true
continue
}
}
fff.inIn = i
fff.in = &in
}
for i := 0; i < ft.NumOut(); i++ {
out := ft.Out(i)
if ft.Out(i).PkgPath() == "" && ft.Out(i).String() == "error" {
fff.outErr = true
} else {
fff.out = &out
}
}
fff.v = reflect.ValueOf(f)
fff.inLen = ft.NumIn()
fff.outLen = ft.NumOut()
return fff
}
func check(f interface{}) {
fv := reflect.ValueOf(f)
ft := fv.Type()
if fv.Kind() != reflect.Func || ft.NumIn() > 2 || ft.NumOut() > 2 {
panic("need func in<=2 out<=2")
}
for i := 0; i < ft.NumIn(); i++ {
in := ft.In(i)
if in.Kind() == reflect.Ptr {
in = in.Elem()
}
if in.Kind() != reflect.Struct && in.String() != "echo.Context" {
panic("param need struct or echo.Context")
}
}
if ft.NumOut() == 2 {
if !(ft.Out(1).PkgPath() == "" && ft.Out(1).String() == "error") {
panic("如果2个返回值 最后一个必须为error")
}
}
}