structure: add IsValid() function
This commit is contained in:
parent
2d4d14a6c8
commit
c36b654328
51
structure.go
51
structure.go
@ -14,19 +14,18 @@ import (
|
|||||||
func ToMap(s interface{}) map[string]interface{} {
|
func ToMap(s interface{}) map[string]interface{} {
|
||||||
out := make(map[string]interface{})
|
out := make(map[string]interface{})
|
||||||
|
|
||||||
t := reflect.TypeOf(s)
|
|
||||||
v := reflect.ValueOf(s)
|
v := reflect.ValueOf(s)
|
||||||
|
|
||||||
// if pointer get the underlying element≤
|
// if pointer get the underlying element≤
|
||||||
if t.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
t = t.Elem()
|
|
||||||
v = v.Elem()
|
v = v.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Struct {
|
||||||
panic("not struct")
|
panic("not struct")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t := v.Type()
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
field := t.Field(i)
|
field := t.Field(i)
|
||||||
|
|
||||||
@ -74,6 +73,50 @@ func ToSlice(s interface{}) []interface{} {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsValid returns true if all fields in a struct are initialized (non zero
|
||||||
|
// value). A struct tag with the content of `structure:"-"` omits the checking
|
||||||
|
// of field. 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 IsValid(s interface{}) bool {
|
||||||
|
v := reflect.ValueOf(s)
|
||||||
|
|
||||||
|
// if pointer get the underlying element≤
|
||||||
|
if v.Kind() == reflect.Ptr {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.Kind() != reflect.Struct {
|
||||||
|
panic("not struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
t := v.Type()
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
field := t.Field(i)
|
||||||
|
|
||||||
|
// we can't access the value of unexported fields
|
||||||
|
if field.PkgPath != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't check if it's omitted
|
||||||
|
if tag := field.Tag.Get("structure"); tag == "-" {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
// Fields returns a sorted slice of field names. Note that only exported
|
// Fields returns a sorted slice of field names. Note that only exported
|
||||||
// fields of a struct can be accessed, non exported fields will be neglected.
|
// fields of a struct can be accessed, non exported fields will be neglected.
|
||||||
func Fields(s interface{}) []string {
|
func Fields(s interface{}) []string {
|
||||||
|
|||||||
@ -167,3 +167,20 @@ func TestFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsValid(t *testing.T) {
|
||||||
|
var T = struct {
|
||||||
|
A string
|
||||||
|
B int
|
||||||
|
C bool `structure:"-"`
|
||||||
|
D []string
|
||||||
|
}{
|
||||||
|
A: "a-value",
|
||||||
|
B: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
ok := IsValid(T)
|
||||||
|
if ok {
|
||||||
|
t.Error("IsValid should return false because D is not initialized")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user