structure: add IsZero() back that checks all fields

This commit is contained in:
Fatih Arslan 2014-08-05 16:54:01 +03:00
parent 301494b442
commit 241e969210
4 changed files with 164 additions and 1 deletions

View File

@ -51,11 +51,16 @@ n := structure.Name(s)
// => true
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) {
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
if structure.IsStruct(s) {
fmt.Println("s is a struct")

View File

@ -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).
// A struct tag with the content of "-" ignores the checking of that particular
// field. Example:

View File

@ -96,6 +96,31 @@ func ExampleFields() {
// 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() {
// 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.

View File

@ -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) {
var T = struct {
A string