Go中的list数组筛选
在业务中,我们常常有一些查询是根据某些条件来的,比如在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 })