|
|
@ -0,0 +1,149 @@ |
|
|
|
package helper |
|
|
|
|
|
|
|
import ( |
|
|
|
"errors" |
|
|
|
"fmt" |
|
|
|
"reflect" |
|
|
|
) |
|
|
|
|
|
|
|
// 结构体泛型提取关键数据
|
|
|
|
// desk结构体, input提取数据源, columnKey提取的字段,indexKey提取的下标
|
|
|
|
func StructColumn(desk, input interface{}, columnKey, indexKey string) (err error) { |
|
|
|
deskValue := reflect.ValueOf(desk) |
|
|
|
if deskValue.Kind() != reflect.Ptr { |
|
|
|
return errors.New("desk must be ptr") |
|
|
|
} |
|
|
|
|
|
|
|
rv := reflect.ValueOf(input) |
|
|
|
if rv.Kind() != reflect.Slice && rv.Kind() != reflect.Array { |
|
|
|
return errors.New("input must be map slice or array") |
|
|
|
} |
|
|
|
|
|
|
|
rt := reflect.TypeOf(input) |
|
|
|
if rt.Elem().Kind() != reflect.Struct { |
|
|
|
return errors.New("input's elem must be struct") |
|
|
|
} |
|
|
|
|
|
|
|
if len(indexKey) > 0 { |
|
|
|
return structIndexColumn(desk, input, columnKey, indexKey) |
|
|
|
} |
|
|
|
return structColumn(desk, input, columnKey) |
|
|
|
} |
|
|
|
|
|
|
|
func structColumn(desk, input interface{}, columnKey string) (err error) { |
|
|
|
if len(columnKey) == 0 { |
|
|
|
return errors.New("columnKey cannot not be empty") |
|
|
|
} |
|
|
|
|
|
|
|
deskElemType := reflect.TypeOf(desk).Elem() |
|
|
|
if deskElemType.Kind() != reflect.Slice { |
|
|
|
return errors.New("desk must be slice") |
|
|
|
} |
|
|
|
|
|
|
|
rv := reflect.ValueOf(input) |
|
|
|
rt := reflect.TypeOf(input) |
|
|
|
|
|
|
|
var columnVal reflect.Value |
|
|
|
deskValue := reflect.ValueOf(desk) |
|
|
|
direct := reflect.Indirect(deskValue) |
|
|
|
|
|
|
|
for i := 0; i < rv.Len(); i++ { |
|
|
|
columnVal, err = findStructValByColumnKey(rv.Index(i), rt.Elem(), columnKey) |
|
|
|
if err != nil { |
|
|
|
return |
|
|
|
} |
|
|
|
if deskElemType.Elem().Kind() != columnVal.Kind() { |
|
|
|
return errors.New(fmt.Sprintf("your slice must be []%s", columnVal.Kind())) |
|
|
|
} |
|
|
|
|
|
|
|
direct.Set(reflect.Append(direct, columnVal)) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func findStructValByColumnKey(curVal reflect.Value, elemType reflect.Type, columnKey string) (columnVal reflect.Value, err error) { |
|
|
|
columnExist := false |
|
|
|
for i := 0; i < elemType.NumField(); i++ { |
|
|
|
curField := curVal.Field(i) |
|
|
|
if elemType.Field(i).Name == columnKey { |
|
|
|
columnExist = true |
|
|
|
columnVal = curField |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
if !columnExist { |
|
|
|
return columnVal, errors.New(fmt.Sprintf("columnKey %s not found in %s's field", columnKey, elemType)) |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func structIndexColumn(desk, input interface{}, columnKey, indexKey string) (err error) { |
|
|
|
deskValue := reflect.ValueOf(desk) |
|
|
|
if deskValue.Elem().Kind() != reflect.Map { |
|
|
|
return errors.New("desk must be map") |
|
|
|
} |
|
|
|
deskElem := deskValue.Type().Elem() |
|
|
|
if len(columnKey) == 0 && deskElem.Elem().Kind() != reflect.Struct { |
|
|
|
return errors.New(fmt.Sprintf("desk's elem expect struct, got %s", deskElem.Elem().Kind())) |
|
|
|
} |
|
|
|
|
|
|
|
rv := reflect.ValueOf(input) |
|
|
|
rt := reflect.TypeOf(input) |
|
|
|
elemType := rt.Elem() |
|
|
|
|
|
|
|
var indexVal, columnVal reflect.Value |
|
|
|
direct := reflect.Indirect(deskValue) |
|
|
|
mapReflect := reflect.MakeMap(deskElem) |
|
|
|
deskKey := deskValue.Type().Elem().Key() |
|
|
|
|
|
|
|
for i := 0; i < rv.Len(); i++ { |
|
|
|
curVal := rv.Index(i) |
|
|
|
indexVal, columnVal, err = findStructValByIndexKey(curVal, elemType, indexKey, columnKey) |
|
|
|
if err != nil { |
|
|
|
return |
|
|
|
} |
|
|
|
if deskKey.Kind() != indexVal.Kind() { |
|
|
|
return errors.New(fmt.Sprintf("cant't convert %s to %s, your map'key must be %s", indexVal.Kind(), deskKey.Kind(), indexVal.Kind())) |
|
|
|
} |
|
|
|
if len(columnKey) == 0 { |
|
|
|
mapReflect.SetMapIndex(indexVal, curVal) |
|
|
|
direct.Set(mapReflect) |
|
|
|
} else { |
|
|
|
if deskElem.Elem().Kind() != columnVal.Kind() { |
|
|
|
return errors.New(fmt.Sprintf("your map must be map[%s]%s", indexVal.Kind(), columnVal.Kind())) |
|
|
|
} |
|
|
|
mapReflect.SetMapIndex(indexVal, columnVal) |
|
|
|
direct.Set(mapReflect) |
|
|
|
} |
|
|
|
} |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
func findStructValByIndexKey(curVal reflect.Value, elemType reflect.Type, indexKey, columnKey string) (indexVal, columnVal reflect.Value, err error) { |
|
|
|
indexExist := false |
|
|
|
columnExist := false |
|
|
|
for i := 0; i < elemType.NumField(); i++ { |
|
|
|
curField := curVal.Field(i) |
|
|
|
if elemType.Field(i).Name == indexKey { |
|
|
|
switch curField.Kind() { |
|
|
|
case reflect.String, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int, reflect.Float64, reflect.Float32: |
|
|
|
indexExist = true |
|
|
|
indexVal = curField |
|
|
|
default: |
|
|
|
return indexVal, columnVal, errors.New("indexKey must be int float or string") |
|
|
|
} |
|
|
|
} |
|
|
|
if elemType.Field(i).Name == columnKey { |
|
|
|
columnExist = true |
|
|
|
columnVal = curField |
|
|
|
continue |
|
|
|
} |
|
|
|
} |
|
|
|
if !indexExist { |
|
|
|
return indexVal, columnVal, errors.New(fmt.Sprintf("indexKey %s not found in %s's field", indexKey, elemType)) |
|
|
|
} |
|
|
|
if len(columnKey) > 0 && !columnExist { |
|
|
|
return indexVal, columnVal, errors.New(fmt.Sprintf("columnKey %s not found in %s's field", columnKey, elemType)) |
|
|
|
} |
|
|
|
return |
|
|
|
} |