数据结构概览

gengine-data-context

1
2
3
4
5
type DataContext struct {
	lockVars sync.Mutex               // 对外部送进来的vars进行加锁
	lockBase sync.Mutex               // 对下面一行的`base`字段加锁
	base     map[string]reflect.Value // 存储各种类型的值, key是变量名, value是变量值, 变量值可以是任意类型, 例如:函数
}

上下文数据的增删查改

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// 在base中添加一条数据,并将obj转换为reflect.Value类型
// 会使用localBase
func (dc *DataContext) Add(key string, obj interface{})
// 批量删除base中的数据
// 会使用localBase
func (dc *DataContext) Del(key string)
// load一个动态库,并将动态库中提供给外部的接口全部写入base中
// 会使用localBase
func (dc *DataContext) PluginLoader(absolutePathOfSO string) (string, plugin.Symbol, error)
// 通过一个key查询到相关的数据
// 如无数据,会返回一个Not Found key: $key的错误
// 会使用localBase
func (dc *DataContext) Get(key string) (reflect.Value, error)

以上函数提供了DataContext对任何数据存储的能力,不论是基础类型,还是自定义类型,亦或者是一个函数都可以存储到DataContext中,但在DataContext中无法断定,最终的使用是读多写少,所以使用了一个互斥锁

执行(Exec)函数族

执行函数(ExecFunc)

 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
/**
execute the injected functions: a(..)
function execute supply multi return values, but simplify ,just return one value
*/
func (dc *DataContext) ExecFunc(Vars map[string]reflect.Value, funcName string, parameters []reflect.Value) (reflect.Value, error) {
    // 使用localBase互斥锁,从DataContext取到函数名(funcName)对应值,取完数据后,立即释放互斥锁(localBase)
	dc.lockBase.Lock()
	v, ok := dc.base[funcName]
	dc.lockBase.Unlock()

    // 检查是否从DataContext获取到函数名称对应的函数
    // 如果获取到函数,执行并返回结果
	if ok {
		args := core.ParamsTypeChange(v, parameters)
		res := v.Call(args)
		raw, e := core.GetRawTypeValue(res)
		if e != nil {
			return reflect.ValueOf(nil), e
		}
		return raw, nil
	}

    // 使用localVars互斥锁,从Vars中获取到函数名对应的函数,取完数据后,立即释放互斥锁(localVars)
	dc.lockVars.Lock()
	vv, vok := Vars[funcName]
	dc.lockVars.Unlock()
	// 检查是否从Vars获取到函数名称对应的函数
    // 如果获取到函数,执行并返回结果
	if vok {
		args := core.ParamsTypeChange(vv, parameters)
		res := vv.Call(args)
		raw, e := core.GetRawTypeValue(res)
		if e != nil {
			return reflect.ValueOf(nil), e
		}
		return raw, nil
	}
	return reflect.ValueOf(nil), errors.New(fmt.Sprintf("NOT FOUND function \"%s(..)\"", funcName))
}

ExecFunc是gengine用来执行用户预定义的函数,还有用户在rule代码中自己构造的函数,但是并没有实现go中的多值返回,只返回了第一个参数。从函数逻辑来看,是先从用户预定义的函数中找到想要执行的函数,然后再从Vars里面找到需要的函数执行,所以优先级是:先用户预定义的函数,再是Vars。我理解的Vars是当前执行环境的上下文,感觉Vars带有的信息更加局部,所以应该先执行,且行且看吧,答案在整个流程中。

执行结构体方法(ExecMethod)

 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
/**
execute the struct's functions: a.b(..)
function execute supply multi return values, but simplify ,just return one value
*/
func (dc *DataContext) ExecMethod(Vars map[string]reflect.Value, methodName string, args []reflect.Value) (reflect.Value, error) {
    // 分解字符串,按照“.”分割,第一个是strcut实例的名称,第二个是struct method的名称
	structAndMethod := strings.Split(methodName, ".")

    // 如果长度不为2,那说明这个语句有问题,也就是说,不是按照a.b的格式
	if len(structAndMethod) != 2 {
		return reflect.ValueOf(nil), errors.New(fmt.Sprintf("Not supported call \"%s(..)\", just support struct.method call, now length is %d", methodName, len(structAndMethod)))
	}

	a := structAndMethod[0]
	b := structAndMethod[1]

    // 从DataContext中获取对应的struct实例
	dc.lockBase.Lock()
	v, ok := dc.base[a]
	dc.lockBase.Unlock()

    // 执行实例对应的方法
	if ok {
		res, err := core.InvokeFunction(v, b, args)
		if err != nil {
			return reflect.ValueOf(nil), err
		}
		return res, nil
	}

    // 从Vars中获取到对应的struct实例
	dc.lockVars.Lock()
	vv, vok := Vars[a]
	dc.lockVars.Unlock()
    // 执行实例对应的方法
	if vok {
		res, err := core.InvokeFunction(vv, b, args)
		if err != nil {
			return reflect.ValueOf(nil), err
		}
		return res, nil
	}
	return reflect.ValueOf(nil), errors.New(fmt.Sprintf("Not found method: \"%s(..)\"", methodName))
}

ExecMethod是gengine用来执行用户预定义对象的方法,还有用户在rule代码中自己构造的对象的方法,但是并没有实现go中的多值返回,只返回了第一个参数。并且和ExecFunc函数类型,都是先从DataContext里面取对象,取不到,再去Vars中获取。

三级函数调用(ExecThreeLevel)

 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
/**
execute the struct's functions: a.b.c(..)
function execute supply multi return values, but simplify ,just return one value
*/
func (dc *DataContext) ExecThreeLevel(Vars map[string]reflect.Value, threeLevelName string, args []reflect.Value) (reflect.Value, error) {
	structAndMethod := strings.Split(threeLevelName, ".")

	if len(structAndMethod) != 3 {
		return reflect.ValueOf(nil), errors.New(fmt.Sprintf("Not supported call \"%s(..)\", just support struct.field.method call, now length is %d", threeLevelName, len(structAndMethod)))
	}

	a := structAndMethod[0]
	b := structAndMethod[1]
	c := structAndMethod[2]

	dc.lockBase.Lock()
	v, ok := dc.base[a]
	dc.lockBase.Unlock()

	if ok {
		value, e := core.GetStructAttributeValue(v, b)
		if e != nil {
			return reflect.ValueOf(nil), e
		}

		res, err := core.InvokeFunction(value, c, args)
		if err != nil {
			return reflect.ValueOf(nil), err
		}
		return res, nil
	}

	dc.lockVars.Lock()
	vv, vok := Vars[structAndMethod[0]]
	dc.lockVars.Unlock()
	if vok {
		value, e := core.GetStructAttributeValue(vv, b)
		if e != nil {
			return reflect.ValueOf(nil), e
		}
		res, err := core.InvokeFunction(value, c, args)
		if err != nil {
			return reflect.ValueOf(nil), err
		}
		return res, nil
	}
	return reflect.ValueOf(nil), errors.New(fmt.Sprintf("Not found method: \"%s(..)\"", threeLevelName))
}

这个函数实现了gengine文档中描述的三级调用中的函数执行

1.当语法是C,或者a=C, 则C可以为具体值、变量、函数或方法、结构体(指针)、map、slice、array等, 具体的如 a=100, a = Mp["hello"], a = x, a = getMessage(p1,p2..)等  
2.当语法是A.C,或者a=A.C, 则A必须为结构体(指针), C同上, 具体如a = A.Mp["hello"], a = A.Field1, a = A.GetMessage(p1,p2..)等
3.当语法是A.B.C,或者a=A.B.C, 则A和B必须为结构体(指针),C同上, 具体如 a = A.B.Mp["hello"], a =A.B.Field1, a= A.B.GetMessage(p1, p2..)等

那么,如果语法为A.B.C时, A.Mp["hello"].C 这种语法是不合法的 

操作值(Get/Set)函数族

获取值(GetValue)

 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
/**
get the value user set
*/
func (dc *DataContext) GetValue(Vars map[string]reflect.Value, variable string) (reflect.Value, error) {
	if strings.Contains(variable, ".") {
        // 不允许超过三级调用的规则
		structAndField := strings.Split(variable, ".")
		if len(structAndField) > 3 {
			//a.b.c.d...
			return reflect.ValueOf(nil), errors.New(fmt.Sprintf("Not supported Field:%s , just support struct.field or struct.field.field, now length is %d", variable, len(structAndField)))
		}

		//a.b
        // 二级调用时,取数据的规则
		if len(structAndField) == 2 {
			a := structAndField[0]
			b := structAndField[1]

			dc.lockBase.Lock()
			v, ok := dc.base[a]
			dc.lockBase.Unlock()

			if ok {
				return core.GetStructAttributeValue(v, b)
			}

			//for return struct or struct ptr
			dc.lockVars.Lock()
			obj, ok := Vars[a]
			dc.lockVars.Unlock()
			if ok {
				return core.GetStructAttributeValue(obj, b)
			}
		}

		//a.b.c
        // 三级调用时,取数据的规则
		if len(structAndField) == 3 {
			a := structAndField[0]
			b := structAndField[1]
			c := structAndField[2]

			dc.lockBase.Lock()
			v, ok := dc.base[a]
			dc.lockBase.Unlock()
			if ok {
				value, e := core.GetStructAttributeValue(v, b)
				if e != nil {
					return reflect.ValueOf(nil), e
				}
				return core.GetStructAttributeValue(value, c)
			}

			dc.lockVars.Lock()
			obj, ok := Vars[a]
			dc.lockVars.Unlock()
			if ok {
				value, e := core.GetStructAttributeValue(obj, b)
				if e != nil {
					return reflect.ValueOf(nil), e
				}
				return core.GetStructAttributeValue(value, c)
			}
		}
	} else {
		//user set
		dc.lockBase.Lock()
		v, ok := dc.base[variable]
		dc.lockBase.Unlock()

		if ok {
			return v, nil
		}
		//in RuleEntity
		dc.lockVars.Lock()
		res, rok := Vars[variable]
		dc.lockVars.Unlock()
		if rok {
			return res, nil
		}

	}
	return reflect.ValueOf(nil), errors.New(fmt.Sprintf("Did not found variable : %s ", variable))
}

该函数只支持带“.”的数据获取,例如:a,a.b,a.b.c,但不支持map的操作,并且遵从了三级调用的规则

设置值(SetValue)

代码其余与GetValue差别不大,主要还是针对带“.”的操作,并且不支持map的操作,并且遵从了三级调用的规则

给Map的Key赋值(SetMapVarValue)

  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
func (dc *DataContext) SetMapVarValue(Vars map[string]reflect.Value, mapVarName, mapVarStrkey, mapVarVarkey string, mapVarIntkey int64, setValue reflect.Value) error {

	// 从上下文变量集合中获取map变量
	value, e := dc.GetValue(Vars, mapVarName)
	if e != nil {
		return e
	}

	if value.Kind() == reflect.Ptr { // mapVarsName对应的变量是指针时
		newValue := value.Elem()
		valueType := newValue.Type().Elem() // map对象中值的类型

		// 判断map变量是否是真的是map变量
		if newValue.Kind() == reflect.Map {
			keyType := newValue.Type().Key() // map的key类型
			if len(mapVarVarkey) > 0 {       // 取出mapVarVarkey对应的值
				key, e := dc.GetValue(Vars, mapVarVarkey)
				if e != nil {
					return e
				}
				wantedKey, e := core.GetWantedValue(key, keyType) // 获取key的真实值
				if e != nil {
					return e
				}

				wantedValue, e := core.GetWantedValue(setValue, valueType) // 获取value的真实值
				if e != nil {
					return e
				}
				value.Elem().SetMapIndex(wantedKey, wantedValue) // 将真实值设置到map中
				return nil
			}

			if len(mapVarStrkey) > 0 {
				wantedValue, e := core.GetWantedValue(setValue, valueType) // 获取value的真实值
				if e != nil {
					return e
				}
				value.Elem().SetMapIndex(reflect.ValueOf(mapVarStrkey), wantedValue) // 将真实值设置到map中
				return nil
			}

			//int key
			wantedKey, e := core.GetWantedValue(reflect.ValueOf(mapVarIntkey), keyType) // 获取key的真实值
			if e != nil {
				return e
			}
			wantedValue, e := core.GetWantedValue(setValue, valueType) // 获取value的真实值
			if e != nil {
				return e
			}
			value.Elem().SetMapIndex(wantedKey, wantedValue) // 将真实值设置到map中
			return nil
		}

		if newValue.Kind() == reflect.Slice || newValue.Kind() == reflect.Array { // map值如果是切片或数组
			if len(mapVarVarkey) > 0 {
				key, e := dc.GetValue(Vars, mapVarVarkey) // 取出mapVarVarkey对应的值
				if e != nil {
					return e
				}
				wantedValue, e := core.GetWantedValue(setValue, valueType) // 获取value的真实值
				if e != nil {
					return e
				}
				value.Elem().Index(int(key.Int())).Set(wantedValue) // 将真实值设置到map中
				return nil
			}

			if len(mapVarStrkey) > 0 {
				return errors.New(fmt.Sprintf("the index of array or slice should not be string, now is str \"%s\"", mapVarStrkey))
			}

			if mapVarIntkey >= 0 {
				wantedValue, e := core.GetWantedValue(setValue, valueType) // 获取value的真实值
				if e != nil {
					return e
				}
				value.Elem().Index(int(mapVarIntkey)).Set(wantedValue) // 将真实值设置到map中
				return nil
			} else {
				return errors.New("Slice or Array index  must be non-negative!")
			}
		}

	} else { // mapVarsName对应的变量是非指针时, 以下逻辑和上面的逻辑几乎一样
		newValue := value
		valueType := newValue.Type().Elem()

		if newValue.Kind() == reflect.Map {
			keyType := newValue.Type().Key()
			if len(mapVarVarkey) > 0 {
				key, e := dc.GetValue(Vars, mapVarVarkey)
				if e != nil {
					return e
				}
				wantedKey, e := core.GetWantedValue(key, keyType)
				if e != nil {
					return e
				}

				wantedValue, e := core.GetWantedValue(setValue, valueType)
				if e != nil {
					return e
				}
				value.SetMapIndex(wantedKey, wantedValue)
				return nil
			}

			if len(mapVarStrkey) > 0 {
				wantedValue, e := core.GetWantedValue(setValue, valueType)
				if e != nil {
					return e
				}
				value.SetMapIndex(reflect.ValueOf(mapVarStrkey), wantedValue)
				return nil
			}

			//int key
			wantedKey, e := core.GetWantedValue(reflect.ValueOf(mapVarIntkey), keyType)
			if e != nil {
				return e
			}
			wantedValue, e := core.GetWantedValue(setValue, valueType)
			if e != nil {
				return e
			}
			value.SetMapIndex(wantedKey, wantedValue)
			return nil

		}

		if newValue.Kind() == reflect.Slice || newValue.Kind() == reflect.Array {
			if len(mapVarVarkey) > 0 {
				key, e := dc.GetValue(Vars, mapVarVarkey)
				if e != nil {
					return e
				}
				wantedValue, e := core.GetWantedValue(setValue, valueType)
				if e != nil {
					return e
				}
				value.Index(int(key.Int())).Set(wantedValue)
				return nil
			}

			if len(mapVarStrkey) > 0 {
				return errors.New(fmt.Sprintf("the index of array or slice should not be string, now is str \"%s\"", mapVarStrkey))
			}

			if mapVarIntkey >= 0 {
				wantedValue, e := core.GetWantedValue(setValue, valueType)
				if e != nil {
					return e
				}
				value.Index(int(mapVarIntkey)).Set(wantedValue)
				return nil
			} else {
				return errors.New("Slice or Array index  must be non-negative!")
			}
		}
	}

	return errors.New(fmt.Sprintf("unspport type, mapVarName =%s", mapVarName))
}

代码看起来很长,实际上有很多冗余的部分,他的大概执行方式是想做类似于Python__setitem__操作,不论你是slice,map,array,都是走了这一套逻辑

Q&A

Vars是什么?lockVars为什么需要给Vars上锁?

文件地址:internal\base\rule_entity.go

1
2
3
4
5
6
7
func (r *RuleEntity) Execute(dc *context.DataContext) (interface{}, error, bool) {
	v, e, b := r.RuleContent.Execute(dc, make(map[string]reflect.Value))
	if v == reflect.ValueOf(nil) {
		return nil, e, b
	}
	return v.Interface(), e, b
}