structure: Add Has() method, fix IsZero()
This commit is contained in:
parent
e68f708c4c
commit
31b952e111
@ -45,8 +45,12 @@ f := structure.Fields(s)
|
||||
// => "Server"
|
||||
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.
|
||||
if structure.IsZero(s) {
|
||||
if !structure.IsZero(s) {
|
||||
fmt.Println("s is initialized")
|
||||
}
|
||||
|
||||
|
||||
32
structure.go
32
structure.go
@ -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
|
||||
// particular field. Example:
|
||||
//
|
||||
@ -96,8 +96,8 @@ func IsZero(s interface{}) bool {
|
||||
val := v.Field(i)
|
||||
if IsStruct(val.Interface()) {
|
||||
ok := IsZero(val.Interface())
|
||||
if !ok {
|
||||
return false
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
|
||||
continue
|
||||
@ -110,11 +110,11 @@ func IsZero(s interface{}) bool {
|
||||
current := v.Field(i).Interface()
|
||||
|
||||
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 "-"
|
||||
@ -172,6 +172,28 @@ func Name(s interface{}) string {
|
||||
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
|
||||
// given s struct. This is a convenient helper method to avoid duplicate code
|
||||
// in some of the functions.
|
||||
|
||||
@ -110,7 +110,7 @@ func ExampleIsZero() {
|
||||
a := &Access{
|
||||
LastAccessed: time.Now(),
|
||||
}
|
||||
validA := IsZero(a)
|
||||
isZeroA := IsZero(a)
|
||||
|
||||
// Name and Number is initialized.
|
||||
b := &Access{
|
||||
@ -118,11 +118,31 @@ func ExampleIsZero() {
|
||||
LastAccessed: time.Now(),
|
||||
Number: 12345,
|
||||
}
|
||||
validB := IsZero(b)
|
||||
isZeroB := IsZero(b)
|
||||
|
||||
fmt.Printf("%#v\n", validA)
|
||||
fmt.Printf("%#v\n", validB)
|
||||
fmt.Printf("%#v\n", isZeroA)
|
||||
fmt.Printf("%#v\n", isZeroB)
|
||||
// Output:
|
||||
// false
|
||||
// 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
|
||||
}
|
||||
|
||||
@ -357,8 +357,8 @@ func TestIsZero(t *testing.T) {
|
||||
}
|
||||
|
||||
ok := IsZero(T)
|
||||
if ok {
|
||||
t.Error("IsZero should return false because D is not initialized")
|
||||
if !ok {
|
||||
t.Error("IsZero should return true because A and B are initialized.")
|
||||
}
|
||||
|
||||
var X = struct {
|
||||
@ -369,8 +369,21 @@ func TestIsZero(t *testing.T) {
|
||||
}
|
||||
|
||||
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 {
|
||||
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}
|
||||
|
||||
ok := IsZero(b)
|
||||
if ok {
|
||||
t.Error("IsZero should return false because D is not initialized")
|
||||
if !ok {
|
||||
t.Error("IsZero should return true because D is not initialized")
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,11 +421,38 @@ func TestIsZero_Anonymous(t *testing.T) {
|
||||
b.A = a
|
||||
|
||||
ok := IsZero(b)
|
||||
if ok {
|
||||
if !ok {
|
||||
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) {
|
||||
type Foo struct {
|
||||
A string
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user