在業務中,我們常常有一些查詢是根據某些條件來的,比如在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 })