From 00ccce7bb8a12107df256d54ef9374c36ad3df6f Mon Sep 17 00:00:00 2001 From: John Guo Date: Thu, 17 Feb 2022 22:02:51 +0800 Subject: [PATCH] fix issue #1607 --- util/gconv/gconv.go | 4 +--- util/gconv/gconv_struct.go | 11 +++++----- util/gconv/gconv_z_unit_scan_test.go | 31 +++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index 358ba5a06..8ca25c547 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -279,9 +279,7 @@ func doConvert(in doConvertInput) interface{} { default: if in.ReferValue != nil { - var ( - referReflectValue reflect.Value - ) + var referReflectValue reflect.Value if v, ok := in.ReferValue.(reflect.Value); ok { referReflectValue = v } else { diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index e73026549..aaddf01be 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -338,6 +338,12 @@ func bindVarToStructAttr(elem reflect.Value, name string, value interface{}, map if empty.IsNil(value) { structFieldValue.Set(reflect.Zero(structFieldValue.Type())) } else { + // Common interface check. + var ok bool + if err, ok = bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok { + return err + } + // Default converting. structFieldValue.Set(reflect.ValueOf(doConvert( doConvertInput{ FromValue: value, @@ -420,11 +426,6 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma return nil } - // Common interface check. - if err, ok = bindVarToReflectValueWithInterfaceCheck(structFieldValue, value); ok { - return err - } - kind := structFieldValue.Kind() // Converting using interface, for some kinds. switch kind { diff --git a/util/gconv/gconv_z_unit_scan_test.go b/util/gconv/gconv_z_unit_scan_test.go index e34f91d99..12d488d90 100644 --- a/util/gconv/gconv_z_unit_scan_test.go +++ b/util/gconv/gconv_z_unit_scan_test.go @@ -8,11 +8,13 @@ package gconv_test import ( "fmt" + "math/big" + "testing" + "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/gconv" - "testing" ) func Test_Scan_StructStructs(t *testing.T) { @@ -601,3 +603,30 @@ func Test_ScanList_Embedded(t *testing.T) { t.Assert(len(entities[2].UserScores), 0) }) } + +type Float64 float64 + +func (f *Float64) UnmarshalValue(value interface{}) error { + if v, ok := value.(*big.Rat); ok { + f64, _ := v.Float64() + *f = Float64(f64) + } + return nil +} + +func Test_Issue1607(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + type Demo struct { + B Float64 + } + rat := &big.Rat{} + rat.SetFloat64(1.5) + + var demos = make([]Demo, 1) + err := gconv.Scan([]map[string]interface{}{ + {"A": 1, "B": rat}, + }, &demos) + t.AssertNil(err) + t.Assert(demos[0].B, 1.5) + }) +}