structure: add IsZero() back that checks all fields
This commit is contained in:
parent
301494b442
commit
241e969210
@ -51,11 +51,16 @@ n := structure.Name(s)
|
|||||||
// => true
|
// => true
|
||||||
h := structure.Has(s, "Enabled")
|
h := structure.Has(s, "Enabled")
|
||||||
|
|
||||||
// Check if any field of a struct is initialized or not.
|
// Check if a field of a struct is initialized or not.
|
||||||
if structure.HasZero(s) {
|
if structure.HasZero(s) {
|
||||||
fmt.Println("s has a zero value field")
|
fmt.Println("s has a zero value field")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if all field of a struct is initialized or not.
|
||||||
|
if structure.IsZero(s) {
|
||||||
|
fmt.Println("all fields of s is zero value")
|
||||||
|
}
|
||||||
|
|
||||||
// Check if it's a struct or a pointer to struct
|
// Check if it's a struct or a pointer to struct
|
||||||
if structure.IsStruct(s) {
|
if structure.IsStruct(s) {
|
||||||
fmt.Println("s is a struct")
|
fmt.Println("s is a struct")
|
||||||
|
|||||||
37
structure.go
37
structure.go
@ -80,6 +80,43 @@ func Values(s interface{}) []interface{} {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsZero returns true if all fields in a struct is a zero value (not
|
||||||
|
// initialized) A struct tag with the content of "-" ignores the checking of
|
||||||
|
// that particular field. Example:
|
||||||
|
//
|
||||||
|
// // Field is ignored by this package.
|
||||||
|
// Field bool `structure:"-"`
|
||||||
|
//
|
||||||
|
// Note that only exported fields of a struct can be accessed, non exported
|
||||||
|
// fields will be neglected. It panics if s's kind is not struct.
|
||||||
|
func IsZero(s interface{}) bool {
|
||||||
|
v, fields := strctInfo(s)
|
||||||
|
|
||||||
|
for i := range fields {
|
||||||
|
val := v.Field(i)
|
||||||
|
if IsStruct(val.Interface()) {
|
||||||
|
ok := IsZero(val.Interface())
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero value of the given field, such as "" for string, 0 for int
|
||||||
|
zero := reflect.Zero(v.Field(i).Type()).Interface()
|
||||||
|
|
||||||
|
// current value of the given field
|
||||||
|
current := v.Field(i).Interface()
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(current, zero) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// HasZero returns true if a field in a struct is not initialized (zero value).
|
// HasZero returns true if a field in a struct is not initialized (zero value).
|
||||||
// A struct tag with the content of "-" ignores the checking of that particular
|
// A struct tag with the content of "-" ignores the checking of that particular
|
||||||
// field. Example:
|
// field. Example:
|
||||||
|
|||||||
@ -96,6 +96,31 @@ func ExampleFields() {
|
|||||||
// Fields: [Name LastAccessed Number]
|
// Fields: [Name LastAccessed Number]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleIsZero() {
|
||||||
|
type Server struct {
|
||||||
|
Name string
|
||||||
|
ID int32
|
||||||
|
Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing is initalized
|
||||||
|
a := &Server{}
|
||||||
|
isZeroA := IsZero(a)
|
||||||
|
|
||||||
|
// Name and Enabled is initialized, but not ID
|
||||||
|
b := &Server{
|
||||||
|
Name: "Golang",
|
||||||
|
Enabled: true,
|
||||||
|
}
|
||||||
|
isZeroB := IsZero(b)
|
||||||
|
|
||||||
|
fmt.Printf("%#v\n", isZeroA)
|
||||||
|
fmt.Printf("%#v\n", isZeroB)
|
||||||
|
// Output:
|
||||||
|
// true
|
||||||
|
// false
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleHasZero() {
|
func ExampleHasZero() {
|
||||||
// Let's define an Access struct. Note that the "Enabled" field is not
|
// Let's define an Access struct. Note that the "Enabled" field is not
|
||||||
// going to be checked because we added the "structure" tag to the field.
|
// going to be checked because we added the "structure" tag to the field.
|
||||||
|
|||||||
@ -345,6 +345,102 @@ func TestFields_Anonymous(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsZero(t *testing.T) {
|
||||||
|
var T = struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
C bool `structure:"-"`
|
||||||
|
D []string
|
||||||
|
}{}
|
||||||
|
|
||||||
|
ok := IsZero(T)
|
||||||
|
if !ok {
|
||||||
|
t.Error("IsZero should return true because none of the fields are initialized.")
|
||||||
|
}
|
||||||
|
|
||||||
|
var X = struct {
|
||||||
|
A string
|
||||||
|
F *bool
|
||||||
|
}{
|
||||||
|
A: "a-value",
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = IsZero(X)
|
||||||
|
if ok {
|
||||||
|
t.Error("IsZero should return false because A is initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
var Y = struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
}{
|
||||||
|
A: "a-value",
|
||||||
|
B: 123,
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = IsZero(Y)
|
||||||
|
if ok {
|
||||||
|
t.Error("IsZero should return false because A and B is initialized")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsZero_Nested(t *testing.T) {
|
||||||
|
type A struct {
|
||||||
|
Name string
|
||||||
|
D string
|
||||||
|
}
|
||||||
|
a := A{Name: "example"}
|
||||||
|
|
||||||
|
type B struct {
|
||||||
|
A A
|
||||||
|
C int
|
||||||
|
}
|
||||||
|
b := &B{A: a, C: 123}
|
||||||
|
|
||||||
|
ok := IsZero(b)
|
||||||
|
if ok {
|
||||||
|
t.Error("IsZero should return false because A, B and C are initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
aZero := A{}
|
||||||
|
bZero := &B{A: aZero}
|
||||||
|
|
||||||
|
ok = IsZero(bZero)
|
||||||
|
if !ok {
|
||||||
|
t.Error("IsZero should return true because neither A nor B is initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsZero_Anonymous(t *testing.T) {
|
||||||
|
type A struct {
|
||||||
|
Name string
|
||||||
|
D string
|
||||||
|
}
|
||||||
|
a := A{Name: "example"}
|
||||||
|
|
||||||
|
type B struct {
|
||||||
|
A
|
||||||
|
C int
|
||||||
|
}
|
||||||
|
b := &B{C: 123}
|
||||||
|
b.A = a
|
||||||
|
|
||||||
|
ok := IsZero(b)
|
||||||
|
if ok {
|
||||||
|
t.Error("IsZero should return false because A, B and C are initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
aZero := A{}
|
||||||
|
bZero := &B{}
|
||||||
|
bZero.A = aZero
|
||||||
|
|
||||||
|
ok = IsZero(bZero)
|
||||||
|
if !ok {
|
||||||
|
t.Error("IsZero should return true because neither A nor B is initialized")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestHasZero(t *testing.T) {
|
func TestHasZero(t *testing.T) {
|
||||||
var T = struct {
|
var T = struct {
|
||||||
A string
|
A string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user