在业务中,我们常常有一些查询是根据某些条件来的,比如在list数据中根据条件匹配相应的数据,常用的做法是通过for循环,然后通过成员单个单个的比较,为方便通用,通过反射做出封装
封装相关方法:
//筛选数组
func GetListByParam(list []interface{}, result interface{}, param map[string]interface{}) error {
if list == nil {
return errors.New("source data is nil")
}
if param == nil {
return errors.New("param is nil")
}
var resultArr []interface{}
for _, value := range list {
refValue := reflect.ValueOf(value)
isHave := true
for key, item := range param {
fieldValue := refValue.FieldByName(key).Interface()
if fieldValue != item {
isHave = false
break
} else {
isHave = true
}
}
if isHave {
resultArr = append(resultArr, value)
}
}
err := InterfaceArrToStructArr(resultArr, result)
if err != nil {
return err
}
return nil
}
//获取结构体有值的成员
func GetStructMember(model interface{}) (map[string]interface{}, error) {
if model == nil {
return nil, errors.New("model is nil")
}
resultmap := make(map[string]interface{})
if model != nil {
refValue := reflect.ValueOf(model)
refType := reflect.TypeOf(model)
fieldCount := refValue.NumField()
for i := 0; i < fieldCount; i++ {
fieldType := refType.Field(i)
fieldValue := refValue.Field(i)
isadd := false
switch fieldType.Type.String() {
case "string":
if fieldValue.Len() > 0 {
isadd = true
}
case "int", "int8", "int16", "int32", "int64":
if fieldValue.Int() != 0 {
isadd = true
}
case "time.Time":
valTime := fieldValue.Interface().(time.Time)
if !CheckIsDefaultTime(valTime) {
isadd = true
}
}
if isadd {
resultmap[refType.Field(i).Name] = fieldValue.Interface()
}
}
}
return resultmap, nil
}
//InterfaceArrToStructArr Interface数组转为结构体数组
func InterfaceArrToStructArr(src []interface{}, model interface{}) error {
val := reflect.Indirect(reflect.ValueOf(model))
typ := val.Type()
for _, r := range src {
mVal := reflect.Indirect(reflect.New(typ.Elem().Elem())).Addr()
fmt.Println(r)
fmt.Println(mVal.Interface())
IntfaceToStruct(r, mVal.Interface())
val = reflect.Append(val, mVal)
}
DeepCopy(model, val.Interface())
return nil
}
//IntfaceToStruct IntfaceToStruct 通过json过渡,结构体互相转化
func IntfaceToStruct(mapSrc interface{}, dst interface{}) error {
//待优化
bytes, err := json.Marshal(mapSrc)
err = json.Unmarshal(bytes, &dst)
return err
}
func DeepCopy(dst, src interface{}) error {
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(src); err != nil {
return err
}
return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst)
}
调用方式:
model = &hostmodels.HostsModel{Gid: 1, CdnName: ""}
results := make([]*hostmodels.HostsModel, 0)
list := make([]interface{}, 0)
list = append(list,new(hostmodels.HostsModel){})
mapQuery, _ := GetStructMember(*model)
err = GetListByParam(list, &results, mapQuery)
if err != nil {
return nil, err
}
//排序
sort.SliceStable(results, func(i, j int) bool {
return results[i].Gid < results[j].Gid
})
