|
|
- 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
- }
|