func encodePacketValue(buf []byte, v reflect.Value) (int, error) { n := 0 switch v.Kind() { default: return n, ErrUnhandledFieldType case reflect.Struct: for i := 0; i < v.NumField(); i++ { field := v.Field(i) n2, err := encodePacketValue(buf[n:], field) n += n2 if err != nil { return n, err } } case reflect.Bool: if v.Bool() { buf[n] = 1 } else { buf[n] = 0 } n += 1 case reflect.Int32: binary.BigEndian.PutUint32(buf[n:n+4], uint32(v.Int())) n += 4 case reflect.Int64: binary.BigEndian.PutUint64(buf[n:n+8], uint64(v.Int())) n += 8 case reflect.String: str := v.String() binary.BigEndian.PutUint32(buf[n:n+4], uint32(len(str))) copy(buf[n+4:n+4+len(str)], []byte(str)) n += 4 + len(str) case reflect.Slice: switch v.Type().Elem().Kind() { default: count := v.Len() startN := n n += 4 for i := 0; i < count; i++ { n2, err := encodePacketValue(buf[n:], v.Index(i)) n += n2 if err != nil { return n, err } } binary.BigEndian.PutUint32(buf[startN:startN+4], uint32(count)) case reflect.Uint8: if v.IsNil() { binary.BigEndian.PutUint32(buf[n:n+4], uint32(0xffffffff)) n += 4 } else { bytes := v.Bytes() binary.BigEndian.PutUint32(buf[n:n+4], uint32(len(bytes))) copy(buf[n+4:n+4+len(bytes)], bytes) n += 4 + len(bytes) } } } return n, nil }
func getSqlFieldsFromJson(updateData map[string]interface{}, v reflect.Value, sqlData map[string]interface{}) error { for i := 0; i < v.NumField(); i++ { if v.Type().Field(i).Type.Kind() == reflect.Struct { subUpdateData := updateData if tag := v.Type().Field(i).Tag.Get("json"); tag != "" { maybeSubUpdateData := updateData[tag] if yesSubUpdateData, ok := maybeSubUpdateData.(map[string]interface{}); ok { subUpdateData = yesSubUpdateData } } getSqlFieldsFromJson(subUpdateData, v.Field(i), sqlData) continue } fieldName := v.Type().Field(i).Name columnName := sqlCase(fieldName) if tag := v.Type().Field(i).Tag.Get("sql"); tag != "" { columnName = tag } jsonName := fieldName if tag := v.Type().Field(i).Tag.Get("json"); tag != "" { jsonName = tag } if val, ok := updateData[jsonName]; ok { sqlData[columnName] = val } } return nil }
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: if v.Type() == reflect.TypeOf(t) { if v.Interface().(time.Time).IsZero() { return true } return false } 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() }
// isZero reports whether the value is the zero of its type. func isZero(val reflect.Value) bool { switch val.Kind() { case reflect.Array: for i := 0; i < val.Len(); i++ { if !isZero(val.Index(i)) { return false } } return true case reflect.Map, reflect.Slice, reflect.String: return val.Len() == 0 case reflect.Bool: return !val.Bool() case reflect.Complex64, reflect.Complex128: return val.Complex() == 0 case reflect.Chan, reflect.Func, reflect.Ptr: return val.IsNil() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return val.Int() == 0 case reflect.Float32, reflect.Float64: return val.Float() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return val.Uint() == 0 case reflect.Struct: for i := 0; i < val.NumField(); i++ { if !isZero(val.Field(i)) { return false } } return true } panic("unknown type in isZero " + val.Type().String()) }
func mergeStruct(out, in reflect.Value) { sprop := GetProperties(in.Type()) for i := 0; i < in.NumField(); i++ { f := in.Type().Field(i) if strings.HasPrefix(f.Name, "XXX_") { continue } mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i]) } if emIn, ok := in.Addr().Interface().(extensionsMap); ok { emOut := out.Addr().Interface().(extensionsMap) mergeExtension(emOut.ExtensionMap(), emIn.ExtensionMap()) } else if emIn, ok := in.Addr().Interface().(extensionsBytes); ok { emOut := out.Addr().Interface().(extensionsBytes) bIn := emIn.GetExtensions() bOut := emOut.GetExtensions() *bOut = append(*bOut, *bIn...) } uf := in.FieldByName("XXX_unrecognized") if !uf.IsValid() { return } uin := uf.Bytes() if len(uin) > 0 { out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...)) } }
func getTemplateFields(keys []string, s reflect.Value) []TemplateField { var fields []TemplateField typeOfSpec := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) t := typeOfSpec.Field(i) if f.CanSet() { fieldName := typeOfSpec.Field(i).Name if f.Kind() == reflect.Struct { keys = append(keys, fieldName) fields = append(fields, getTemplateFields(keys, f)...) continue } fields = append(fields, TemplateField{ Name: fieldName, Value: f.Interface(), String: fmt.Sprintf("%#v", f.Interface()), Type: t.Type, Tags: getTags(t.Tag), }) } } return fields }
func marshal(buf []byte, prefix string, rv reflect.Value, inArray, arrayTable bool) ([]byte, error) { rt := rv.Type() for i := 0; i < rv.NumField(); i++ { ft := rt.Field(i) if !ast.IsExported(ft.Name) { continue } colName, rest := extractTag(rt.Field(i).Tag.Get(fieldTagName)) if colName == tagSkip { continue } if colName == "" { colName = stringutil.ToSnakeCase(ft.Name) } fv := rv.Field(i) switch rest { case tagOmitempty: if fv.Interface() == reflect.Zero(ft.Type).Interface() { continue } } var err error if buf, err = encodeValue(buf, prefix, colName, fv, inArray, arrayTable); err != nil { return nil, err } } return buf, nil }
// mapColumns creates a list of field addresses and column maps, to // make looking up the column for a field address easier. Note that // it doesn't do any special handling for overridden fields, because // passing the address of a field that has been overridden is // difficult to do accidentally. func (plan *QueryPlan) mapColumns(table *TableMap, value reflect.Value) (err error) { value = value.Elem() valueType := value.Type() if plan.colMap == nil { plan.colMap = make(structColumnMap, 0, value.NumField()) } quotedTableName := table.dbmap.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName) for i := 0; i < value.NumField(); i++ { fieldType := valueType.Field(i) fieldVal := value.Field(i) if fieldType.Anonymous { if fieldVal.Kind() != reflect.Ptr { fieldVal = fieldVal.Addr() } plan.mapColumns(table, fieldVal) } else if fieldType.PkgPath == "" { col := table.ColMap(fieldType.Name) quotedCol := table.dbmap.Dialect.QuoteField(col.ColumnName) fieldMap := fieldColumnMap{ addr: fieldVal.Addr().Interface(), column: col, quotedTable: quotedTableName, quotedColumn: quotedCol, } plan.colMap = append(plan.colMap, fieldMap) } } return }
func writeStruct(w io.Writer, val reflect.Value) (err error) { _, err = fmt.Fprint(w, "d") if err != nil { return } typ := val.Type() numFields := val.NumField() svList := make(stringValueArray, numFields) for i := 0; i < numFields; i++ { field := typ.Field(i) bencodeKey(field, &svList[i]) // The tag `bencode:"-"` should mean that this field must be ignored // See https://golang.org/pkg/encoding/json/#Marshal or https://golang.org/pkg/encoding/xml/#Marshal // We set a zero value so that it is ignored by the writeSVList() function if svList[i].key == "-" { svList[i].value = reflect.Value{} } else { svList[i].value = val.Field(i) } } err = writeSVList(w, svList) if err != nil { return } _, err = fmt.Fprint(w, "e") if err != nil { return } return }
func azureStateRefreshFunc(resourceURI string, client *ArmClient, command riviera.APICall) resource.StateRefreshFunc { return func() (interface{}, string, error) { req := client.rivieraClient.NewRequestForURI(resourceURI) req.Command = command res, err := req.Execute() if err != nil { return nil, "", fmt.Errorf("Error executing %T command in azureStateRefreshFunc", req.Command) } var value reflect.Value if reflect.ValueOf(res.Parsed).Kind() == reflect.Ptr { value = reflect.ValueOf(res.Parsed).Elem() } else { value = reflect.ValueOf(res.Parsed) } for i := 0; i < value.NumField(); i++ { // iterates through every struct type field tag := value.Type().Field(i).Tag // returns the tag string tagValue := tag.Get("mapstructure") if tagValue == "provisioningState" { return res.Parsed, value.Field(i).Elem().String(), nil } } panic(fmt.Errorf("azureStateRefreshFunc called on structure %T with no mapstructure:provisioningState tag. This is a bug", res.Parsed)) } }
func approxDataSize(rv reflect.Value) (sum int) { switch rk := rv.Kind(); rk { case reflect.Invalid: case reflect.Ptr, reflect.Interface: sum += int(rv.Type().Size()) sum += approxDataSize(rv.Elem()) case reflect.Slice: sum += int(rv.Type().Size()) for j := 0; j < rv.Len(); j++ { sum += approxDataSize(rv.Index(j)) } case reflect.String: sum += int(rv.Type().Size()) sum += rv.Len() case reflect.Map: sum += int(rv.Type().Size()) for _, mk := range rv.MapKeys() { sum += approxDataSize(mk) sum += approxDataSize(rv.MapIndex(mk)) } case reflect.Struct: //struct size already includes the full data size. //sum += int(rv.Type().Size()) for j := 0; j < rv.NumField(); j++ { sum += approxDataSize(rv.Field(j)) } default: //pure value types sum += int(rv.Type().Size()) } return }
func readStruct(value reflect.Value, parentName string, optional bool) (err error) { for i := 0; i < value.NumField(); i++ { field := value.Field(i) name := value.Type().Field(i).Name tag := parseTag(value.Type().Field(i).Tag.Get("envconfig")) var combinedName string if tag.customName != "" { combinedName = tag.customName } else { combinedName = combineName(parentName, name) } doRead: switch field.Kind() { case reflect.Ptr: // it's a pointer, create a new value and restart the switch field.Set(reflect.New(field.Type().Elem())) field = field.Elem() goto doRead case reflect.Struct: err = readStruct(field, combinedName, optional || tag.optional) default: err = setField(field, combinedName, tag.customName != "", optional || tag.optional) } if err != nil { return err } } return }
func Whitelist(from interface{}, fields []string) map[string]interface{} { out := make(map[string]interface{}) var v reflect.Value var t reflect.Type v = reflect.ValueOf(from) t = reflect.TypeOf(from) if reflect.Ptr == t.Kind() { v = v.Elem() t = t.Elem() } for i := 0; i < v.NumField(); i++ { valueOfField := v.Field(i) typeOfField := t.Field(i) val := valueOfField.Interface() name := strings.Split(typeOfField.Tag.Get("json"), ",")[0] if len(fields) > 0 && fields[0] != "" { if slice.StringInSlice(name, fields) { out[name] = val } } else { out[name] = val } } return out }
// isSameUnknownStruct returns true if the two struct values are the same length // and have the same contents as defined by IsSame. This function explicitly // ignores the declared type of the struct. func isSameStruct(x, y reflect.Value) bool { sx, okx := x.Interface().(StringConvertable) sy, oky := x.Interface().(StringConvertable) if okx && oky { //log.Println("Stringable", x, y) return sx.String() == sy.String() } numFields := x.NumField() if numFields != y.NumField() { return false } typeX := x.Type() for i := 0; i < numFields; i++ { path := []int{i} vx := x.FieldByIndex(path) vy := y.FieldByName(typeX.Field(i).Name) if vx.CanInterface() && vy.CanInterface() { if !IsSame(vx.Interface(), vy.Interface()) { return false } } } return true }
func (e *Encoder) encodeStruct(rv reflect.Value, name string, inlist bool) error { err := e.emit(tagCompound, name, inlist) if err != nil { return err } rt := rv.Type() for i := 0; i < rv.NumField(); i++ { fv := rv.Field(i) ft := rt.Field(i) if hasField(ft.Tag.Get("nbt"), "omitempty") && isEmpty(fv) { continue } fname := tagField(ft.Tag.Get("nbt"), 0) if len(fname) == 0 { fname = ft.Name } // Special-case time.Time if e.isTime(ft.Type) { t := fv.Interface().(time.Time).Unix() fv = reflect.ValueOf(t) } err = e.encode(fv, fname, false) if err != nil { return err } } return e.writeU8(uint8(tagEnd)) }
func (c *Config) applyEnvOverridesToStruct(prefix string, s reflect.Value) error { typeOfSpec := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) // Get the toml tag to determine what env var name to use configName := typeOfSpec.Field(i).Tag.Get("toml") // Replace hyphens with underscores to avoid issues with shells configName = strings.Replace(configName, "-", "_", -1) fieldName := typeOfSpec.Field(i).Name // Skip any fields that we cannot set if f.CanSet() || f.Kind() == reflect.Slice { // Use the upper-case prefix and toml name for the env var key := strings.ToUpper(configName) if prefix != "" { key = strings.ToUpper(fmt.Sprintf("%s_%s", prefix, configName)) } // If the type is s slice, apply to each using the index as a suffix // e.g. GRAPHITE_0 if f.Kind() == reflect.Slice || f.Kind() == reflect.Array { for i := 0; i < f.Len(); i++ { if err := c.applyEnvOverrides(fmt.Sprintf("%s_%d", key, i), fieldName, f.Index(i)); err != nil { return err } } } else if err := c.applyEnvOverrides(key, fieldName, f); err != nil { return err } } } return nil }
func (c *Client) setStruct(directory string, value *reflect.Value) (err error) { tv := value.Type() for i := 0; i < value.NumField(); i++ { if tagv := tv.Field(i).Tag.Get(c.tag); tagv != "" { field := value.Field(i) if field.Kind() == reflect.Struct { if err := c.setStruct(path.Join(directory, tagv), &field); err != nil { return err } } else { key := path.Join(directory, tagv) response, err := c.client.Get(key, false, false) if err != nil { return err } value := response.Node.Value switch field.Kind() { case reflect.String: field.SetString(value) case reflect.Int64: i, _ := strconv.Atoi(value) field.SetInt(int64(i)) case reflect.Int: i, _ := strconv.Atoi(value) field.SetInt(int64(i)) } } } } return nil }
func isZero(v reflect.Value) bool { switch v.Kind() { case reflect.String: return len(v.String()) == 0 case reflect.Ptr, reflect.Interface: return v.IsNil() case reflect.Slice: return v.Len() == 0 case reflect.Map: return v.Len() == 0 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.Bool: return !v.Bool() case reflect.Struct: vt := v.Type() if vt == typeTime { return v.Interface().(time.Time).IsZero() } for i := 0; i < v.NumField(); i++ { if vt.Field(i).PkgPath != "" && !vt.Field(i).Anonymous { continue // Private field } if !isZero(v.Field(i)) { return false } } return true } return false }
func (state *marshalState) marshalStruct(v reflect.Value) error { state.writeString("<< ") t := v.Type() n := v.NumField() for i := 0; i < n; i++ { f := t.Field(i) if f.PkgPath != "" { continue } tag, omitEmpty := f.Name, false if tv := f.Tag.Get("pdf"); tv != "" { if tv == "-" { continue } name, options := parseTag(tv) if name != "" { tag = name } omitEmpty = options.Contains("omitempty") } fieldValue := v.Field(i) if omitEmpty && isEmptyValue(fieldValue) { continue } state.marshalKeyValue(name(tag), fieldValue) } state.writeString(">>") return nil }
// Generic struct printer. // Doesn't care about the string tag "domain-name", // but does look for an "ipv4" tag on uint32 variables // and the "ipv6" tag on array variables, // printing them as IP addresses. func printStructValue(val reflect.Value) string { s := "{" for i := 0; i < val.NumField(); i++ { if i > 0 { s += ", " } f := val.Type().Field(i) if !f.Anonymous { s += f.Name + "=" } fval := val.Field(i) if fv := fval; fv.Kind() == reflect.Struct { s += printStructValue(fv) } else if fv := fval; (fv.Kind() == reflect.Uint || fv.Kind() == reflect.Uint8 || fv.Kind() == reflect.Uint16 || fv.Kind() == reflect.Uint32 || fv.Kind() == reflect.Uint64 || fv.Kind() == reflect.Uintptr) && f.Tag == "ipv4" { i := fv.Uint() s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String() } else if fv := fval; fv.Kind() == reflect.Array && f.Tag == "ipv6" { i := fv.Interface().([]byte) s += IP(i).String() } else { s += fmt.Sprint(fval.Interface()) } } s += "}" return s }
// visit calls the visitor function for each string it finds, and will descend // recursively into structures and slices. If any visitor returns an error then // the search will stop and that error will be returned. func visit(path string, v reflect.Value, t reflect.Type, fn visitor) error { switch v.Kind() { case reflect.String: return fn(path, v) case reflect.Struct: for i := 0; i < v.NumField(); i++ { vf := v.Field(i) tf := t.Field(i) newPath := fmt.Sprintf("%s.%s", path, tf.Name) if err := visit(newPath, vf, tf.Type, fn); err != nil { return err } } case reflect.Slice: for i := 0; i < v.Len(); i++ { vi := v.Index(i) ti := vi.Type() newPath := fmt.Sprintf("%s[%d]", path, i) if err := visit(newPath, vi, ti, fn); err != nil { return err } } } return nil }
func isZero(v reflect.Value) bool { switch v.Kind() { case reflect.Func, reflect.Map, reflect.Slice: return v.IsNil() case reflect.Struct: // Special case to get zero values by method. switch obj := v.Interface().(type) { case time.Time: return obj.IsZero() } // Check public fields for zero values. z := true for i := 0; i < v.NumField(); i++ { if v.Type().Field(i).PkgPath != "" { continue // Skip private fields. } z = z && isZero(v.Field(i)) } return z } // Compare other types directly: z := reflect.Zero(v.Type()) return v.Interface() == z.Interface() }
func convertStruct(in interface{}, val reflect.Value) *ConfigError { dict, ok := in.(map[string]interface{}) if !ok || len(dict) != val.NumField() { return &ConfigError{ErrInvalidType, ""} } for k, from := range dict { to := val.FieldByName(strings.ToTitle(k[:1]) + k[1:]) if !to.IsValid() { return &ConfigError{ErrInvalidType, ""} } convertor := convertFuncs.get(to) if convertor == nil { return &ConfigError{ErrInvalidType, ""} } if err := convertor(from, to); err != nil { if len(err.Field) > 0 { err.Field = fmt.Sprintf("%s.%s", k, err.Field) } else { err.Field = k } return err } } return nil }
func size(v reflect.Value) int { v = reflect.Indirect(v) switch v.Kind() { case reflect.String: return v.Len() + 1 case reflect.Bool: return 1 case reflect.Uint, reflect.Int: return 8 case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: return int(v.Type().Size()) case reflect.Struct: sum := 0 for i, n := 0, v.NumField(); i < n; i++ { s := size(v.Field(i)) if s < 0 { return -1 } sum += s } if sum == 0 { return -1 } return sum } return -1 }
func display(name string, v reflect.Value) { switch v.Kind() { //uint case reflect.Invalid: fmt.Printf("%s = invalid\n", name) case reflect.Slice, reflect.Array: for i := 0; i < v.Len(); i++ { display(fmt.Sprintf("%s[%d]", name, i), v.Index(i)) } case reflect.Struct: for i := 0; i < v.NumField(); i++ { fieldPath := fmt.Sprintf("%s.%s", name, v.Type().Field(i).Name) display(fieldPath, v.Field(i)) } case reflect.Map: for _, key := range v.MapKeys() { display(fmt.Sprintf("%s[%s]", name, formatAtom(key)), v.MapIndex(key)) } case reflect.Ptr: if v.IsNil() { fmt.Printf("%s = nil\n", name) } else { display(fmt.Sprintf("(*%s)", name), v.Elem()) } case reflect.Interface: if v.IsNil() { fmt.Printf("%s = nil\n", name) } else { fmt.Printf("%s.type = %s\n", name, v.Elem().Type()) display(name+".value", v.Elem()) } default: // basic types, channels, funcs fmt.Printf("%s = %s\n", name, formatAtom(v)) } }
func ToJson(_struct interface{}) (map[string]interface{}, error) { var ( v reflect.Value t reflect.Type ) result := make(map[string]interface{}) if reflect.TypeOf(_struct).Kind() == reflect.Ptr { v = reflect.ValueOf(_struct).Elem() t = reflect.TypeOf(_struct).Elem() } else { v = reflect.ValueOf(_struct) t = reflect.TypeOf(_struct) } if t.Kind() != reflect.Struct { panic(errors.New("excepted a pointer of struct or a struct")) } for i := 0; i < v.NumField(); i++ { //fieldName := strings.ToLower(t.Field(i).Name) fieldName := t.Field(i).Name result[fieldName] = v.Field(i).Interface() } val, _ := json.MarshalIndent(result, "", "\t") fmt.Printf("%v\n", (string)(val)) return result, nil }
func (e *Encoder) encode(v reflect.Value, dst map[string][]string) error { var opts string var value string t := v.Type() for i := 0; i < v.NumField(); i++ { tag := t.Field(i).Tag.Get(e.TagID) name := tag if idx := strings.Index(tag, ","); idx != -1 { name = tag[:idx] opts = tag[idx+1:] } if name == "-" { continue } encFunc, recurse := encoder(v.Field(i).Type()) if recurse { e.encode(v.Field(i), dst) continue } value = encFunc(v.Field(i)) if value == "" && strings.Contains(opts, "omitempty") { continue } dst[name] = []string{value} } return nil }
func (c *EC2Client) loadStruct(v url.Values, value reflect.Value, prefix string) error { if !value.IsValid() { return nil } t := value.Type() for i := 0; i < value.NumField(); i++ { value := value.Field(i) name := t.Field(i).Tag.Get("ec2") if name == "" { name = t.Field(i).Name } if prefix != "" { name = prefix + "." + name } switch casted := value.Interface().(type) { case StringValue: if casted != nil { v.Set(name, *casted) } case BooleanValue: if casted != nil { v.Set(name, strconv.FormatBool(*casted)) } case LongValue: if casted != nil { v.Set(name, strconv.FormatInt(*casted, 10)) } case IntegerValue: if casted != nil { v.Set(name, strconv.Itoa(*casted)) } case DoubleValue: if casted != nil { v.Set(name, strconv.FormatFloat(*casted, 'f', -1, 64)) } case FloatValue: if casted != nil { v.Set(name, strconv.FormatFloat(float64(*casted), 'f', -1, 32)) } case []string: if len(casted) != 0 { for i, val := range casted { v.Set(fmt.Sprintf("%s.%d", name, i+1), val) } } case time.Time: if !casted.IsZero() { const ISO8601UTC = "2006-01-02T15:04:05Z" v.Set(name, casted.UTC().Format(ISO8601UTC)) } default: if err := c.loadValues(v, value.Interface(), name); err != nil { return err } } } return nil }
func isZero(v reflect.Value) bool { switch v.Kind() { case reflect.String: return len(v.String()) == 0 case reflect.Interface, reflect.Ptr: return v.IsNil() case reflect.Slice: return v.Len() == 0 case reflect.Map: return v.Len() == 0 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Bool: return !v.Bool() case reflect.Struct: vt := v.Type() for i := v.NumField() - 1; i >= 0; i-- { if vt.Field(i).PkgPath != "" { continue // Private field } if !isZero(v.Field(i)) { return false } } return true } return false }
func quietOutput(prefix string, v reflect.Value) { // For pointers and interfaces, just grab the underlying value and try again if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { quietOutput(prefix, v.Elem()) return } switch v.Kind() { case reflect.Struct: for f := 0; f < v.NumField(); f++ { name := v.Type().Field(f).Name quietOutput(prefix+name+" ", v.Field(f)) } case reflect.Array: fallthrough case reflect.Slice: for i := 0; i < v.Len(); i++ { quietOutput(prefix, v.Index(i)) } case reflect.Map: for _, k := range v.MapKeys() { if name, ok := k.Interface().(string); ok { quietOutput(prefix+name+" ", v.MapIndex(k)) } else { quietOutput(prefix+"UnknownField", v.MapIndex(k)) } } default: if v.CanInterface() { fmt.Printf("%s%v\n", prefix, v.Interface()) } else { fmt.Printf("%s <Invalid>", prefix) } } }