-
Notifications
You must be signed in to change notification settings - Fork 0
/
defer.go
169 lines (149 loc) · 5.2 KB
/
defer.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package vweb
import(
"reflect"
"github.com/456vv/verror"
"sync"
)
//ExecCall 执行函数
type ExecCall struct {
fun reflect.Value // 函数
arg []reflect.Value // 参数
argVariadic bool // 有可变参数
}
func (T *ExecCall) Func(call interface{}, args ... interface{}) error {
var (
fn reflect.Value
ft reflect.Type
fnInLen int
argLen int = len(args)
variadic bool
)
if f, ok := call.(reflect.Value); ok {
fn = f
}else{
fn = reflect.ValueOf(call)
}
fvdirect := inDirect(fn)
if fvdirect.Kind() != reflect.Func {
return verror.TrackErrorf("vweb: 第一个参数不是有效的func,错误的func类型为 %s。", fvdirect.Kind())
}
if fvdirect.IsNil() {
return verror.TrackErrorf("vweb: 该函数 %s 还没被初始化,不可以使用!", fn.Type().Name())
}
ft = fvdirect.Type()
fnInLen = ft.NumIn()
variadic = ft.IsVariadic()
fnargLen := fnInLen - argLen
if (!variadic && fnInLen != argLen) ||
variadic && fnargLen != 1 && fnInLen > argLen {
return verror.TrackErrorf("vweb: 传入的参数长度与调用函数参数不符合。调用函数参数长度为(%d),传入参数长度为(%d)。", fnInLen, argLen)
}
fnInLen = fnInLen-1 //函数参数-长度
var argIndex reflect.Type //函数参数-类型
var varArgs reflect.Value //创建一上存放可变参数slice
var typeErr bool
for index, arg := range args {
argv := reflect.ValueOf(&arg).Elem().Elem()
//限制参数数量
if index <= fnInLen {
argIndex = ft.In(index)
//防止无类型nil参数
if argv.Kind() == reflect.Invalid {
argv = reflect.New(argIndex).Elem()
}
//1,函数参数是接口
//2,类型相等
//3,类型可以转换
if argIndex.Kind() == reflect.Interface || argIndex.Kind() == argv.Kind() && argv.Type().ConvertibleTo(argIndex) {
//适用func(a interface{}, b ...interface{}) => call(interface{}, []interface{})
T.arg = append(T.arg, argv)//argv.Elem() 是将参数 interface{} 转为 原类型
continue
}
//最后一个是切片
if index == fnInLen && variadic && (argIndex.Elem().Kind() == reflect.Interface || argv.Type().ConvertibleTo(argIndex.Elem())) {
//适用func(a interface{}, b ...interface{}) => call(interface{}, interface{})
varArgs = reflect.MakeSlice(argIndex, 0, 0)
varArgs = reflect.Append(varArgs, argv)
continue
}
//参数类型不匹配
typeErr = true
}
//可变参数+1...
if !typeErr {
if varArgs.Kind() != reflect.Invalid {
if argIndex.Elem().Kind() == reflect.Interface || (argIndex.Elem().Kind() == argv.Kind() && argv.Type().ConvertibleTo(argIndex.Elem())) {
//适用func(a interface{}, b ...interface{}) => call(interface{}, interface{}, interface{})
varArgs = reflect.Append(varArgs, argv)
continue
}
}
typeErr = true
}
if typeErr {
return verror.TrackErrorf("vweb: 传入参数类型与调用函数参数类型不符,第(%d)个参数,函数参数类型为(%s),传入类型为(%s)。", index+1, argIndex.Kind(), argv.Kind())
}
}
//调用没有传入可变参数
if variadic {
//1,函数参数-输入参数=1,表示没有设置可变参数
//2,判断 varArgs 上面没有初始化,否则创建一个空的可变参数
if (ft.NumIn()-argLen) == 1 && varArgs.Kind() == reflect.Invalid {
varArgs = reflect.MakeSlice(ft.In(fnInLen), 0, 0)
}
//1,仅对有效 varArgs 追加
if varArgs.Kind() != reflect.Invalid {
T.arg = append(T.arg, varArgs)
}
}
T.fun = fn
T.argVariadic = variadic
return nil
}
func (T *ExecCall) Exec() (ret []interface{}) {
var rvs []reflect.Value
if T.argVariadic {
rvs = T.fun.CallSlice(T.arg)
}else{
rvs = T.fun.Call(T.arg)
}
if len(rvs) == 0 {
return nil
}
for _, rv := range rvs {
ret = append(ret, typeSelect(rv))
}
return
}
//ExitCall 过期函数
type ExitCall struct {
// 记录每个用户的函数,会话超时后关闭打开的对象
efs []*ExecCall
m sync.Mutex
}
// Defer 在用户会话时间过期后,将被调用。
// call interface{} 函数
// args ... interface{} 参数或更多个函数是函数的参数
// error 错误
// 例:
// .Defer(fmt.Println, "1", "2")
// .Defer(fmt.Printf, "%s", "汉字")
func (T *ExitCall) Defer(call interface{}, args ... interface{}) error {
T.m.Lock()
defer T.m.Unlock()
df := new(ExecCall)
if err := df.Func(call, args...); err != nil {
return err
}
T.efs = append(T.efs, df)
return nil
}
//Free 执行结束Defer
func (T *ExitCall) Free() {
T.m.Lock()
defer T.m.Unlock()
for i:=len(T.efs)-1; i>=0; i-- {
T.efs[i].Exec()
}
T.efs = nil
}