From b6ab1a992cac618384e79ea6bbd9c21fa516e633 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 25 May 2020 14:26:08 +0800 Subject: [PATCH] improve empty checks for common interfaces implementer --- container/gmap/gmap_z_unit_any_any_test.go | 18 ++++++-- internal/empty/empty.go | 25 ++++++++++ util/gconv/gconv.go | 10 ---- util/gconv/gconv_interface.go | 53 ++++++++++++++++++++++ util/gconv/gconv_map.go | 5 -- util/gconv/gconv_slice_any.go | 5 -- util/gconv/gconv_slice_float.go | 5 -- util/gconv/gconv_slice_int.go | 5 -- util/gconv/gconv_slice_str.go | 5 -- util/gconv/gconv_slice_uint.go | 5 -- util/gconv/gconv_struct.go | 6 --- 11 files changed, 93 insertions(+), 49 deletions(-) create mode 100644 util/gconv/gconv_interface.go diff --git a/container/gmap/gmap_z_unit_any_any_test.go b/container/gmap/gmap_z_unit_any_any_test.go index 88fd41daa..5418959a8 100644 --- a/container/gmap/gmap_z_unit_any_any_test.go +++ b/container/gmap/gmap_z_unit_any_any_test.go @@ -9,12 +9,12 @@ package gmap_test import ( "encoding/json" "github.com/gogf/gf/container/garray" + "github.com/gogf/gf/container/gmap" "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/test/gtest" "github.com/gogf/gf/util/gconv" "testing" - - "github.com/gogf/gf/container/gmap" - "github.com/gogf/gf/test/gtest" + "time" ) func Test_AnyAnyMap_Var(t *testing.T) { @@ -218,6 +218,18 @@ func Test_AnyAnyMap_FilterEmpty(t *testing.T) { t.Assert(m.Get(1), nil) t.Assert(m.Get(2), 2) }) + gtest.C(t, func(t *gtest.T) { + m := gmap.NewAnyAnyMap() + m.Set(1, 0) + m.Set("time1", time.Time{}) + m.Set("time2", time.Now()) + t.Assert(m.Get(1), 0) + t.Assert(m.Get("time1"), time.Time{}) + m.FilterEmpty() + t.Assert(m.Get(1), nil) + t.Assert(m.Get("time1"), nil) + t.AssertNE(m.Get("time2"), nil) + }) } func Test_AnyAnyMap_Json(t *testing.T) { diff --git a/internal/empty/empty.go b/internal/empty/empty.go index 4225085fe..378cdb4d7 100644 --- a/internal/empty/empty.go +++ b/internal/empty/empty.go @@ -11,6 +11,21 @@ import ( "reflect" ) +// apiString is used for type assert api for String(). +type apiString interface { + String() string +} + +// apiInterfaces is used for type assert api for Interfaces. +type apiInterfaces interface { + Interfaces() []interface{} +} + +// apiMapStrAny is the interface support for converting struct parameter to map. +type apiMapStrAny interface { + MapStrAny() map[string]interface{} +} + // IsEmpty checks whether given empty. // It returns true if is in: 0, nil, false, "", len(slice/map/chan) == 0, // or else it returns false. @@ -52,6 +67,16 @@ func IsEmpty(value interface{}) bool { case []rune: return len(value) == 0 default: + // Common interfaces checks. + if f, ok := value.(apiString); ok { + return f.String() == "" + } + if f, ok := value.(apiInterfaces); ok { + return len(f.Interfaces()) == 0 + } + if f, ok := value.(apiMapStrAny); ok { + return len(f.MapStrAny()) == 0 + } // Finally using reflect. var rv reflect.Value if v, ok := value.(reflect.Value); ok { diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index a14f2eabe..cfc0bdda0 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -19,16 +19,6 @@ import ( "github.com/gogf/gf/encoding/gbinary" ) -// Type assert api for String(). -type apiString interface { - String() string -} - -// Type assert api for Error(). -type apiError interface { - Error() string -} - var ( // Empty strings. emptyStringMap = map[string]struct{}{ diff --git a/util/gconv/gconv_interface.go b/util/gconv/gconv_interface.go new file mode 100644 index 000000000..b10a600cf --- /dev/null +++ b/util/gconv/gconv_interface.go @@ -0,0 +1,53 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gconv + +// apiString is used for type assert api for String(). +type apiString interface { + String() string +} + +// apiError is used for type assert api for Error(). +type apiError interface { + Error() string +} + +// apiInterfaces is used for type assert api for Interfaces(). +type apiInterfaces interface { + Interfaces() []interface{} +} + +// apiFloats is used for type assert api for Floats(). +type apiFloats interface { + Floats() []float64 +} + +// apiInts is used for type assert api for Ints(). +type apiInts interface { + Ints() []int +} + +// apiStrings is used for type assert api for Strings(). +type apiStrings interface { + Strings() []string +} + +// apiUints is used for type assert api for Uints(). +type apiUints interface { + Uints() []uint +} + +// apiMapStrAny is the interface support for converting struct parameter to map. +type apiMapStrAny interface { + MapStrAny() map[string]interface{} +} + +// apiUnmarshalValue is the interface for custom defined types customizing value assignment. +// Note that only pointer can implement interface apiUnmarshalValue. +type apiUnmarshalValue interface { + UnmarshalValue(interface{}) error +} diff --git a/util/gconv/gconv_map.go b/util/gconv/gconv_map.go index 7e76515ef..f13889d86 100644 --- a/util/gconv/gconv_map.go +++ b/util/gconv/gconv_map.go @@ -17,11 +17,6 @@ import ( "github.com/gogf/gf/internal/utils" ) -// apiMapStrAny is the interface support for converting struct parameter to map. -type apiMapStrAny interface { - MapStrAny() map[string]interface{} -} - // Map converts any variable to map[string]interface{}. If the parameter is not a // map/struct/*struct type, then the conversion will fail and returns nil. // diff --git a/util/gconv/gconv_slice_any.go b/util/gconv/gconv_slice_any.go index 959845a20..bad33630c 100644 --- a/util/gconv/gconv_slice_any.go +++ b/util/gconv/gconv_slice_any.go @@ -11,11 +11,6 @@ import ( "reflect" ) -// apiInterfaces is used for type assert api for Interfaces. -type apiInterfaces interface { - Interfaces() []interface{} -} - // SliceAny is alias of Interfaces. func SliceAny(i interface{}) []interface{} { return Interfaces(i) diff --git a/util/gconv/gconv_slice_float.go b/util/gconv/gconv_slice_float.go index eac270fc8..44f95cced 100644 --- a/util/gconv/gconv_slice_float.go +++ b/util/gconv/gconv_slice_float.go @@ -6,11 +6,6 @@ package gconv -// apiFloats is used for type assert api for Floats. -type apiFloats interface { - Floats() []float64 -} - // SliceFloat is alias of Floats. func SliceFloat(i interface{}) []float64 { return Floats(i) diff --git a/util/gconv/gconv_slice_int.go b/util/gconv/gconv_slice_int.go index 64fe50517..9116c1089 100644 --- a/util/gconv/gconv_slice_int.go +++ b/util/gconv/gconv_slice_int.go @@ -6,11 +6,6 @@ package gconv -// apiInts is used for type assert api for Ints. -type apiInts interface { - Ints() []int -} - // SliceInt is alias of Ints. func SliceInt(i interface{}) []int { return Ints(i) diff --git a/util/gconv/gconv_slice_str.go b/util/gconv/gconv_slice_str.go index b830fe61b..cb7bc2b6c 100644 --- a/util/gconv/gconv_slice_str.go +++ b/util/gconv/gconv_slice_str.go @@ -6,11 +6,6 @@ package gconv -// apiStrings is used for type assert api for Strings. -type apiStrings interface { - Strings() []string -} - // SliceStr is alias of Strings. func SliceStr(i interface{}) []string { return Strings(i) diff --git a/util/gconv/gconv_slice_uint.go b/util/gconv/gconv_slice_uint.go index f9095e618..a65fb4f6d 100644 --- a/util/gconv/gconv_slice_uint.go +++ b/util/gconv/gconv_slice_uint.go @@ -6,11 +6,6 @@ package gconv -// apiUints is used for type assert api for Uints. -type apiUints interface { - Uints() []uint -} - // SliceUint is alias of Uints. func SliceUint(i interface{}) []uint { return Uints(i) diff --git a/util/gconv/gconv_struct.go b/util/gconv/gconv_struct.go index da536327b..1c613130c 100644 --- a/util/gconv/gconv_struct.go +++ b/util/gconv/gconv_struct.go @@ -19,12 +19,6 @@ import ( "github.com/gogf/gf/internal/utils" ) -// apiUnmarshalValue is the interface for custom defined types customizing value assignment. -// Note that only pointer can implement interface apiUnmarshalValue. -type apiUnmarshalValue interface { - UnmarshalValue(interface{}) error -} - var ( // replaceCharReg is the regular expression object for replacing chars // in map keys and attribute names.