diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index 75a16afc9..19d838a2f 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -296,6 +296,9 @@ func Bytes(any interface{}) []byte { case []byte: return value default: + if f, ok := value.(apiBytes); ok { + return f.Bytes() + } return gbinary.Encode(any) } } @@ -439,6 +442,9 @@ func Bool(any interface{}) bool { } return true default: + if f, ok := value.(apiBool); ok { + return f.Bool() + } rv := reflect.ValueOf(any) switch rv.Kind() { case reflect.Ptr: @@ -543,6 +549,9 @@ func Int64(any interface{}) int64 { case []byte: return gbinary.DecodeToInt64(value) default: + if f, ok := value.(apiInt64); ok { + return f.Int64() + } s := String(value) isMinus := false if len(s) > 0 { @@ -665,6 +674,9 @@ func Uint64(any interface{}) uint64 { case []byte: return gbinary.DecodeToUint64(value) default: + if f, ok := value.(apiUint64); ok { + return f.Uint64() + } s := String(value) // Hexadecimal if len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') { @@ -700,6 +712,9 @@ func Float32(any interface{}) float32 { case []byte: return gbinary.DecodeToFloat32(value) default: + if f, ok := value.(apiFloat32); ok { + return f.Float32() + } v, _ := strconv.ParseFloat(String(any), 64) return float32(v) } @@ -718,6 +733,9 @@ func Float64(any interface{}) float64 { case []byte: return gbinary.DecodeToFloat64(value) default: + if f, ok := value.(apiFloat64); ok { + return f.Float64() + } v, _ := strconv.ParseFloat(String(any), 64) return v } diff --git a/util/gconv/gconv_interface.go b/util/gconv/gconv_interface.go index 9ff344889..8ddbe7c3b 100644 --- a/util/gconv/gconv_interface.go +++ b/util/gconv/gconv_interface.go @@ -11,11 +11,41 @@ type apiString interface { String() string } +// apiBool is used for type assert api for Bool(). +type apiBool interface { + Bool() bool +} + +// apiInt64 is used for type assert api for Int64(). +type apiInt64 interface { + Int64() int64 +} + +// apiUint64 is used for type assert api for Uint64(). +type apiUint64 interface { + Uint64() uint64 +} + +// apiFloat32 is used for type assert api for Float32(). +type apiFloat32 interface { + Float32() float32 +} + +// apiFloat64 is used for type assert api for Float64(). +type apiFloat64 interface { + Float64() float64 +} + // apiError is used for type assert api for Error(). type apiError interface { Error() string } +// apiBytes is used for type assert api for Bytes(). +type apiBytes interface { + Bytes() []byte +} + // apiInterfaces is used for type assert api for Interfaces(). type apiInterfaces interface { Interfaces() []interface{} diff --git a/util/gconv/gconv_z_unit_struct_test.go b/util/gconv/gconv_z_unit_struct_test.go index 6c08a6d21..062c17d50 100644 --- a/util/gconv/gconv_z_unit_struct_test.go +++ b/util/gconv/gconv_z_unit_struct_test.go @@ -7,6 +7,7 @@ package gconv_test import ( + "github.com/gogf/gf/container/gvar" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/internal/json" "github.com/gogf/gf/os/gtime" @@ -1139,3 +1140,27 @@ func Test_Struct_JsonParam(t *testing.T) { t.Assert(a.Name, "john") }) } + +func Test_Struct_GVarAttribute(t *testing.T) { + type A struct { + Id int `json:"id"` + Name string `json:"name"` + Status bool `json:"status"` + } + gtest.C(t, func(t *gtest.T) { + var ( + a = A{} + data = g.Map{ + "id": 100, + "name": "john", + "status": gvar.New(false), + } + ) + err := gconv.Struct(data, &a) + t.Assert(err, nil) + t.Assert(a.Id, data["id"]) + t.Assert(a.Name, data["name"]) + t.Assert(a.Status, data["status"]) + }) + +}