I have a struct containing many fields - I've figured out how to extract the field name, value, and tag information using reflection. What I also want to do is to determine if the value of a field is different from the field's default value.
Currently, I have this (works, but a bit smelly):
...
qsMap := make(map[string]interface{})
var defaultTime time.Time
var defaultString string
...
// get the field name and value
fieldName := s.Type().Field(i).Tag.Get("bson")
fieldValue := valueField.Interface()
// use reflection to determine the TYPE of the field and apply the proper formatting
switch fieldValue.(type) {
case time.Time:
if fieldValue != defaultTime {
qsMap[fieldName] = fieldValue
}
case string:
if fieldValue != defaultString {
qsMap[fieldName] = fieldValue
}
...
}
Seems to me that there should be a way to avoid the type switch in this case - what I'm trying to do is build up a map of field/values that have a value different from their default zero value, something like:
// doesn't work -- i.e., if fieldValue of type string would be compared against "", etc.
if fieldValue != reflect.Zero(reflect.Type(fieldValue)) {
qsMap[fieldName] = fieldValue
}
Is there an elegant way to accomplish this?
Thanks!
If an enum does not define an item with a value of zero, its default value will be zero.
A zero value struct is simply a struct variable where each key's value is set to their respective zero value. This article is part of the Structs in Go series. We can create a zero value struct using the var statement to initialize our struct variable.
The default value for the bool type in the Go programming language is false.
For types that support the equality operation, you can just compare interface{}
variables holding the zero value and field value. Something like this:
v.Interface() == reflect.Zero(v.Type()).Interface()
For functions, maps and slices though, this comparison will fail, so we still need to include some special casing. Further more, while arrays and structs are comparable, the comparison will fail if they contain non-comparable types. So you probably need something like:
func isZero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Func, reflect.Map, reflect.Slice:
return v.IsNil()
case reflect.Array:
z := true
for i := 0; i < v.Len(); i++ {
z = z && isZero(v.Index(i))
}
return z
case reflect.Struct:
z := true
for i := 0; i < v.NumField(); i++ {
z = z && isZero(v.Field(i))
}
return z
}
// Compare other types directly:
z := reflect.Zero(v.Type())
return v.Interface() == z.Interface()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With