211 lines
5.6 KiB
Go
211 lines
5.6 KiB
Go
// Package event ...
|
||
//
|
||
// Description : event ...
|
||
//
|
||
// Author : go_developer@163.com<白茶清欢>
|
||
//
|
||
// Date : 2023-02-01 14:30
|
||
package event
|
||
|
||
import (
|
||
"reflect"
|
||
"strings"
|
||
"sync"
|
||
)
|
||
|
||
var (
|
||
// ReflectTypeInstance 反射实例
|
||
ReflectTypeInstance *ReflectType
|
||
)
|
||
|
||
func init() {
|
||
ReflectTypeInstance = &ReflectType{
|
||
lock: &sync.RWMutex{},
|
||
cacheTable: make(map[string]*StructInfo),
|
||
}
|
||
}
|
||
|
||
// ReflectType 反射数据类型
|
||
//
|
||
// Author : go_developer@163.com<白茶清欢>
|
||
//
|
||
// Date : 14:31 2023/2/1
|
||
type ReflectType struct {
|
||
// 数据锁
|
||
lock *sync.RWMutex
|
||
// 反射结果缓存
|
||
cacheTable map[string]*StructInfo
|
||
}
|
||
|
||
// Do 反射获取数据类型
|
||
//
|
||
// Author : go_developer@163.com<白茶清欢>
|
||
//
|
||
// Date : 14:34 2023/2/1
|
||
//
|
||
// 为特定结构体生成全局唯一的标识, 并进行缓存, 加速反射结果获取
|
||
func (rt *ReflectType) Do(dataFlag string, data interface{}) *StructInfo {
|
||
rt.lock.Lock()
|
||
defer rt.lock.Unlock()
|
||
if cacheResult, exist := rt.cacheTable[dataFlag]; exist {
|
||
// 缓存存在, 直接是有缓存结果
|
||
return cacheResult
|
||
}
|
||
// 缓存不存在, 解析
|
||
res := &StructInfo{
|
||
Flag: dataFlag,
|
||
IsStruct: false,
|
||
StructFieldList: make([]*StructField, 0),
|
||
}
|
||
reflectType := reflect.TypeOf(data)
|
||
if reflectType.Kind() == reflect.Ptr {
|
||
reflectType = reflectType.Elem()
|
||
}
|
||
if reflectType.Kind() != reflect.Struct {
|
||
// 非结构体,无需反射
|
||
rt.cacheTable[dataFlag] = res
|
||
return res
|
||
}
|
||
res.IsStruct = true
|
||
for idx := 0; idx < reflectType.NumField(); idx++ {
|
||
field := &StructField{
|
||
Idx: idx,
|
||
Name: reflectType.Field(idx).Name,
|
||
JsonTag: reflectType.Field(idx).Tag.Get(JsonTag),
|
||
EventTag: reflectType.Field(idx).Tag.Get(OutEventTag),
|
||
MappingRuleList: make([]MappingRuleItem, 0),
|
||
}
|
||
rt.fillFieldType(field, reflectType.Field(idx).Type.Kind())
|
||
rt.fillMappingRule(field, reflectType.Field(idx).Tag.Get(MappingTag))
|
||
res.StructFieldList = append(res.StructFieldList, field)
|
||
}
|
||
rt.cacheTable[dataFlag] = res
|
||
return res
|
||
}
|
||
|
||
// fillFieldType 填充字段类型
|
||
//
|
||
// Author : go_developer@163.com<白茶清欢>
|
||
//
|
||
// Date : 20:46 2023/2/1
|
||
func (rt *ReflectType) fillFieldType(field *StructField, dataType reflect.Kind) {
|
||
switch dataType {
|
||
case reflect.Float32:
|
||
fallthrough
|
||
case reflect.Float64:
|
||
field.Type = reflect.Float64
|
||
case reflect.String:
|
||
field.Type = reflect.String
|
||
default:
|
||
if strings.Contains(dataType.String(), "int") {
|
||
field.Type = reflect.Int64
|
||
} else {
|
||
field.Type = reflect.Interface
|
||
}
|
||
}
|
||
}
|
||
|
||
// fillTagInfo 填充标签信息
|
||
//
|
||
// Author : go_developer@163.com<白茶清欢>
|
||
//
|
||
// Date : 17:11 2023/2/1
|
||
func (rt *ReflectType) fillTagInfo(field *StructField) {
|
||
if len(field.JsonTag) == 0 {
|
||
field.JsonTag = field.Name
|
||
}
|
||
|
||
// jsonTag 去掉 omitempty
|
||
jsonTagValArr := strings.Split(field.JsonTag, ",")
|
||
for _, item := range jsonTagValArr {
|
||
if len(item) > 0 && item != OmitemptyTag {
|
||
field.JsonTag = item
|
||
break
|
||
}
|
||
}
|
||
|
||
// 没有设置event tag,则和 json tag保持一致
|
||
if len(field.EventTag) == 0 {
|
||
field.EventTag = field.JsonTag
|
||
}
|
||
}
|
||
|
||
// fillMappingRule 解析参数映射规则
|
||
//
|
||
// Author : go_developer@163.com<白茶清欢>
|
||
//
|
||
// Date : 17:14 2023/2/1
|
||
//
|
||
// mapping:"user_id:param#user_id|header#id"
|
||
func (rt *ReflectType) fillMappingRule(field *StructField, inputMappingVal string) {
|
||
|
||
if len(inputMappingVal) == 0 {
|
||
// 没有指定规则, 有默认规则
|
||
for _, location := range mappingLocationList {
|
||
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
|
||
Location: location,
|
||
Field: field.JsonTag,
|
||
})
|
||
}
|
||
return
|
||
}
|
||
mappingArr := strings.Split(inputMappingVal, ",")
|
||
for _, item := range mappingArr {
|
||
item = strings.TrimSpace(item)
|
||
// 要赋值的字段名
|
||
itemArr := strings.Split(item, ":")
|
||
if len(itemArr) != 2 {
|
||
// 配置格式错误, 跳过
|
||
continue
|
||
}
|
||
mapRuleArr := strings.Split(strings.TrimSpace(itemArr[1]), "|")
|
||
for _, itemMapRule := range mapRuleArr {
|
||
itemMapRule = strings.TrimLeft(itemMapRule, "#")
|
||
itemMapRuleArr := strings.Split(itemMapRule, "#")
|
||
// 注意 : # 为特殊分隔符, 如配置成 mapping:"project_id:#source_project_id#xxx_project_id" 实际等价于 mapping:"project_id:#source_project_id" 多余配置自动跳过
|
||
if len(itemMapRuleArr[0]) < 2 {
|
||
// 没有指定位置,默认all, 即配置格式: mapping:"project_id:#source_project_id"
|
||
itemMapRuleArr[0] = MappingLocationAll
|
||
itemMapRuleArr = []string{MappingLocationAll, itemMapRuleArr[0]}
|
||
}
|
||
|
||
switch itemMapRuleArr[0] {
|
||
// 从header读取
|
||
case MappingLocationHeader:
|
||
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
|
||
Location: MappingLocationHeader,
|
||
Field: itemMapRuleArr[1],
|
||
})
|
||
// 从请求参数读取
|
||
case MappingLocationParam:
|
||
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
|
||
Location: MappingLocationParam,
|
||
Field: itemMapRuleArr[1],
|
||
})
|
||
// 从响应数据读取
|
||
case MappingLocationResponse:
|
||
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
|
||
Location: MappingLocationResponse,
|
||
Field: itemMapRuleArr[1],
|
||
})
|
||
// 从扩展数据读取
|
||
case MappingLocationExtension:
|
||
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
|
||
Location: MappingLocationExtension,
|
||
Field: itemMapRuleArr[1],
|
||
})
|
||
// 全部读取一遍
|
||
case MappingLocationAll:
|
||
fallthrough
|
||
default:
|
||
for _, itemLocation := range mappingLocationList {
|
||
field.MappingRuleList = append(field.MappingRuleList, MappingRuleItem{
|
||
Location: itemLocation,
|
||
Field: itemMapRuleArr[1],
|
||
})
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|