golang mysql 内嵌_golang操作mysql聚合结果

这里是基于github.com/gocraft/dbr三方库的改进,该三方库不支持不支持对mysql查询结果聚合。

原始方法如下:

// Load loads any value from sql.Rows

func Load(rows *sql.Rows, value interface{}) (int, error) {

defer rows.Close()

column, err := rows.Columns()

if err != nil {

return 0, err

}

v := reflect.ValueOf(value)

if v.Kind() != reflect.Ptr || v.IsNil() {

return 0, ErrInvalidPointer

}

v = v.Elem()

isSlice := v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8

count := 0

for rows.Next() {

var elem reflect.Value

if isSlice {

elem = reflect.New(v.Type().Elem()).Elem()

} else {

elem = v

}

ptr, err := findPtr(column, elem)

if err != nil {

return 0, err

}

err = rows.Scan(ptr...)

if err != nil {

return 0, err

}

count++

if isSlice {

v.Set(reflect.Append(v, elem))

} else {

break

}

}

return count, nil

}

type dummyScanner struct{}

func (dummyScanner) Scan(interface{}) error {

return nil

}

var (

dummyDest sql.Scanner = dummyScanner{}

typeScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem()

)

func findPtr(column []string, value reflect.Value) ([]interface{}, error) {

if value.Addr().Type().Implements(typeScanner) {

return []interface{}{value.Addr().Interface()}, nil

}

switch value.Kind() {

case reflect.Struct:

var ptr []interface{}

m := structMap(value)

for _, key := range column {

if val, ok := m[key]; ok {

ptr = append(ptr, val.Addr().Interface())

} else {

ptr = append(ptr, dummyDest)

}

}

return ptr, nil

case reflect.Ptr:

if value.IsNil() {

value.Set(reflect.New(value.Type().Elem()))

}

return findPtr(column, value.Elem())

}

return []interface{}{value.Addr().Interface()}, nil

}

改进方法如下:

//当存在聚合结果的时候调用api 如果没有聚合 建议使用dbr的load接口

func Load(rows *sql.Rows, value interface{}) (int, error) {

defer rows.Close()

columns, err := rows.Columns()

if err != nil {

return 0, err

}

v := reflect.ValueOf(value)

if v.Kind() != reflect.Ptr || v.IsNil() {

return 0, dbr.ErrInvalidPointer

}

v = v.Elem()

isSlice := v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8

//if !isSlice {

// return 0, dbr.ErrInvalidPointer

//}

count := 0

for rows.Next() {

scanResultContainers := make([]interface{}, len(columns))

for i := 0; i < len(columns); i++ {

var scanResultContainer interface{}

scanResultContainers[i] = &scanResultContainer

}

err = rows.Scan(scanResultContainers...)

if err != nil {

return 0, err

}

rowStr := make(map[string]string)

for k, v := range columns {

if scanResultContainers[k] == nil {

continue

}

rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[k]))

if rawValue.Interface() == nil {

continue

}

resstr := ""

resstr, err = Reflect2value(&rawValue, false)

if err != nil {

return 0, err

}

rowStr[v] = resstr

}

var elem reflect.Value

if isSlice {

elem = reflect.New(v.Type().Elem()).Elem()

} else {

elem = reflect.New(v.Type()).Elem()

}

destPtrMap := make(map[string]interface{})

err = mapStr2Struct(rowStr, elem, destPtrMap)

if err != nil {

return 0, err

}

count++

if isSlice {

if v.Len() == 0 {

v.Set(reflect.Append(v, elem))

} else {

vv := v.Index(v.Len() - 1)

if !togetherSlice(elem, vv) {

v.Set(reflect.Append(v, elem))

}

}

} else {

if count == 1 {

v.Set(elem)

} else {

if !togetherSlice(elem, v) {

return 0, errors.New("传入对象不是一个数组,合并后超过两条")

}

}

}

}

return count, nil

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值