Add fast path for ValueOf, ReflectValueOf

This commit is contained in:
Jinzhu 2022-02-27 22:10:17 +08:00
parent 4d14ac39ff
commit 530b0a12b4
2 changed files with 44 additions and 27 deletions

View File

@ -465,24 +465,33 @@ func (field *Field) setupValuerAndSetter() {
} }
// ValueOf returns field's value and if it is zero // ValueOf returns field's value and if it is zero
field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) { fieldIndex := field.StructField.Index[0]
v = reflect.Indirect(v) switch {
for _, fieldIdx := range field.StructField.Index { case len(field.StructField.Index) == 1 && fieldIndex > 0:
if fieldIdx >= 0 { field.ValueOf = func(ctx context.Context, value reflect.Value) (interface{}, bool) {
v = v.Field(fieldIdx) fieldValue := reflect.Indirect(value).Field(fieldIndex)
} else { return fieldValue.Interface(), fieldValue.IsZero()
v = v.Field(-fieldIdx - 1) }
default:
if !v.IsNil() { field.ValueOf = func(ctx context.Context, v reflect.Value) (interface{}, bool) {
v = v.Elem() v = reflect.Indirect(v)
for _, fieldIdx := range field.StructField.Index {
if fieldIdx >= 0 {
v = v.Field(fieldIdx)
} else { } else {
return nil, true v = v.Field(-fieldIdx - 1)
if !v.IsNil() {
v = v.Elem()
} else {
return nil, true
}
} }
} }
}
fv, zero := v.Interface(), v.IsZero() fv, zero := v.Interface(), v.IsZero()
return fv, zero return fv, zero
}
} }
if field.Serializer != nil { if field.Serializer != nil {
@ -509,24 +518,31 @@ func (field *Field) setupValuerAndSetter() {
} }
// ReflectValueOf returns field's reflect value // ReflectValueOf returns field's reflect value
field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value { switch {
v = reflect.Indirect(v) case len(field.StructField.Index) == 1 && fieldIndex > 0:
for idx, fieldIdx := range field.StructField.Index { field.ReflectValueOf = func(ctx context.Context, value reflect.Value) reflect.Value {
if fieldIdx >= 0 { return reflect.Indirect(value).Field(fieldIndex)
v = v.Field(fieldIdx) }
} else { default:
v = v.Field(-fieldIdx - 1) field.ReflectValueOf = func(ctx context.Context, v reflect.Value) reflect.Value {
v = reflect.Indirect(v)
for idx, fieldIdx := range field.StructField.Index {
if fieldIdx >= 0 {
v = v.Field(fieldIdx)
} else {
v = v.Field(-fieldIdx - 1)
if v.IsNil() { if v.IsNil() {
v.Set(reflect.New(v.Type().Elem())) v.Set(reflect.New(v.Type().Elem()))
} }
if idx < len(field.StructField.Index)-1 { if idx < len(field.StructField.Index)-1 {
v = v.Elem() v = v.Elem()
}
} }
} }
return v
} }
return v
} }
fallbackSetter := func(ctx context.Context, value reflect.Value, v interface{}, setter func(context.Context, reflect.Value, interface{}) error) (err error) { fallbackSetter := func(ctx context.Context, value reflect.Value, v interface{}, setter func(context.Context, reflect.Value, interface{}) error) (err error) {

View File

@ -3,6 +3,7 @@ module gorm.io/gorm/tests
go 1.14 go 1.14
require ( require (
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/jackc/pgx/v4 v4.15.0 // indirect github.com/jackc/pgx/v4 v4.15.0 // indirect
github.com/jinzhu/now v1.1.4 github.com/jinzhu/now v1.1.4