优化字段结构定义 + 半成品映射规则解析

This commit is contained in:
白茶清欢 2023-02-01 18:46:18 +08:00
parent bbb9639b09
commit 7b7aee4070
2 changed files with 183 additions and 6 deletions

View File

@ -10,14 +10,18 @@ package event
import "reflect"
const (
// OutputKeyTag 事件数据输出key的标签
OutputKeyTag = "event"
// OutEventTag 事件数据输出key的标签
OutEventTag = "event"
// JsonTag json输出的标签
JsonTag = "json"
// IgnoreTagValue 不做输出的标签值
IgnoreTagValue = "-"
// MappingTag 参数映射标签
MappingTag = "mapping"
// PriorityTag 处理数据时, mapping数据查找的优先级, 默认值 : field
PriorityTag = "priority"
// OmitemptyTag ...
OmitemptyTag = "omitempty"
)
const (
@ -33,15 +37,52 @@ const (
MappingLocationExtension = "extension"
)
var (
mappingLocationList = []string{
MappingLocationHeader,
MappingLocationParam,
MappingLocationResponse,
MappingLocationExtension,
}
)
// SetMappingLocationList 只持续该默认的查找优先级
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:17 2023/2/1
func SetMappingLocationList(locationList []string) {
if len(locationList) > 0 {
mappingLocationList = locationList
}
}
const (
// PriorityLocation 读取位置优先
PriorityLocation = "location"
// PriorityField 读取字段优先
PriorityField = "field"
)
// MappingRuleItem 规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:36 2023/2/1
type MappingRuleItem struct {
Location string `json:"location"` // 数据所在位置, header-请求头 param-参数获取 response-响应数据获取 extension-扩展数据读取 all-自动按照header/param/response/extension的顺序查询
Field string `json:"field"` // 查询的字段名称
}
// MappingRule 数据映射规则
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:24 2023/2/1
type MappingRule struct {
Location string `json:"location"` // 数据所在位置, header-请求头 param-参数获取 response-响应数据获取 extension-扩展数据读取 all-自动按照header/param/response/extension的顺序查询
Field []string `json:"field"` // 查询的字段名称, 列表, 按照优先级诸葛查询
RuleList []MappingRuleItem `json:"rule_list"` // 规则列表
Priority string `json:"priority"` // 查找优先级 : location - 位置优先 field - 字段优先
TargetField string `json:"target_field"` // 目标字段
}
// StructField 结构体字段信息
@ -50,9 +91,21 @@ type MappingRule struct {
//
// Date : 14:35 2023/2/1
type StructField struct {
Idx int // 字段在结构体的索引
Name string // 字段名
Type reflect.Kind // 字段类型
JsonTag string // json标签
EventTag string // 事件标签
MappingRule *MappingRule // 数据映射规则
}
// StructInfo 结构体信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:17 2023/2/1
type StructInfo struct {
Flag string // 结构体标识
IsStruct bool // 是否为结构体
StructFieldList []*StructField // 结构体字段列表
}

View File

@ -7,12 +7,34 @@
// 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 反射获取数据类型
@ -20,6 +42,108 @@ type ReflectType struct {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:34 2023/2/1
func (rt *ReflectType) Do(data interface{}) {
//
// 为特定结构体生成全局唯一的标识, 并进行缓存, 加速反射结果获取
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 {
// 非结构体,无需反射
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),
MappingRule: nil,
}
res.StructFieldList = append(res.StructFieldList, field)
}
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,则和
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, inputPriorityVal string) {
rule := &MappingRule{
RuleList: make([]MappingRuleItem, 0),
Priority: "",
TargetField: "",
}
switch inputPriorityVal {
case PriorityLocation:
rule.Priority = PriorityLocation
case PriorityField:
rule.Priority = PriorityField
default:
rule.Priority = PriorityField
}
if len(inputMappingVal) == 0 {
// 没有指定规则, 有默认规则
for _, location := range mappingLocationList {
rule.RuleList = append(rule.RuleList, MappingRuleItem{
Location: location,
Field: field.JsonTag,
})
}
field.MappingRule = rule
return
}
mappingArr := strings.Split(inputMappingVal, ",")
for _, item := range mappingArr {
item = strings.TrimSpace(item)
// 要赋值的字段名
itemArr := strings.Split(item, ":")
rule.TargetField = strings.TrimSpace(itemArr[0])
}
}