1 Star 0 Fork 0

tomatomeatman/GolangRepository

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
Entity.go 54.07 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023
package dbinfo
import (
"crypto/md5"
"encoding/hex"
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
"time"
"unicode/utf8"
"github.com/shopspring/decimal"
"gopkg.in/ini.v1"
)
//const timeFormat = "2006-01-02 15:04:05"
var (
entityWriteLock sync.Mutex //保存锁
entityMap = make(map[string]Entity) //注册实体结构体集合
// dbMap = make(map[string]string) //注册数据库别名集合
// tableNameMap = make(map[string]string) //实体的TableName缓存,TableName用于在进行gorm查询时自定义表名需要
// -- 数据库字段名常量 -- //
tableKeyNameMap = map[string]string{}
BaseSystemName string //基本数据库库名
TableMajorKeyString string //数据库表主键名称(字符串形式)
TableMajorKeyAutoInt string //数据库表主键名称(自增长形式)
TableMajorKeyUuId string //数据库表主键名称(UUID形式)
TablePidKey string //数据库表字段名称-上级字段名
TablePathKey string //数据库表字段名称-主键路径名
TableTreeNodeName string //数据库表字段名称-树形节点名
TableCreatorName string //数据库表字段名称-创建人
TableCreateDateName string //数据库表字段名称-创建时间
TableModifiederName string //数据库表字段名称-修改人
TableModifiedDateName string //数据库表字段名称-修改时间
TableStateName string //数据库表字段名称-状态值
TableIndexName string //数据库表字段名称-排序值
TableVersionName string //数据库表字段名称-版本号
TablePasswordName string //数据库表字段名称-密码
TableDelSignName string //数据库表字段名称-逻辑删除标识
TableSetpName string //数据库表字段名称-步骤值
TableOnlyignName string //数据库表字段名称-唯一标识
TableNameDictionary string //字典表表名
TableDictionaryValueName string //字典表值字段名
TableRecordKeyName string //记录验证串字段名
TablesSign string //标识字段名
TablesMemo string //备注字段名
TableTreeRootValue = "00" //数据库树型表根节点默认值
)
// 实体接口定义,用于规范实体结构体
type Entity interface {
New() Entity //创建结构实体
BaseColumnNames() string //结构体映射表的字段名串
BaseEntity() Entity //取基础实体,用于在子类(嵌套结构体)时同样获得基类
GetDataInfo(name string) *DataInfo //取数据结构信息
TableName() string //结构体映射表名,当gorm进行查询时要明确与gorm规则不同的表名时使用
OwnerName() string //结构体映射库名,去除'Dev_'等前缀
OwnerTable() string //结构体映射表名,无库名
}
func init() {
initTableKeyName()
}
// --------- 注册实体结构体集合 开始 ---------//
/**
* 注册实体结构体
* @param name
* @param entity
*/
func RegisterEntity(name string, entity Entity) Entity {
entityWriteLock.Lock() //加锁
defer entityWriteLock.Unlock() //解锁
entityMap[name] = entity
return entity
}
/**
* 取实体结构体
* @param name
* @return
*/
func GetEntity(name string) Entity {
entityWriteLock.Lock() //加锁
defer entityWriteLock.Unlock() //解锁
return entityMap[name]
}
// --------- 注册实体结构体集合 结束 ---------//
// --------- 注册数据库别名集合 开始 ---------//
// /**
// * 注册数据库别名
// * @param name
// * @param entity
// */
// func RegisterDbName(id, name string) string {
// if id == "" {
// return ""
// }
// if name == "" {
// return ""
// }
// entityWriteLock.Lock() //加锁
// defer entityWriteLock.Unlock() //解锁
// dbMap[id] = name
// return name
// }
// /**
// * 取数据库别名
// * @param id
// * @return
// */
// func GetDbNameById(id string) string {
// if id == "" {
// return ""
// }
// entityWriteLock.Lock() //加锁
// defer entityWriteLock.Unlock() //解锁
// return dbMap[id]
// }
// /**
// * 取数据库别名
// * @param entity
// * @return
// */
// func GetDbName(entity Entity) string {
// if entity == nil {
// return ""
// }
// entityWriteLock.Lock() //加锁
// defer entityWriteLock.Unlock() //解锁
// id := EntityDbName(entity)
// return dbMap[id]
// }
// --------- 注册数据库别名集合 结束 ---------//
// --------- 注册实体结构体对应数据库表名集合 开始 ---------//
// /**
// * 注册实体表名
// * @param id
// * @param name
// */
// func RegisterTableName(id, name string) string {
// if id == "" {
// return ""
// }
// if name == "" {
// return ""
// }
// entityWriteLock.Lock() //加锁
// defer entityWriteLock.Unlock() //解锁
// tableNameMap[id] = name
// return name
// }
// /**
// * 取实体表名
// * @param id
// * @return
// */
// func GetTableNameById(id string) string {
// if id == "" {
// return ""
// }
// entityWriteLock.Lock() //加锁
// defer entityWriteLock.Unlock() //解锁
// if name, ok := tableNameMap[id]; ok {
// return name
// }
// return ""
// }
// /**
// * 取实体表名
// * @param entity
// * @return
// */
// func GetTableName(entity Entity) string {
// if entity == nil {
// return ""
// }
// entityWriteLock.Lock() //加锁
// defer entityWriteLock.Unlock() //解锁
// id := EntityTableName(entity)
// if name, ok := tableNameMap[id]; ok {
// return name
// }
// return ""
// }
// --------- 注册实体结构体对应数据库表名集合 结束 ---------//
/**
* 取基础实体,用于在子类(嵌套结构体)时同样获得基类
* @param entity
* @return
*/
func BaseEntity(entity Entity) Entity {
return entity.BaseEntity() //调用子类的实现方法
}
/**
* 按名称取数据结构信息
* @param entity
* @param name
* @return
*/
func GetDataInfo(entity Entity, name string) *DataInfo {
return entity.GetDataInfo(name) //子类实现
}
/**
* 按字段顺序取数据结构信息
* @param entity
* @param name
* @return
*/
func GetDataInfoByIndex(entity Entity, index int) *DataInfo {
if index < 0 {
index = 0
}
array := strings.Split(entity.BaseColumnNames(), ",")
if len(array) <= index {
return nil
}
return entity.GetDataInfo(array[index]) //子类实现
}
/**
* 判断是否存在字段名
* @param entity
* @param name
* @return
*/
func HasColumnName(entity Entity, name string) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, v := range array {
if v == name {
return true
}
}
return false
}
/**
* 取所有数据结构信息
* @param entity
* @return
*/
func AllDataInfo(entity Entity) []*DataInfo {
array := strings.Split(entity.BaseColumnNames(), ",")
result := []*DataInfo{}
for _, key := range array {
result = append(result, entity.GetDataInfo(key))
}
return result
}
/**
* 结构体映射表的字段名集合
* @param entity
* @return
*/
func BaseColumnNameList(entity Entity) []string {
return strings.Split(entity.BaseColumnNames(), ",")
}
/**
* 创建指定长度的结构实体集合
* @param entity
* @param iSize
* @return
*/
func NewList(entity Entity, iSize int) []Entity {
result := make([]Entity, iSize)
for i := 0; i < iSize; i++ {
result[i] = entity.New()
}
return result
}
/**
* 设置默认值
* @param entity
* @param cover 是否覆盖
*/
func SetDefault(entity Entity, cover bool) {
array := strings.Split(entity.BaseColumnNames(), ",") //结构体映射表的字段名串
data := make(map[string]interface{})
for _, name := range array {
dataInfo := entity.GetDataInfo(name)
if dataInfo.GoDefaultData == nil {
continue
}
data[name] = dataInfo.GoDefaultData
}
pValue := reflect.ValueOf(entity) // 获取指针指向的值
setFieldsVal(pValue, data, cover)
}
/**
* 取主键数据结构信息
* @param entity
* @return
*/
func GetKeyDataInfo(entity Entity) []*DataInfo {
array := strings.Split(entity.BaseColumnNames(), ",")
result := []*DataInfo{}
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.Gbkey {
result = append(result, dataInfo)
}
}
return result
}
/**
* 取所属数据库名
* @param entity
* @return
*/
func EntityDbName(entity Entity) string {
array := strings.Split(entity.BaseColumnNames(), ",")
var dataInfo *DataInfo
for _, key := range array {
dataInfo = entity.GetDataInfo(key)
if dataInfo.Gbkey {
return dataInfo.GsDbName
}
}
if dataInfo == nil {
return ""
}
return dataInfo.GsDbName
}
/**
* 取所属数据库表名
* @param entity
* @return
*/
func EntityTableName(entity Entity) string {
array := strings.Split(entity.BaseColumnNames(), ",")
var dataInfo *DataInfo
for _, key := range array {
dataInfo = entity.GetDataInfo(key)
if dataInfo.Gbkey {
return dataInfo.GsTableName
}
}
if dataInfo == nil {
return ""
}
return dataInfo.GsDbName
}
/**
* 取所属数据库表主键名
* 注意:如果有多个主键,则取第一个主键
* @param entity
* @return
*/
func EntityKeyName(entity Entity) string {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.Gbkey {
return dataInfo.GsName
}
}
return ""
}
/**
* 取所属数据库表主键名
* 注意:如果有多个主键,则全取,并以','分隔
* @param entity
* @return
*/
func EntityKeyNames(entity Entity) string {
array := strings.Split(entity.BaseColumnNames(), ",")
result := ""
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.Gbkey {
result += "," + dataInfo.GsName
}
}
return strings.TrimPrefix(result, ",") //去掉前缀
}
/**
* 取所属数据库表主键长度
* 注意:如果有多个主键,则取第一个主键
* @param entity
* @return
*/
func EntityKeyLength(entity Entity) int {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.Gbkey {
return dataInfo.GiMaxLength
}
}
return 8
}
/**
* 取所属数据库表主键长度
* 注意:如果有多个主键,则全取
* @param entity
* @return
*/
func EntityKeysLength(entity Entity) map[string]int {
array := strings.Split(entity.BaseColumnNames(), ",")
result := make(map[string]int, 0)
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.Gbkey {
result[dataInfo.GsName] = dataInfo.GiMaxLength
}
}
return result
}
// ---------- 去除字符类型属性前后空格 开始 -------- //
/**
* 去除字符类型属性前后空格
*/
func TrimFields(entity Entity) {
v := reflect.ValueOf(entity).Elem()
trimStringFields(v) // 调用函数清除字符串字段的前后空格
}
/**
* 通用函数,用于递归处理结构体及其匿名字段中的字符串
* @param v 结构体或匿名结构体
*/
func trimStringFields(v reflect.Value) {
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
fieldType := v.Type().Field(i)
// 检查字段是否为匿名结构体
if fieldType.Anonymous {
trimStringFields(field)
continue
}
if field.Kind() == reflect.String {
field.SetString(strings.TrimSpace(field.String())) // 清除前后空格
continue
}
if field.Kind() == reflect.Struct {
trimStringFields(field) // 如果字段是结构体,则递归调用trimStringFields
continue
}
}
}
// ---------- 去除字符类型属性前后空格 结束 -------- //
/*
* 创建记录验证值
* @param entity
* @return
*/
func CreateRecordKey(entity Entity) string {
pValue := reflect.ValueOf(entity) // 获取指针指向的值
array := strings.Split(entity.BaseColumnNames(), ",")
valMap := getFieldsVal(pValue) // 递归遍历结构体的所有字段
temp := ""
for _, k := range array { //只有数组才能固定顺序
if k == "sRecordKey" { //sRecordKey字段不能参与,并且一旦轮询到sRecordKey就结束
break
}
v, ok := valMap[k]
if !ok {
continue
}
if v == nil {
temp = temp + ";"
continue
}
switch reflect.TypeOf(v).String() {
case "time.Time":
temp = temp + v.(time.Time).Format(timeFormat) + ";"
default:
temp = temp + fmt.Sprintf("%v", v) + ";"
}
}
data := []byte(temp)
md5Ctx := md5.New()
md5Ctx.Write(data)
cipherStr := md5Ctx.Sum(nil)
result := hex.EncodeToString(cipherStr)
return strings.ToUpper(result)
}
/*
* 根据结构体创建map的记录验证值
* @param entity 参照结构体,仅用于取结构
* @param data 数据
* @return
*/
func CreateRecordKeyByMap(entity Entity, data map[string]interface{}) string {
array := strings.Split(entity.BaseColumnNames(), ",") //关键就是按顺序进行
temp := ""
for _, k := range array { //只有数组才能固定顺序
if k == "sRecordKey" { //sRecordKey字段不能参与,并且一旦轮询到sRecordKey就结束
break
}
v, ok := data[k]
if !ok {
temp = temp + ";"
continue
}
if v == nil {
temp = temp + ";"
continue
}
switch reflect.TypeOf(v).String() {
case "time.Time":
temp = temp + v.(time.Time).Format(timeFormat) + ";"
default:
temp = temp + fmt.Sprintf("%v", v) + ";"
}
}
b := []byte(temp)
md5Ctx := md5.New()
md5Ctx.Write(b)
cipherStr := md5Ctx.Sum(nil)
result := hex.EncodeToString(cipherStr)
return strings.ToUpper(result)
}
/**
* 验证'记录验证串'是否正确
* @param entity
* @return
*/
func CheckRecordKey(entity Entity) bool {
nowKey := CreateRecordKey(entity)
v := reflect.ValueOf(entity)
oldKey := v.FieldByName(TableRecordKeyName).Interface().(string)
return oldKey == nowKey
}
/**
* 设置当前实体的'记录验证串'值
* @param entity
* @return 返回新值
*/
func SetRecordKey(entity Entity) string {
nowKey := CreateRecordKey(entity)
v := reflect.ValueOf(entity).Elem()
v.FieldByName(TableRecordKeyName).SetString(nowKey)
return nowKey
}
// /* 相对鱼每个表中定义一个变量来保存数据库表名来说性能太差
// * 结构体映射表名,处理结构体名称与表名不一致的情况
// * @return
// */
// func TableName(entity Entity) string {
// array := strings.Split(entity.BaseColumnNames(), ",")
// var dbName, tableName string
// var dataInfo *DataInfo
// for _, key := range array {
// dataInfo = entity.GetDataInfo(key)
// if dataInfo.Gbkey {
// dbName = dataInfo.GsDbName
// tableName = dataInfo.GsTableName
// break
// }
// }
// if dataInfo != nil && tableName == "" {
// dbName = dataInfo.GsDbName
// tableName = dataInfo.GsTableName
// }
// id := dbName + "." + tableName
// name := GetTableNameById(id)
// if name != "" {
// return name
// }
// if dbName == "" {
// return tableName
// }
// dbName = dbMap[dbName] //从注册数据库别名集合中获取到实际的库名
// if dbName == "" {
// return id //如果没有别名,则直接返回id
// }
// return dbName + tableName //别名中存在'.'
// }
/*
* 结构体简略表名(无库名)
* @return
*/
func SimpleTableName(entity Entity) string {
return EntityTableName(entity)
}
/**
* 取数据值
* @param entity
* @param name 字段名
* @return
*/
func GetVal(entity Entity, name string) interface{} {
// // 使用反射获取结构体类型和值
// entityValue := reflect.ValueOf(entity).Elem() // 获取指针指向的值
// entityType := entityValue.Type()
// // 遍历结构体的所有字段
// for i := 0; i < entityType.NumField(); i++ {
// fieldType := entityType.Field(i)
// fieldValue := entityValue.Field(i)
// jsonTag := fieldType.Tag.Get("json") // 获取json标签
// // 检查是否有特定的json标签
// if jsonTag == name {
// return fieldValue.Interface()
// }
// }
// return nil
pValue := reflect.ValueOf(entity)
return getFieldVal(pValue, name)
}
/**
* 设置数据值(此函数用于未知结构体的情况下调用)
* @param name 字段名
* @param val 值
* @return
*/
func SetVal(entity Entity, name string, val interface{}) {
pValue := reflect.ValueOf(entity)
setFieldVal(pValue, name, val)
}
/**
* 将map转成实体
* data 数据
* entity 数据结构
*/
func ToEntity(data map[string]interface{}, entity Entity) (Entity, int, error) {
if data == nil {
return nil, 1001, errors.New("map为nil")
}
if entity == nil {
return nil, 1002, errors.New("数据结构为nil")
}
SetDefault(entity, true) //补齐默认值
if !EntityHasRecordKey(entity) { //如果没有sRecordKey字段则直接结束
MapSetEntity(data, entity) //Map设置结构体
return entity, 1999, nil
}
MapSetEntity(data, entity) //Map设置结构体
sRecordKey := CreateRecordKey(entity)
SetVal(entity, TableRecordKeyName, sRecordKey)
return entity, 1999, nil
}
// Map设置结构体
func MapSetEntity(data map[string]interface{}, entity Entity) Entity {
pValue := reflect.ValueOf(entity) // 获取指针指向的值
setFieldsVal(pValue, data, true) //设置值
return entity
}
// ----------- Map转结构体 开始 ----------- //
// 将map数据转换为实体
func MapToEntity(data map[string]interface{}, entity Entity) Entity {
result := mapToEntity(data, entity) // mapToStruct 将map数据转换为指定的结构体实例
return result.(Entity)
}
// mapToStruct 将map数据转换为指定的结构体实例
func mapToEntity(data map[string]interface{}, target interface{}) interface{} {
targetValue := reflect.ValueOf(target)
if targetValue.Kind() == reflect.Ptr { //传入的是指针如:&User{}
//v = v.Elem() // 获取指针指向的值
} else { //传入的是实体,如User{}
// 获取目标结构体的类型
targetType := reflect.TypeOf(target)
targetPtrType := reflect.PtrTo(targetType)
// 创建一个新的指针类型
newTarget := reflect.New(targetPtrType.Elem()).Interface()
// 将原始值复制到新指针中
reflect.ValueOf(newTarget).Elem().Set(reflect.ValueOf(target))
// 重新设置目标为指针类型
target = newTarget
targetValue = reflect.ValueOf(target)
}
v := targetValue.Elem() // 获取目标结构体的元素值
for key, val := range data {
setField(v, key, val)
}
if targetValue.Kind() == reflect.Ptr { //如果参数本身就是指针,则参数已经被修改,直接返回参数即可
return target
}
result := v.Interface() //参数不是指针,属于内部结构体,需要返回指针
return &result
}
// setField 遍历结构体并设置字段值,如果字段名与key相同,则设置为val
func setField(v reflect.Value, key string, val interface{}) {
// 检查是否为结构体
if v.Kind() != reflect.Struct {
return
}
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
fieldType := v.Type().Field(i)
// 获取字段的json标签
jsonTag := fieldType.Tag.Get("json")
if jsonTag == "" {
continue
}
// 解析json标签
parts := strings.Split(jsonTag, ",")
if len(parts) > 0 && parts[0] == key {
// 尝试将 val 转换为字段类型
canSetValue(field, val)
// if _, ok := canSetValue(field, val); ok { //有可能其它嵌套结构体也有同名字段
// field.Set(reflect.ValueOf(cVal))
// }
}
// 递归处理嵌套结构体或指针
if field.Kind() == reflect.Ptr && !field.IsNil() {
elem := field.Elem()
if elem.Kind() == reflect.Struct {
setField(elem, key, val)
}
continue
}
if field.Kind() == reflect.Struct {
setField(field, key, val)
continue
}
if field.Kind() == reflect.Interface { // 处理 interface{} 类型
if field.IsNil() && (jsonTag == key) { // 如果类型为interface{}的字段当前值为nil,且json键值与map键值相符,则赋值,否则无法赋值
field.Set(reflect.ValueOf(val))
continue
}
handleInterface(field, key, val)
continue
}
}
}
// handleInterface 处理 interface{} 类型的字段
func handleInterface(v reflect.Value, key string, val interface{}) {
if v.IsNil() {
return
}
elem := v.Elem() // 获取实际类型
switch elem.Kind() {
case reflect.Map:
handleMap(elem, key, val) // 处理 map 类型
return
case reflect.Struct:
setField(elem, key, val) // 处理结构体类型
return
}
}
// handleMap 处理 map 类型的字段
func handleMap(v reflect.Value, key string, val interface{}) {
for _, k := range v.MapKeys() {
val0 := v.MapIndex(k)
if val0.Kind() == reflect.Struct {
setField(val0, key, val)
} else if val0.Kind() == reflect.Map {
handleMap(val0, key, val)
} else {
// 尝试将 val 转换为字段类型
if cVal, ok := canSetValue(val0, val); ok {
val0.Set(reflect.ValueOf(cVal))
}
}
}
}
// canSetValue 判断是否可以将 val 转换为字段类型
func canSetValue(field reflect.Value, val interface{}) (interface{}, bool) {
fieldValue := reflect.ValueOf(val)
fieldType := field.Type()
switch fieldType.Kind() {
case reflect.String:
if fieldValue.Type().ConvertibleTo(fieldType) {
field.Set(fieldValue.Convert(fieldType))
return val, true
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if fieldValue.Type().ConvertibleTo(fieldType) {
field.Set(fieldValue.Convert(fieldType))
return val, true
}
case reflect.Float32, reflect.Float64:
if fieldValue.Type().ConvertibleTo(fieldType) {
field.Set(fieldValue.Convert(fieldType))
return val, true
}
case reflect.Bool:
if fieldValue.Type().ConvertibleTo(fieldType) {
field.Set(fieldValue.Convert(fieldType))
return val, true
}
temp := strings.ToUpper(fmt.Sprintf("%v", fieldValue))
bl := (temp == "1") || (temp == "TRUE")
field.Set(reflect.ValueOf(bl))
return bl, bl
case reflect.Struct:
switch fieldType.String() {
case "time.Time":
if fieldValue.Type().Kind() == reflect.String {
t := toDate(fieldValue.String())
field.Set(reflect.ValueOf(t))
return t, true
}
field.Set(fieldValue)
return val, true
case "decimal.Decimal":
t, err := decimal.NewFromString(fmt.Sprintf("%v", fieldValue))
if err != nil {
field.Set(reflect.ValueOf(decimal.Zero))
return decimal.Zero, true
}
field.Set(reflect.ValueOf(t))
return t, true
}
}
return val, false
}
// 字符串转时间
func toDate(str string) time.Time {
str = strings.TrimSpace(str)
if str == "" {
return time.Now()
}
str = strings.Replace(str, "/", "-", -1)
str = strings.Replace(str, "T", " ", -1)
str = strings.Replace(str, "Z", "", -1)
str = strings.Replace(str, "z", "", -1)
iEd := strings.LastIndex(str, ".")
if iEd > -1 {
str = str[:iEd]
}
local, _ := time.LoadLocation("Asia/Shanghai")
if len(str) == 19 {
result, _ := time.ParseInLocation(timeFormat, str, local)
return result
}
if len(str) == 16 {
result, _ := time.ParseInLocation("2006-01-02 15:04", str, local)
return result
}
result, _ := time.ParseInLocation("2006-01-02", str, local)
return result
}
// ----------- Map转结构体 结束 ----------- //
// ----------- 结构体转Map 开始 ----------- //
// 将结构体的所有属性及其值存入 map[string]interface{}
func ToMap(entity interface{}) map[string]interface{} {
return structToMap(entity)
}
// 将结构体的所有属性及其值存入 map[string]interface{}
func structToMap(source interface{}) map[string]interface{} {
entityValue := reflect.ValueOf(source)
if entityValue.Kind() == reflect.Ptr { //传入的是指针如:&User{}
entityValue = entityValue.Elem() // 获取指针指向的值
}
entityType := entityValue.Type()
result := make(map[string]interface{})
// 遍历结构体的所有字段
for i := 0; i < entityType.NumField(); i++ {
fieldType := entityType.Field(i)
fieldValue := entityValue.Field(i)
jsonTag := fieldType.Tag.Get("json")
// 跳过忽略字段
if jsonTag == "-" {
continue
}
// 获取当前字段的键名
key := jsonTag
// 处理匿名结构体
if fieldType.Anonymous {
if fieldValue.Kind() == reflect.Struct {
subMap := structToMap(fieldValue.Interface()) //递归
for k, v := range subMap {
//result["@@@Anonymous_" + k] = v//如果发现匿名字段覆盖了上级字段,则必须进行特殊处理,在此保留代码
result[k] = v
}
}
continue
}
if fieldValue.Kind() == reflect.Ptr && !fieldValue.IsNil() {
// 处理结构体指针
subMap := structToMap(fieldValue.Elem().Interface()) //递归
result[key] = subMap
continue
}
// 直接处理普通字段
if fieldType.Type == reflect.TypeOf(time.Time{}) {
// 格式化 time.Time 类型
if fieldValue.CanInterface() {
t := fieldValue.Interface().(time.Time)
result[key] = t.Format(timeFormat)
}
continue
}
result[key] = fieldValue.Interface()
}
return result
}
// ----------- 结构体转Map 结束 ----------- //
// ----------- 特殊字段是否存在判断 开始 ----------- //
func EntityAutoKey(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GbExtra && dataInfo.Gbkey {
return true
}
}
return false
}
func EntityHasPid(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TablePidKey {
return true
}
}
return false
}
func EntityHasPath(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TablePathKey {
return true
}
}
return false
}
func EntityHasRecordKey(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableRecordKeyName {
return true
}
}
return false
}
func EntityHasMemo(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TablesMemo {
return true
}
}
return false
}
func EntityHasCreator(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableCreatorName {
return true
}
}
return false
}
func EntityHasCreateDate(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableCreateDateName {
return true
}
}
return false
}
func EntityHasModifieder(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableModifiederName {
return true
}
}
return false
}
func EntityHasModifiedDate(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableModifiedDateName {
return true
}
}
return false
}
func EntityHasState(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableStateName {
return true
}
}
return false
}
func EntityHasIndex(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableIndexName {
return true
}
}
return false
}
func EntityHasVersion(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableVersionName {
return true
}
}
return false
}
func EntityHasPassword(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TablePasswordName {
return true
}
}
return false
}
func EntityHasSign(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TablesSign {
return true
}
}
return false
}
func EntityHasOnlyign(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableOnlyignName {
return true
}
}
return false
}
func EntityHasDelSign(entity Entity) bool {
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
if dataInfo.GsName == TableDelSignName {
return true
}
}
return false
}
// ----------- 特殊字段是否存在判断 结束 ----------- //
/**
* 结构体映射表简化信息
*/
func GetTableInfo(entity Entity) *TableInfo {
result := &TableInfo{}
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
dataInfo := entity.GetDataInfo(key)
result.GsDbName = dataInfo.GsDbName
result.GsTableName = dataInfo.GsTableName
if dataInfo.Gbkey && result.GsKeyName == "" {
result.GsKeyName = dataInfo.GsName
result.GbAutoKey = dataInfo.GbExtra
result.GiKeyLen = dataInfo.GiMaxLength
continue
}
if dataInfo.GbBigTxt {
result.GsBigTextFields += dataInfo.GsName + ";"
}
switch dataInfo.GsName {
case TablePidKey:
result.GbHasPid = true
case TablePathKey:
result.GbHasPath = true
case TableRecordKeyName:
result.GbHasRecordKey = true
case TablesMemo:
result.GbHasMemo = true
case TableCreatorName:
result.GbHasCreator = true
case TableCreateDateName:
result.GbHasCreateDate = true
case TableModifiederName:
result.GbHasModifieder = true
case TableModifiedDateName:
result.GbHasModifiedDate = true
case TableStateName:
result.GbHasState = true
case TableIndexName:
result.GbHasIndex = true
case TableVersionName:
result.GbHasVersion = true
case TablePasswordName:
result.GbHasPassword = true
case TablesSign:
result.GbHasSign = true
case TableOnlyignName:
result.GbHasOnlyign = true
case TableDelSignName:
result.GbHasDelSign = true
}
}
return result
}
// ----------- 实体验证 开始 ----------- //
/**
* 对对象中添加了DataInfo注解的不为null的属性检查限制
* data 数据
* entity 检查用数据结构
* ignoreNames 待忽略的字段
*/
func ValidAttr(data map[string]interface{}, entity Entity, ignoreNames []string) (int, error) {
if data == nil {
return 1001, createError("数据为nil")
}
if entity == nil {
return 1002, createError("数据结构为nil")
}
ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
for _, v := range ignoreNames {
ignoreNamesMap[v] = struct{}{}
}
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
if _, ok := ignoreNamesMap[key]; ok { //忽略字段
continue
}
dataInfo := entity.GetDataInfo(key)
if dataInfo == nil { //这个字段没有数据信息(一般不太可能)
return 1003, createError("发现不符合框架规则的字段:", key)
}
if !dataInfo.GbNull { //字段是否允许为空
temp := data[key]
if temp == nil { //数据如果为空
return 1004, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空!")
} else if fmt.Sprintf("%v", temp) == "" {
return 1005, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空!")
}
}
oldValue := fmt.Sprintf("%v", data[key])
strType := dataInfo.GsDbFileType
if strType == "int" { // 此时oldValue的值为:"<int Value>"
oldValue = fmt.Sprintf("%v", data[key])
}
iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
if !strings.Contains("/datetime/date/time/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
return 1006, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出,最大长度限制为:", iL)
}
}
return 1999, nil
}
/**
* 对'编辑'对象中添加了DataInfo注解的不为null的属性检查限制
* data 数据
* entity 检查用数据结构
* ignoreNames 待忽略的字段
*/
func ValidAttrByEdit(data map[string]interface{}, entity Entity, ignoreNames []string) (int, error) {
if data == nil {
return 1001, errors.New("数据为nil")
}
if entity == nil {
return 1002, errors.New("数据结构为nil")
}
ignoreNamesMap := make(map[string]string, len(ignoreNames))
for _, v := range ignoreNames {
ignoreNamesMap[v] = v
}
allDataInfo := AllDataInfo(entity)
for _, dataInfo := range allDataInfo {
value, ok := data[dataInfo.GsName]
if !ok {
continue //此字段不参与更新则不进行检查
}
if _, ok = ignoreNamesMap[dataInfo.GsName]; ok {
continue
}
oldValue := strings.TrimSpace(fmt.Sprintf("%v", value))
strType := dataInfo.GsDbFileType
if strType == "int" { // 此时oldValue的值为:"<int Value>"
oldValue = fmt.Sprintf("%v", value)
}
iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
if (!strings.Contains("/datetime/date/time/time.Time/decimal.Decimal", strType)) && (iL > 0) && (iL < utf8.RuneCountInString(oldValue)) {
return 1003, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出,最大长度限制为:", iL)
}
if !dataInfo.GbNull && (oldValue == "<nil>" || oldValue == "") {
return 1004, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空!")
}
if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
str := fmt.Sprintf("%v", data[dataInfo.GsName])
array := strings.Split(str, ".")
if dataInfo.GiIntegralLength < len(array[0]) {
return 1005, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出,最大长度限制为:", dataInfo.GiIntegralLength)
}
if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
return 1006, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过,最大长度限制为:", dataInfo.GiIntegralLength)
}
}
if strings.Contains("/float64/float32/", strType) && (iL > 0) {
str := fmt.Sprintf("%f", data[dataInfo.GsName])
array := strings.Split(str, ".")
if dataInfo.GiIntegralLength < len(array[0]) {
return 1005, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出,最大长度限制为:", dataInfo.GiIntegralLength)
}
if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
return 1006, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过,最大长度限制为:", dataInfo.GiIntegralLength)
}
}
}
return 1999, nil
}
/**
* 对'新增'对象中添加了DataInfo注解的属性检查限制
* entity 检查用数据结构
* ignoreNames 待忽略的字段
*/
func ValidAttrByAdd(entity Entity, ignoreNames []string) (int, error) {
if entity == nil {
return 1001, createError("数据结构为nil")
}
ignoreNamesMap := make(map[string]struct{}, len(ignoreNames))
for _, v := range ignoreNames {
ignoreNamesMap[v] = struct{}{}
}
pType := reflect.TypeOf(entity).Elem() // 获取指针指向的类型
pValue := reflect.ValueOf(entity).Elem() // 获取指针指向的值
for i := 0; i < pValue.NumField(); i++ {
field := pValue.Field(i)
jsonTag := pType.Field(i).Tag.Get("json") // 获取json标签
if jsonTag == "-" {
continue
}
dataInfo := GetDataInfo(entity, jsonTag)
if dataInfo == nil {
continue
}
if _, ok := ignoreNamesMap[dataInfo.GsName]; ok { //排除忽略字段
continue
}
oldValue := fmt.Sprintf("%v", reflect.ValueOf(field))
strType := fmt.Sprintf("%v", field.Type()) //类型
if strType == "int" { // 此时oldValue的值为:"<int Value>"
oldValue = fmt.Sprintf("%v", field)
}
iL := dataInfo.GiMaxLength //真正存储字段的最大长度要求不可能小于1,否则无意义,如果定义iMaxLength为0,或-1则说明是要忽略检查的
if !strings.Contains("/datetime/date/time/time.Time/decimal.Decimal/", strType) && iL > 0 && iL < utf8.RuneCountInString(oldValue) {
return 1002, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]长度超出,最大长度限制为:", iL)
}
if !dataInfo.GbNull && ((oldValue == "<nil>") || (oldValue == "")) {
return 1003, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空!")
}
if strings.Contains("/datetime/date/time/time.Time/", strType) && !dataInfo.GbNull && (oldValue == "" || oldValue == "0001-01-01 00:00:00 +0000 UTC" || oldValue == "<nil>") {
return 1004, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]不允许为空!")
}
if strings.Contains("/decimal.Decimal/*big.Float", strType) && (iL > 0) {
str := fmt.Sprintf("%v", field)
array := strings.Split(str, ".")
if dataInfo.GiIntegralLength < len(array[0]) {
return 1005, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出,最大长度限制为:", dataInfo.GiIntegralLength)
}
if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
return 1006, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过,最大长度限制为:", dataInfo.GiIntegralLength)
}
}
if strings.Contains("/float64/float32/", strType) && (iL > 0) {
str := fmt.Sprintf("%v", field)
array := strings.Split(str, ".")
if dataInfo.GiIntegralLength < len(array[0]) {
return 1005, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]整数超出,最大长度限制为:", dataInfo.GiIntegralLength)
}
if (len(array) > 1) && (dataInfo.GiDecimalLength < len(array[1])) {
return 1006, createError(dataInfo.GsComment, "[", dataInfo.GsName, "]小数超过,最大长度限制为:", dataInfo.GiIntegralLength)
}
}
}
return 1999, nil
}
/**
* 按实体保留map中的数据
* object 待检查对象
* data 数据
* fieldPrefix 字段前缀(可不传)
*/
func HoldByEntity(entity Entity, data map[string]interface{}) map[string]interface{} {
result := make(map[string]interface{})
if entity == nil {
return result
}
if data == nil {
return result
}
array := strings.Split(entity.BaseColumnNames(), ",")
for _, key := range array {
if v, ok := data[key]; ok {
result[key] = v
}
}
return result
}
/**
* 创建错误信息
* msg 错误信息
* 返回错误信息
*/
func createError(msg ...interface{}) error {
var build strings.Builder
for _, v := range msg {
build.WriteString(fmt.Sprintf("%v", v))
}
return errors.New(build.String())
}
// ----------- 实体验证 结束 ----------- //
// ----------- 反射属性操作 开始 ----------- //
// 递归访问所有字段
func getFieldsVal(val reflect.Value) map[string]interface{} {
result := make(map[string]interface{})
var t reflect.Type
if val.Kind() == reflect.Ptr { // 判断是否是指针类型
val = val.Elem()
t = val.Type()
} else {
t = val.Type()
}
// 遍历结构体字段,遍历优先级: 具名结构体>匿名结构体>字段; 按此遍历将实现后面遍历到的同名字段将覆盖前面被遍历到的
// 处理具名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if !field.Anonymous && field.Type.Kind() == reflect.Struct {
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
temp := getFieldsVal(anonVal)
for k, v := range temp {
result[k] = v
}
}
}
// 处理匿名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Anonymous && field.Type.Kind() == reflect.Struct {
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
temp := getFieldsVal(anonVal)
for k, v := range temp {
result[k] = v
}
}
}
// 处理最外层普通属性
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
jsonTag := field.Tag.Get("json")
if jsonTag != "" {
fieldValue := val.Field(i).Interface()
result[jsonTag] = fieldValue
}
}
return result
}
// 取指定字段值,从外往内找,找到就结束
func getFieldVal(val reflect.Value, jsonName string) interface{} {
var t reflect.Type
if val.Kind() == reflect.Ptr { // 判断是否是指针类型
val = val.Elem()
t = val.Type()
} else {
t = val.Type()
}
//在外层找,再向内层(匿名结构体)查找
// 最外层普通属性
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
jsonTag := field.Tag.Get("json")
if jsonTag == jsonName {
fieldValue := val.Field(i).Interface()
return fieldValue
}
}
// 处理匿名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if !field.Anonymous {
continue
}
if field.Type.Kind() != reflect.Struct {
continue
}
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
temp := getFieldVal(anonVal, jsonName)
if temp != nil {
return temp
}
}
// 处理具名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Anonymous || field.Type.Kind() != reflect.Struct {
continue
}
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
temp := getFieldVal(anonVal, jsonName)
if temp != nil {
return temp
}
}
return nil
}
// 设置指定字段的值,从外往内找,找到就结束
func setFieldVal(val reflect.Value, jsonName string, data interface{}) bool {
var t reflect.Type
if val.Kind() == reflect.Ptr { // 判断是否是指针类型
val = val.Elem()
t = val.Type()
} else {
t = val.Type()
}
//在外层找,再向内层(匿名结构体)查找
// 最外层普通属性
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
jsonTag := field.Tag.Get("json")
if jsonTag == jsonName {
fieldV := val.Field(i)
canSetValue(fieldV, data)
// if _, ok := canSetValue(fieldV, data); ok { //有可能其它嵌套结构体也有同名字段
//fieldV.Set(reflect.ValueOf(cData))
// }
return true
}
}
// 处理匿名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if !field.Anonymous {
continue
}
if field.Type.Kind() != reflect.Struct {
continue
}
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
if setFieldVal(anonVal, jsonName, data) {
return true
}
}
// 处理具名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Anonymous || field.Type.Kind() != reflect.Struct {
continue
}
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
if setFieldVal(anonVal, jsonName, data) {
return true
}
}
return false
}
// 按map设置指定字段的值,从外往内找,找到就结束
func setFieldsVal(val reflect.Value, data map[string]interface{}, cover bool) {
var t reflect.Type
if val.Kind() == reflect.Ptr { // 判断是否是指针类型
val = val.Elem()
t = val.Type()
} else {
t = val.Type()
}
//在外层找,再向内层(匿名结构体)查找
// 最外层普通属性
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
jsonTag := field.Tag.Get("json")
if v, ok := data[jsonTag]; ok {
fieldV := val.Field(i)
oldValue := reflect.ValueOf(field)
if (fmt.Sprintf("%v", oldValue) != "") && !cover {
continue //如果值不为空,且不允许覆盖,则不要赋值
}
canSetValue(fieldV, v)
//fieldV.Set(reflect.ValueOf(v))
}
}
// 处理匿名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if !field.Anonymous {
continue
}
if field.Type.Kind() != reflect.Struct {
continue
}
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
setFieldsVal(anonVal, data, cover)
}
// 处理具名结构体
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.Anonymous || field.Type.Kind() != reflect.Struct {
continue
}
anonVal := val.Field(i)
if anonVal.Kind() == reflect.Ptr && !anonVal.IsNil() {
anonVal = anonVal.Elem()
}
setFieldsVal(anonVal, data, cover)
}
}
// ----------- 反射属性操作 结束 ----------- //
// ----------- 数据库字段名常量 开始 ----------- //
// 初始化数据库字段名常量
func initTableKeyName() {
root := ""
exePath, err := os.Executable()
if err != nil {
root = "."
}
root, _ = filepath.EvalSymlinks(filepath.Dir(exePath))
filePath := root + "/config/entity.ini"
// 尝试加载配置文件
cfg, err := ini.Load(filePath)
if err != nil {
// 文件不存在或打开失败,返回默认值
initTableKeyNameDefalut() //配置文件不存在,取默认
return
}
// 获取 "mode" 部分
modeSection, err := cfg.GetSection("mode")
if err != nil {
// "mode" 部分不存在,返回默认值
initTableKeyNameDefalut() //配置文件不存在,取默认
return
}
// 获取 "type" 键的值
modeType, err := modeSection.GetKey("type")
if err != nil {
// "type" 键不存在,返回默认值
initTableKeyNameDefalut() //配置文件不存在,取默认
return
}
sType := strings.ToLower(modeType.String())
if sType == "default" {
initTableKeyNameDefalut() //取默认方式
} else if sType == "popular" {
initTableKeyNamePopular() //取通俗方式
} else if sType == "custom" {
customSection, err := cfg.GetSection("custom")
if err != nil {
// "mode" 部分不存在,返回默认值
initTableKeyNameDefalut() //自定义配置不存在,取默认
return
}
initTableKeyNameCustom(customSection) //取自定义方式
} else {
initTableKeyNameDefalut() //取默认方式
}
}
// 初始化数据库字段名常量-默认值方式
func initTableKeyNameDefalut() {
tableKeyNameMap = map[string]string{
"BaseSystem": "BaseSystem", //基本数据库库名
"sId": "sId", //数据库表主键名称(字符串形式)
"iId": "iId", //数据库表主键名称(自增长形式)
"uId": "uId", //数据库表主键名称(UUID形式)
"sPid": "sPid", //数据库表字段名称-上级字段名
"sPath": "sPath", //数据库表字段名称-主键路径名
"sName": "sName", //数据库表字段名称-树形节点名
"sCreator": "sCreator", //数据库表字段名称-创建人
"dCreateDate": "dCreateDate", //数据库表字段名称-创建时间
"sModifieder": "sModifieder", //数据库表字段名称-修改人
"dModifiedDate": "dModifiedDate", //数据库表字段名称-修改时间
"iState": "iState", //数据库表字段名称-状态值
"iIndex": "iIndex", //数据库表字段名称-排序值
"iVersion": "iVersion", //数据库表字段名称-版本号
"sPassword": "sPassword", //数据库表字段名称-密码
"iDelSign": "iDelSign", //数据库表字段名称-逻辑删除标识
"iSetp": "iSetp", //数据库表字段名称-步骤值
"sOnlyign": "sOnlyign", //数据库表字段名称-唯一标识
"Dictionary": "Dictionary", //字典表表名
"sValue": "sValue", //字典表值字段名
"sRecordKey": "sRecordKey", //记录验证串字段名
"sSign": "sSign", //标识字段名
"sMemo": "sMemo", //备注字段名
}
initTableKeyNameValue()
}
// 初始化数据库字段名常量-通俗方式
func initTableKeyNamePopular() {
tableKeyNameMap = map[string]string{
"BaseSystem": "base_system", //基本数据库库名
"sId": "id", //数据库表主键名称(字符串形式)
"iId": "id", //数据库表主键名称(自增长形式)
"uId": "uId", //数据库表主键名称(UUID形式)
"sPid": "pid", //数据库表字段名称-上级字段名
"sPath": "path", //数据库表字段名称-主键路径名
"sName": "name", //数据库表字段名称-树形节点名
"sCreator": "creator", //数据库表字段名称-创建人
"dCreateDate": "create_date", //数据库表字段名称-创建时间
"sModifieder": "modifieder", //数据库表字段名称-修改人
"dModifiedDate": "modified_date", //数据库表字段名称-修改时间
"iState": "state", //数据库表字段名称-状态值
"iIndex": "index", //数据库表字段名称-排序值
"iVersion": "version", //数据库表字段名称-版本号
"sPassword": "password", //数据库表字段名称-密码
"iDelSign": "del_sign", //数据库表字段名称-逻辑删除标识
"iSetp": "setp", //数据库表字段名称-步骤值
"sOnlyign": "onlyign", //数据库表字段名称-唯一标识
"Dictionary": "dictionary", //字典表表名
"sValue": "value", //字典表值字段名
"sRecordKey": "record_key", //记录验证串字段名
"sSign": "sign", //标识字段名
"sMemo": "memo", //备注字段名
}
initTableKeyNameValue()
}
// 初始化数据库字段名常量-自定义方式
func initTableKeyNameCustom(section *ini.Section) {
for _, key := range section.Keys() {
tableKeyNameMap[key.Name()] = key.String()
}
initTableKeyNameValue()
}
func initTableKeyNameValue() {
BaseSystemName = tableKeyNameMap["BaseSystem"] //基本数据库库名
TableMajorKeyString = tableKeyNameMap["sId"] //数据库表主键名称(字符串形式)
TableMajorKeyAutoInt = tableKeyNameMap["iId"] //数据库表主键名称(自增长形式)
TableMajorKeyUuId = tableKeyNameMap["uId"] //数据库表主键名称(UUID形式)
TablePidKey = tableKeyNameMap["sPid"] //数据库表字段名称-上级字段名
TablePathKey = tableKeyNameMap["sPath"] //数据库表字段名称-主键路径名
TableTreeNodeName = tableKeyNameMap["sName"] //数据库表字段名称-树形节点名
TableCreatorName = tableKeyNameMap["sCreator"] //数据库表字段名称-创建人
TableCreateDateName = tableKeyNameMap["dCreateDate"] //数据库表字段名称-创建时间
TableModifiederName = tableKeyNameMap["sModifieder"] //数据库表字段名称-修改人
TableModifiedDateName = tableKeyNameMap["dModifiedDate"] //数据库表字段名称-修改时间
TableStateName = tableKeyNameMap["iState"] //数据库表字段名称-状态值
TableIndexName = tableKeyNameMap["iIndex"] //数据库表字段名称-排序值
TableVersionName = tableKeyNameMap["iVersion"] //数据库表字段名称-版本号
TablePasswordName = tableKeyNameMap["sPassword"] //数据库表字段名称-密码
TableDelSignName = tableKeyNameMap["iDelSign"] //数据库表字段名称-逻辑删除标识
TableSetpName = tableKeyNameMap["iSetp"] //数据库表字段名称-步骤值
TableOnlyignName = tableKeyNameMap["sOnlyign"] //数据库表字段名称-唯一标识
TableNameDictionary = tableKeyNameMap["Dictionary"] //字典表表名
TableDictionaryValueName = tableKeyNameMap["sValue"] //字典表值字段名
TableRecordKeyName = tableKeyNameMap["sRecordKey"] //记录验证串字段名
TablesSign = tableKeyNameMap["sSign"] //标识字段名
TablesMemo = tableKeyNameMap["sMemo"] //备注字段名
TableTreeRootValue = "00" //数据库树型表根节点默认值
//------------------------------------------- //
// GtableMajorKeyString = "G" + tableKeyNameMap["sId"] //属性对应数据库表主键名称(字符串形式)
// GtableMajorKeyAutoInt = "G" + tableKeyNameMap["iId"] //属性对应数据库表主键名称(自增长形式)
// GtableMajorKeyUuId = "G" + tableKeyNameMap["uId"] //属性对应数据库表主键名称(UUID形式)
// GtablePidKey = "G" + tableKeyNameMap["sPid"] //属性对应数据库表字段名称-上级字段名
// GtablePathKey = "G" + tableKeyNameMap["sPath"] //属性对应数据库表字段名称-主键路径名
// GtableTreeNodeName = "G" + tableKeyNameMap["sName"] //属性对应数据库表字段名称-树形节点名
// GtableCreatorName = "G" + tableKeyNameMap["sCreator"] //属性对应数据库表字段名称-创建人
// GtableCreateDateName = "G" + tableKeyNameMap["dCreateDate"] //属性对应数据库表字段名称-创建时间
// GtableModifiederName = "G" + tableKeyNameMap["sModifieder"] //属性对应数据库表字段名称-修改人
// GtableModifiedDateName = "G" + tableKeyNameMap["dModifiedDate"] //属性对应数据库表字段名称-修改时间
// GtableStateName = "G" + tableKeyNameMap["iState"] //属性对应数据库表字段名称-状态值
// GtableIndexName = "G" + tableKeyNameMap["iIndex"] //属性对应数据库表字段名称-排序值
// GtableVersionName = "G" + tableKeyNameMap["iVersion"] //属性对应数据库表字段名称-版本号
// GtablePasswordName = "G" + tableKeyNameMap["sPassword"] //属性对应数据库表字段名称-密码
// GtableDelSignName = "G" + tableKeyNameMap["iDelSign"] //属性对应数据库表字段名称-逻辑删除标识
// GtableSetpName = "G" + tableKeyNameMap["iSetp"] //属性对应数据库表字段名称-步骤值
// GtableOnlyignName = "G" + tableKeyNameMap["sOnlyign"] //属性对应数据库表字段名称-唯一标识
// GtableNameDictionary = "G" + tableKeyNameMap["Dictionary"] //属性对应字典表表名
// GtableDictionaryValueName = "G" + tableKeyNameMap["sValue"] //属性对应字典表值字段名
// GtableRecordKeyName = "G" + tableKeyNameMap["sRecordKey"] //属性对应记录验证串字段名
// GtablesSign = "G" + tableKeyNameMap["sSign"] //属性对应标识字段名
// GtablesMemo = "G" + tableKeyNameMap["sMemo"] //属性对应备注字段名
// GBaseSystemName = "G" + tableKeyNameMap["BaseSystem"] //属性对应基本数据库库名
// GGtableTreeRootValue = "00" //属性对应数据库树型表根节点默认值
}
// ----------- 数据库字段名常量 结束 ----------- //
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/tomatomeatman/golang-repository.git
git@gitee.com:tomatomeatman/golang-repository.git
tomatomeatman
golang-repository
GolangRepository
63715d19f9ea

搜索帮助