ecodeclub / eorm

简单 ORM 框架
Apache License 2.0
194 stars 64 forks source link

valuer/unsafe:删除对不同类型的特殊处理,直接依赖于 reflect.NewAt #85

Closed flycash closed 2 years ago

flycash commented 2 years ago

仅限中文

使用场景

早期我在设计 eorm 处理结果集的部分的时候,最开始的想法是引入一个中间表达:

image

即我们最开始读取返回的查询结果集,我们使用 []byte 来接收,这个是一个中间表达。通过这样一个中间表达,我们可以在将结果集拼装成对象之前,做一些事情。

但是后来我发现这里面有两个缺点:

所以最终我又去掉了这个中间表达,但是代码里面还有一些遗留代码。

这一次我们将去掉 valuer/unsafe 里面的相关代码:

func (u unsafeValue) Field(name string) (interface{}, error) {
    fd, ok := u.meta.FieldMap[name]
    if !ok {
        return nil, errs.NewInvalidFieldError(name)
    }
    ptr := unsafe.Pointer(uintptr(u.addr) + fd.Offset)
    if fd.IsHolderType {
        val := reflect.NewAt(fd.Typ, ptr).Elem()
        return val.Interface(), nil
    }
    switch fd.Typ.Kind() {
    case reflect.Bool:
        return *(*bool)(ptr), nil
    case reflect.Int:
        return *(*int)(ptr), nil
    case reflect.Int8:
        return *(*int8)(ptr), nil
    case reflect.Int16:
        return *(*int16)(ptr), nil
    case reflect.Int32:
        return *(*int32)(ptr), nil
    case reflect.Int64:
        return *(*int64)(ptr), nil
    case reflect.Uint:
        return *(*uint)(ptr), nil
    case reflect.Uint8:
        return *(*uint8)(ptr), nil
    case reflect.Uint16:
        return *(*uint16)(ptr), nil
    case reflect.Uint32:
        return *(*uint32)(ptr), nil
    case reflect.Uint64:
        return *(*uint64)(ptr), nil
    case reflect.Float32:
        return *(*float32)(ptr), nil
    case reflect.Float64:
        return *(*float64)(ptr), nil
    case reflect.String:
        return *(*string)(ptr), nil
    case reflect.Slice:
        // Array 只有一种可能,那就是 []byte
        return *(*[]byte)(ptr), nil
    case reflect.Pointer:
        ele := fd.Typ.Elem()
        switch ele.Kind() {
        case reflect.Bool:
            return *(**bool)(ptr), nil
        case reflect.Int:
            return *(**int)(ptr), nil
        case reflect.Int8:
            return *(**int8)(ptr), nil
        case reflect.Int16:
            return *(**int16)(ptr), nil
        case reflect.Int32:
            return *(**int32)(ptr), nil
        case reflect.Int64:
            return *(**int64)(ptr), nil
        case reflect.Uint:
            return *(**uint)(ptr), nil
        case reflect.Uint8:
            return *(**uint8)(ptr), nil
        case reflect.Uint16:
            return *(**uint16)(ptr), nil
        case reflect.Uint32:
            return *(**uint32)(ptr), nil
        case reflect.Uint64:
            return *(**uint64)(ptr), nil
        case reflect.Float32:
            return *(**float32)(ptr), nil
        case reflect.Float64:
            return *(**float64)(ptr), nil
        default:
            return nil, errs.NewUnsupportedTypeError(fd.Typ)
        }
    default:
        return nil, errs.NewUnsupportedTypeError(fd.Typ)
    }
}

这一大堆的 switch case,就是在引入中间结果 []byte 之后遗留产物,包括对 IsHolderType 的处理也是。

这个时候我们可以直接删除掉大部分代码:

func (u unsafeValue) Field(name string) (interface{}, error) {
    fd, ok := u.meta.FieldMap[name]
    if !ok {
        return nil, errs.NewInvalidFieldError(name)
    }
    ptr := unsafe.Pointer(uintptr(u.addr) + fd.Offset)
        val := reflect.NewAt(fd.Typ, ptr).Elem()
    return val.Interface(), nil
}

其它

任何你觉得有利于解决问题的补充说明

你使用的是 eorm 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果