event/reflect.go

189 lines
5.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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,
Type: reflectType.Field(idx).Type.Kind(),
JsonTag: reflectType.Field(idx).Tag.Get(JsonTag),
EventTag: reflectType.Field(idx).Tag.Get(OutEventTag),
MappingRuleList: make([]MappingRuleItem, 0),
}
rt.fillMappingRule(field, reflectType.Field(idx).Tag.Get(MappingTag))
res.StructFieldList = append(res.StructFieldList, field)
}
rt.cacheTable[dataFlag] = res
return res
}
// 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],
})
}
}
}
}
}