structure: Add Has() method, fix IsZero()

This commit is contained in:
Fatih Arslan 2014-07-30 22:01:18 +03:00
parent e68f708c4c
commit 31b952e111
4 changed files with 103 additions and 17 deletions

View File

@ -45,8 +45,12 @@ f := structure.Fields(s)
// => "Server" // => "Server"
n := structure.Name(s) n := structure.Name(s)
// Check if field name exists
// => true
n := structure.Has(s, "Enabled")
// Check if the fields of a struct is initialized or not. // Check if the fields of a struct is initialized or not.
if structure.IsZero(s) { if !structure.IsZero(s) {
fmt.Println("s is initialized") fmt.Println("s is initialized")
} }

View File

@ -80,7 +80,7 @@ func Values(s interface{}) []interface{} {
} }
// IsZero returns true if all fields in a struct are initialized (non zero // IsZero returns true if any field in a struct is not initialized (zero
// value). A struct tag with the content of "-" ignores the checking of that // value). A struct tag with the content of "-" ignores the checking of that
// particular field. Example: // particular field. Example:
// //
@ -96,8 +96,8 @@ func IsZero(s interface{}) bool {
val := v.Field(i) val := v.Field(i)
if IsStruct(val.Interface()) { if IsStruct(val.Interface()) {
ok := IsZero(val.Interface()) ok := IsZero(val.Interface())
if !ok { if ok {
return false return true
} }
continue continue
@ -110,11 +110,11 @@ func IsZero(s interface{}) bool {
current := v.Field(i).Interface() current := v.Field(i).Interface()
if reflect.DeepEqual(current, zero) { if reflect.DeepEqual(current, zero) {
return false return true
} }
} }
return true return false
} }
// Fields returns a slice of field names. A struct tag with the content of "-" // Fields returns a slice of field names. A struct tag with the content of "-"
@ -172,6 +172,28 @@ func Name(s interface{}) string {
return t.Name() return t.Name()
} }
// Has returns true if the given field name exists for the struct s. It panic's
// if s's kind is not struct.
func Has(s interface{}, fieldName string) bool {
v, fields := strctInfo(s)
for i, field := range fields {
val := v.Field(i)
if IsStruct(val.Interface()) {
if ok := Has(val.Interface(), fieldName); ok {
return true
}
}
if field.Name == fieldName {
return true
}
}
return false
}
// strctInfo returns the struct value and the exported struct fields for a // strctInfo returns the struct value and the exported struct fields for a
// given s struct. This is a convenient helper method to avoid duplicate code // given s struct. This is a convenient helper method to avoid duplicate code
// in some of the functions. // in some of the functions.

View File

@ -110,7 +110,7 @@ func ExampleIsZero() {
a := &Access{ a := &Access{
LastAccessed: time.Now(), LastAccessed: time.Now(),
} }
validA := IsZero(a) isZeroA := IsZero(a)
// Name and Number is initialized. // Name and Number is initialized.
b := &Access{ b := &Access{
@ -118,11 +118,31 @@ func ExampleIsZero() {
LastAccessed: time.Now(), LastAccessed: time.Now(),
Number: 12345, Number: 12345,
} }
validB := IsZero(b) isZeroB := IsZero(b)
fmt.Printf("%#v\n", validA) fmt.Printf("%#v\n", isZeroA)
fmt.Printf("%#v\n", validB) fmt.Printf("%#v\n", isZeroB)
// Output: // Output:
// false
// true // true
// false
}
func ExampleHas() {
type Access struct {
Name string
LastAccessed time.Time
Number int
}
s := &Access{
Name: "Fatih",
LastAccessed: time.Now(),
Number: 1234567,
}
found := Has(s, "LastAccessed")
fmt.Printf("Has: %+v\n", found)
// Output:
// Has: true
} }

View File

@ -357,8 +357,8 @@ func TestIsZero(t *testing.T) {
} }
ok := IsZero(T) ok := IsZero(T)
if ok { if !ok {
t.Error("IsZero should return false because D is not initialized") t.Error("IsZero should return true because A and B are initialized.")
} }
var X = struct { var X = struct {
@ -369,8 +369,21 @@ func TestIsZero(t *testing.T) {
} }
ok = IsZero(X) ok = IsZero(X)
if !ok {
t.Error("IsZero should return true because A is initialized")
}
var Y = struct {
A string
B int
}{
A: "a-value",
B: 123,
}
ok = IsZero(Y)
if ok { if ok {
t.Error("IsZero should return false because F is not initialized") t.Error("IsZero should return false because A and B is initialized")
} }
} }
@ -388,8 +401,8 @@ func TestIsZero_Nested(t *testing.T) {
b := &B{A: a, C: 123} b := &B{A: a, C: 123}
ok := IsZero(b) ok := IsZero(b)
if ok { if !ok {
t.Error("IsZero should return false because D is not initialized") t.Error("IsZero should return true because D is not initialized")
} }
} }
@ -408,11 +421,38 @@ func TestIsZero_Anonymous(t *testing.T) {
b.A = a b.A = a
ok := IsZero(b) ok := IsZero(b)
if ok { if !ok {
t.Error("IsZero should return false because D is not initialized") t.Error("IsZero should return false because D is not initialized")
} }
} }
func TestHas(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
if !Has(b, "Name") {
t.Error("Has should return true for Name, but it's false")
}
if Has(b, "NotAvailable") {
t.Error("Has should return false for NotAvailable, but it's true")
}
if !Has(b, "C") {
t.Error("Has should return true for C, but it's false")
}
}
func TestName(t *testing.T) { func TestName(t *testing.T) {
type Foo struct { type Foo struct {
A string A string