123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- package util
- import (
- "database/sql"
- "errors"
- "fmt"
- "reflect"
- "strconv"
- "strings"
- )
- func ScanStruct(rows *sql.Rows, dest interface{}) error {
- rv := reflect.ValueOf(dest)
- if rv.Kind() != reflect.Ptr {
- return errors.New("must pass a pointer, not a value, to StructScan destination")
- }
- if rv.IsNil() {
- return errors.New("nil pointer passed to StructScan destination")
- }
- direct := rv.Elem()
- dtype := direct.Type()
- if dtype.Kind() != reflect.Slice {
- return fmt.Errorf("expected %s but got %s", reflect.Slice, dtype.Kind())
- }
- elemType := dtype.Elem()
- var (
- field reflect.StructField
- fmap = map[string]TagIndex{}
- dbtagVal string
- tagSplits []string
- fimap = map[TagIndex]int{}
- )
- cols, _ := rows.Columns()
- for i := 0; i < elemType.NumField(); i++ {
- field = elemType.Field(i)
- dbtagVal = field.Tag.Get("db")
- if dbtagVal == "null" {
- continue
- }
- tagIdx := TagIndex{}
- tagSplits = strings.Split(dbtagVal, ",")
- if len(tagSplits) > 1 {
- dbtagVal = tagSplits[0]
- if tagSplits[1] == "omitempty" {
- tagIdx.IsOmitEmpty = true
- }
- }
- if dbtagVal == "" {
- dbtagVal = field.Name
- }
- tagIdx.Idx = i
- fmap[dbtagVal] = tagIdx
- }
- var (
- tempStr sql.NullString
- valArr []interface{}
- )
- for rows.Next() {
- nelemVal := reflect.New(elemType)
- valArr = make([]interface{}, len(cols))
- for i, col := range cols {
- if fieldIdx, ok := fmap[col]; !ok {
- valArr[i] = new(interface{})
- } else {
- field = elemType.Field(fieldIdx.Idx)
- if fieldIdx.IsOmitEmpty {
- valArr[i] = &sql.NullString{}
- fimap[fieldIdx] = i
- } else {
- valArr[i] = nelemVal.Elem().Field(fieldIdx.Idx).Addr().Interface()
- }
- }
- }
- rows.Scan(valArr...)
- for k, v := range fimap {
- fval := reflect.ValueOf(valArr[v])
- if fval.IsValid() {
- field := elemType.Field(k.Idx)
- dstFval := reflect.New(field.Type)
- tempStr = fval.Elem().Interface().(sql.NullString)
- if !tempStr.Valid {
- continue
- }
- switch field.Type.Kind() {
- case reflect.Float64:
- float, _ := strconv.ParseFloat(tempStr.String, 64)
- float = ToFix(float, 2)
- dstFval.Elem().Set(reflect.ValueOf(float))
- case reflect.String:
- dstFval.Elem().Set(reflect.ValueOf(tempStr.String))
- case reflect.Int:
- intVal, _ := strconv.ParseInt(tempStr.String, 10, 0)
- dstFval.Elem().Set(reflect.ValueOf(int(intVal)))
- }
- //fmt.Println(dstFval.Elem().Interface())
- nelemVal.Elem().Field(k.Idx).Set(dstFval.Elem())
- }
- }
- direct.Set(reflect.Append(direct, nelemVal.Elem()))
- }
- return nil
- }
|