// Pretty-print any random data we get back from the server func genericLogData(name string, v reflect.Value, indent string, skip int) { prefix := "->" + indent if name != "" { prefix = "-> " + indent + name + ":" } // For pointers and interfaces, just grab the underlying value and try again if v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { genericLogData(name, v.Elem(), indent, skip) return } // Only print if skip is 0. Recursive calls should indent or decrement skip, depending on if anything was // printed. var skipped bool if skip == 0 { skipped = false indent = indent + " " } else { skipped = true skip = skip - 1 } switch v.Kind() { case reflect.Struct: if !skipped { Log("%s\n", prefix) } for f := 0; f < v.NumField(); f++ { name := v.Type().Field(f).Name genericLogData(name, v.Field(f), indent, skip) } case reflect.Array: fallthrough case reflect.Slice: if !skipped { Log("%s\n", prefix) } for i := 0; i < v.Len(); i++ { genericLogData("", v.Index(i), indent, skip) } case reflect.Map: if !skipped { Log("%s\n", prefix) } for _, k := range v.MapKeys() { if name, ok := k.Interface().(string); ok { genericLogData(name, v.MapIndex(k), indent, skip) } else { genericLogData("Unknown field", v.MapIndex(k), indent, skip) } } default: if v.CanInterface() { Log("%s %v", prefix, v.Interface()) } else { Log("%s <Invalid>", prefix) } } }
func isValueKind(v *reflect.Value, isEmpty *bool, val *interface{}) bool { switch v.Kind() { case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128: if val != nil && v.CanInterface() { *val = v.Interface() } if isEmpty != nil { *isEmpty = false } return true } return false }
// equal return true when lhsV and rhsV is same value. func equal(lhsV, rhsV reflect.Value) bool { lhsIsNil, rhsIsNil := isNil(lhsV), isNil(rhsV) if lhsIsNil && rhsIsNil { return true } if (!lhsIsNil && rhsIsNil) || (lhsIsNil && !rhsIsNil) { return false } if lhsV.Kind() == reflect.Interface || lhsV.Kind() == reflect.Ptr { lhsV = lhsV.Elem() } if rhsV.Kind() == reflect.Interface || rhsV.Kind() == reflect.Ptr { rhsV = rhsV.Elem() } if !lhsV.IsValid() || !rhsV.IsValid() { return true } if isNum(lhsV) && isNum(rhsV) { if rhsV.Type().ConvertibleTo(lhsV.Type()) { rhsV = rhsV.Convert(lhsV.Type()) } } if lhsV.CanInterface() && rhsV.CanInterface() { return reflect.DeepEqual(lhsV.Interface(), rhsV.Interface()) } return reflect.DeepEqual(lhsV, rhsV) }
// printValue is like printArg but starts with a reflect value, not an interface{} value. func (p *pp) printValue(value reflect.Value, verb rune, depth int) { if !value.IsValid() { switch verb { case 'T', 'v': p.buf.WriteString(nilAngleString) default: p.badVerb(verb) } return } // Special processing considerations. // %T (the value's type) and %p (its address) are special; we always do them first. switch verb { case 'T': p.printArg(value.Type().String(), 's', 0) return case 'p': p.fmtPointer(value, verb) return } // Handle values with special methods. // Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us. p.arg = nil // Make sure it's cleared, for safety. if value.CanInterface() { p.arg = value.Interface() } if p.handleMethods(verb, depth) { return } p.printReflectValue(value, verb, depth) }
func (vk *GenericInvoker) Return(f interface{}, returns []interface{}) ([]interface{}, error) { funcT := reflect.TypeOf(f) // make sure parameter matched if len(returns) != funcT.NumOut() { return nil, fmt.Errorf("Parameter Count mismatch: %v %v", len(returns), funcT.NumOut()) } var ( err error ret reflect.Value ) out := make([]interface{}, funcT.NumOut()) for i := 0; i < funcT.NumOut(); i++ { ret, err = vk.from(returns[i], funcT.Out(i)) if err != nil { return nil, err } if ret.CanInterface() { out[i] = ret.Interface() } else { return nil, fmt.Errorf("Unable to convert to interface{} for %d", i) } } return out, nil }
// thanks James Henstridge // TODO: tweak // TODO: IsZero() interface support func isZero(rv reflect.Value) bool { // use IsZero for supported types if rv.CanInterface() { if zeroer, ok := rv.Interface().(isZeroer); ok { return zeroer.IsZero() } } switch rv.Kind() { case reflect.Func, reflect.Map, reflect.Slice: return rv.IsNil() case reflect.Array: z := true for i := 0; i < rv.Len(); i++ { z = z && isZero(rv.Index(i)) } return z case reflect.Struct: z := true for i := 0; i < rv.NumField(); i++ { z = z && isZero(rv.Field(i)) } return z } // Compare other types directly: z := reflect.Zero(rv.Type()) return rv.Interface() == z.Interface() }
func setFieldDefaults(v reflect.Value, sf reflect.StructField, s reflect.Value) { if v.CanInterface() && reflect.DeepEqual( v.Interface(), reflect.Zero(v.Type()).Interface()) { tag := sf.Tag.Get("ebmldef") if tag != "" { switch v.Kind() { case reflect.Int, reflect.Int64: u, _ := strconv.ParseInt(tag, 10, 0) v.SetInt(int64(u)) case reflect.Uint, reflect.Uint64: u, _ := strconv.ParseUint(tag, 10, 0) v.SetUint(u) case reflect.Float32, reflect.Float64: f, _ := strconv.ParseFloat(tag, 64) v.SetFloat(f) case reflect.String: v.SetString(tag) default: log.Panic("Unsupported default value") } } ltag := sf.Tag.Get("ebmldeflink") if ltag != "" { v.Set(s.FieldByName(ltag)) } } }
// ToCsv takes a struct and returns CSV line with data delimited by delim and // true, false values translated to boolTrue, boolFalse respectively. func ToCsv(v interface{}, delim, boolTrue, boolFalse string) string { var csvLine []string var strValue string var structField reflect.StructField var field reflect.Value t := reflect.ValueOf(v) if t.Kind() == reflect.Ptr { t = t.Elem() } if t.Kind() != reflect.Struct { panic("Expected pointer to a struct") } for i := 0; i < t.NumField(); i++ { structField = t.Type().Field(i) field = t.Field(i) if structField.Anonymous { strValue = ToCsv(field.Interface(), delim, boolTrue, boolFalse) csvLine = append(csvLine, strValue) continue } if !skip(structField.Tag) && field.CanInterface() { strValue = getValue(field, boolTrue, boolFalse) csvLine = append(csvLine, strValue) } } return strings.Join(csvLine, delim) }
// unmarshalAttr unmarshals a single XML attribute into val. func (p *Decoder) unmarshalAttr(val reflect.Value, attr Attr) error { if val.Kind() == reflect.Ptr { if val.IsNil() { val.Set(reflect.New(val.Type().Elem())) } val = val.Elem() } if val.CanInterface() && val.Type().Implements(unmarshalerAttrType) { // This is an unmarshaler with a non-pointer receiver, // so it's likely to be incorrect, but we do what we're told. return val.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr) } if val.CanAddr() { pv := val.Addr() if pv.CanInterface() && pv.Type().Implements(unmarshalerAttrType) { return pv.Interface().(UnmarshalerAttr).UnmarshalXMLAttr(attr) } } // Not an UnmarshalerAttr; try encoding.TextUnmarshaler. if val.CanInterface() && val.Type().Implements(textUnmarshalerType) { // This is an unmarshaler with a non-pointer receiver, // so it's likely to be incorrect, but we do what we're told. return val.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value)) } if val.CanAddr() { pv := val.Addr() if pv.CanInterface() && pv.Type().Implements(textUnmarshalerType) { return pv.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(attr.Value)) } } return copyValue(val, []byte(attr.Value)) }
// bypassCanInterface returns a version of v that // bypasses the CanInterface check. func bypassCanInterface(v reflect.Value) reflect.Value { if !v.IsValid() || v.CanInterface() { return v } *flagField(&v) &^= flagRO return v }
func isZeroVal(val reflect.Value) bool { if !val.CanInterface() { return false } z := reflect.Zero(val.Type()).Interface() return reflect.DeepEqual(val.Interface(), z) }
// IsZero returns true when the value is a zero for the type func isZero(data reflect.Value) bool { if !data.CanInterface() { return true } tpe := data.Type() return reflect.DeepEqual(data.Interface(), reflect.Zero(tpe).Interface()) }
// printValue is like printArg but starts with a reflect value, not an interface{} value. func (p *pp) printValue(value reflect.Value, verb rune, plus, goSyntax bool, depth int) (wasString bool) { if !value.IsValid() { if verb == 'T' || verb == 'v' { p.buf.Write(nilAngleBytes) } else { p.badVerb(verb) } return false } // Special processing considerations. // %T (the value's type) and %p (its address) are special; we always do them first. switch verb { case 'T': p.printArg(value.Type().String(), 's', false, false, 0) return false case 'p': p.fmtPointer(value, verb, goSyntax) return false } // Handle values with special methods. // Call always, even when arg == nil, because handleMethods clears p.fmt.plus for us. p.arg = nil // Make sure it's cleared, for safety. if value.CanInterface() { p.arg = value.Interface() } if isString, handled := p.handleMethods(verb, plus, goSyntax, depth); handled { return isString } return p.printReflectValue(value, verb, plus, goSyntax, depth) }
func printValue(v reflect.Value, space int) { if !v.CanInterface() { fmt.Print(v) } else { printVar(v.Interface(), space) } }
func formatValue(value reflect.Value, indentation uint) string { if indentation > MaxDepth { return "..." } if isNilValue(value) { return "nil" } if UseStringerRepresentation { if value.CanInterface() { obj := value.Interface() switch x := obj.(type) { case fmt.GoStringer: return x.GoString() case fmt.Stringer: return x.String() } } } switch value.Kind() { case reflect.Bool: return fmt.Sprintf("%v", value.Bool()) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return fmt.Sprintf("%v", value.Int()) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return fmt.Sprintf("%v", value.Uint()) case reflect.Uintptr: return fmt.Sprintf("0x%x", value.Uint()) case reflect.Float32, reflect.Float64: return fmt.Sprintf("%v", value.Float()) case reflect.Complex64, reflect.Complex128: return fmt.Sprintf("%v", value.Complex()) case reflect.Chan: return fmt.Sprintf("0x%x", value.Pointer()) case reflect.Func: return fmt.Sprintf("0x%x", value.Pointer()) case reflect.Ptr: return formatValue(value.Elem(), indentation) case reflect.Slice: return formatSlice(value, indentation) case reflect.String: return formatString(value.String(), indentation) case reflect.Array: return formatSlice(value, indentation) case reflect.Map: return formatMap(value, indentation) case reflect.Struct: return formatStruct(value, indentation) case reflect.Interface: return formatValue(value.Elem(), indentation) default: if value.CanInterface() { return fmt.Sprintf("%#v", value.Interface()) } else { return fmt.Sprintf("%#v", value) } } }
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) } } }
// layerString outputs, recursively, a layer in a "smart" way. See docs for // LayerString for more details. // // Params: // i - value to write out // anonymous: if we're currently recursing an anonymous member of a struct // writeSpace: if we've already written a value in a struct, and need to // write a space before writing more. This happens when we write various // anonymous values, and need to keep writing more. func layerString(v reflect.Value, anonymous bool, writeSpace bool) string { // Let String() functions take precedence. if v.CanInterface() { if s, ok := v.Interface().(fmt.Stringer); ok { return s.String() } } // Reflect, and spit out all the exported fields as key=value. switch v.Type().Kind() { case reflect.Interface, reflect.Ptr: if v.IsNil() { return "nil" } r := v.Elem() return layerString(r, anonymous, writeSpace) case reflect.Struct: var b bytes.Buffer typ := v.Type() if !anonymous { b.WriteByte('{') } for i := 0; i < v.NumField(); i++ { // Check if this is upper-case. ftype := typ.Field(i) f := v.Field(i) if ftype.Anonymous { anonStr := layerString(f, true, writeSpace) writeSpace = writeSpace || anonStr != "" b.WriteString(anonStr) } else if ftype.PkgPath == "" { // exported if writeSpace { b.WriteByte(' ') } writeSpace = true fmt.Fprintf(&b, "%s=%s", typ.Field(i).Name, layerString(f, false, writeSpace)) } } if !anonymous { b.WriteByte('}') } return b.String() case reflect.Slice: var b bytes.Buffer b.WriteByte('[') if v.Len() > 4 { fmt.Fprintf(&b, "..%d..", v.Len()) } else { for j := 0; j < v.Len(); j++ { if j != 0 { b.WriteString(", ") } b.WriteString(layerString(v.Index(j), false, false)) } } b.WriteByte(']') return b.String() } return fmt.Sprintf("%v", v.Interface()) }
// Checks whether the given value is writeable to this schema. func (rs *RecordSchema) Validate(v reflect.Value) bool { v = dereference(v) if v.Kind() != reflect.Struct || !v.CanAddr() || !v.CanInterface() { fmt.Println("Incorrect record structure") return false } rec, ok := v.Interface().(GenericRecord) if !ok { // This is not a generic record and is likely a specific record. Hence // use the basic check. panic("Not supported") return v.Kind() == reflect.Struct } // If lengths for value and schema does not match up, then validate will fail if len(rs.Fields) != len(rec.fields) { return false } // Cache names in a map if rs.mapFields == nil { rs.mapFields = make(map[string]int) for idx := range rs.Fields { rs.mapFields[rs.Fields[idx].Name] = idx } } field_count := 0 for key, val := range rec.fields { // Implement a fast path. If all names of the fields match up, we assume schemas will match too. // This may not be true in general, but in our case it is, and recursively validating fields is // very expensive. if _, ok := rs.mapFields[key]; ok { field_count++ continue } else { break } for idx := range rs.Fields { // key.Name must have rs.Fields[idx].Name as a suffix if len(rs.Fields[idx].Name) <= len(key) { lhs := key[len(key)-len(rs.Fields[idx].Name) : len(key)] if lhs == rs.Fields[idx].Name { if !rs.Fields[idx].Type.Validate(reflect.ValueOf(val)) { fmt.Println("field validation failed ..", lhs, "..", rs.GetName()) return false } field_count++ break } } } } // All of the fields set must be accounted for in the union. if field_count < len(rec.fields) { return false } return true }
func getFormatterInterface(v reflect.Value) (f fmt.Formatter, ok bool) { ok = v.CanInterface() if !ok { return } f, ok = v.Interface().(fmt.Formatter) return }
func rvToExpr(rv reflect.Value) ast.Expr { if rv.CanInterface() { if e, ok := rv.Interface().(ast.Expr); ok { return e } } return nil }
// handleMethods attempts to call the Error and String methods on the underlying // type the passed reflect.Value represents and outputes the result to Writer w. // // It handles panics in any called methods by catching and displaying the error // as the formatted value. func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { // We need an interface to check if the type implements the error or // Stringer interface. However, the reflect package won't give us an // interface on certain things like unexported struct fields in order // to enforce visibility rules. We use unsafe to bypass these restrictions // since this package does not mutate the values. if !v.CanInterface() { v = unsafeReflectValue(v) } // Choose whether or not to do error and Stringer interface lookups against // the base type or a pointer to the base type depending on settings. // Technically calling one of these methods with a pointer receiver can // mutate the value, however, types which choose to satisify an error or // Stringer interface with a pointer receiver should not be mutating their // state inside these interface methods. var viface interface{} if !cs.DisablePointerMethods { if !v.CanAddr() { v = unsafeReflectValue(v) } viface = v.Addr().Interface() } else { if v.CanAddr() { v = v.Addr() } viface = v.Interface() } // Is it an error or Stringer? switch iface := viface.(type) { case error: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.Error())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.Error())) return true case fmt.Stringer: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.String())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.String())) return true } return false }
//only cacheable values will be inspected at attribute level and, perhaps, stored separately. //non cacheable values, will be stored at all func addIfCacheable(values *[]reflect.Value, value reflect.Value) { if value.IsValid() && value.CanInterface() { // i really try to put these two ifs at the same line... sorry about that :-( if cacheable, isCacheable := value.Interface().(Cacheable); isCacheable && len(cacheable.GetCacheKey()) > 0 { //the value is cacheable and key is not empty *values = append(*values, value) } } }
func isReadableReader(src reflect.Value) bool { if !(src.CanInterface()) { return false } if _, ok := src.Interface().(io.Reader); ok { return true } return false }
func pretty(v reflect.Value, indent string) string { var result string // If it's a Stringer, and we can get to it, use that if v.CanInterface() { if s, ok := v.Interface().(fmt.Stringer); ok { return s.String() } } switch v.Kind() { case reflect.Interface: if v.IsNil() { return "nil" } return pretty(v.Elem(), indent) case reflect.Slice: fallthrough case reflect.Array: n := v.Len() result = fmt.Sprintf("[%d]%s[\n", n, v.Type().Elem()) for i := 0; i < n; i++ { f := pretty(v.Index(i), indent) result += indent + addIndent(f, indent) + "\n" } result += "]" return result case reflect.Ptr: if v.IsNil() { return "nil" } return fmt.Sprintf("&%s", pretty(v.Elem(), indent)) case reflect.Struct: n := v.NumField() result = fmt.Sprintf("%v{\n", v.Type()) for i := 0; i < n; i++ { sf := v.Type().Field(i) f := pretty(v.Field(i), indent) result += fmt.Sprintf("%s%s: %s\n", indent, sf.Name, addIndent(f, indent)) } result += "}" case reflect.Map: result = fmt.Sprintf("map[%s]%s[\n", v.Type().Key(), v.Type().Elem()) keys := v.MapKeys() for _, k := range keys { e := v.MapIndex(k) keyStr := addIndent(pretty(k, indent), indent) elemStr := addIndent(pretty(e, indent), indent) result += fmt.Sprintf("%s%s: %s\n", indent, keyStr, elemStr) } result += "]" default: result = fmt.Sprintf("%v", getInterfaceDammit(v)) } return result }
/* func (handler *JsonHttpHandler) rpcCall(funcMeta *ApiFuncMeta, rawInput *httpInput) (interface{}, error) { if handler.ReflectDecl == nil { return structRpcCall(funcMeta, rawInput) } objectReflectType := funcMeta.AttachObject.Type() f, ok := handler.ReflectDecl.GetMethodDeclByReflectType(objectReflectType, funcMeta.MethodName) if !ok { return nil, fmt.Errorf("not found method in ReflectDecl %s.%s", objectReflectType.Name(), funcMeta.MethodName) } reflectFuncDecl, err := f.GetReflectFuncDecl(funcMeta.Func.Type(), funcMeta.IsMethod) if err != nil { return nil, fmt.Errorf("func %s.%s FuncDecl not match reflect err:%s", objectReflectType.Name(), funcMeta.MethodName, err.Error()) } if len(reflectFuncDecl.Results) > 0 && !reflectFuncDecl.ResultHasNames { return nil, fmt.Errorf("func %s.%s need have result name to become a api func", objectReflectType.Name(), funcMeta.MethodName) } inValues := make([]reflect.Value, funcMeta.Func.Type().NumIn()) if funcMeta.IsMethod { inValues[0] = funcMeta.AttachObject } if len(reflectFuncDecl.Params) > 0 { inRaw := map[string]json.RawMessage{} err := json.Unmarshal([]byte(rawInput.Data), inRaw) if err != nil { return nil, fmt.Errorf("api input shuold be a map :%s", err.Error()) } for key, rawData := range inRaw { field, ok := reflectFuncDecl.ParamMap[key] if !ok { continue } thisValuePtr := reflect.New(field.Type) err := json.Unmarshal([]byte(rawData), thisValuePtr.Interface()) if err != nil { return nil, fmt.Errorf("api input key: %s, type not match: %s", key, err.Error()) } inValues[field.Index] = thisValuePtr.Elem() } //zero value input for key not in ParamMap for i, value := range inValues { if value.IsValid() { continue } inValues[i] = reflect.Zero(funcMeta.Func.Type().In(i)) } } return nil, errors.New("not implement rpcCall by function param name") } */ func structRpcCall(funcMeta *ApiFuncMeta, rawInput *httpInput) (interface{}, error) { funcType := funcMeta.Func.Type() var inValues []reflect.Value var apiOutputValue reflect.Value serviceValue := funcMeta.AttachObject switch funcType.NumIn() { case 1: inValues = []reflect.Value{serviceValue} case 2: apiInputValue, err := jsonUnmarshalFromPtrReflectType(funcType.In(1), []byte(rawInput.Data)) if err != nil { return nil, err } inValues = []reflect.Value{serviceValue, apiInputValue} case 3: apiInputValue, err := jsonUnmarshalFromPtrReflectType(funcType.In(1), []byte(rawInput.Data)) if err != nil { return nil, err } apiOutputValue = reflect.New(funcType.In(2).Elem()) inValues = []reflect.Value{serviceValue, apiInputValue, apiOutputValue} default: return nil, &ApiFuncArgumentError{Reason: "only accept function input argument num 0,1,2", ApiName: rawInput.Name} } switch funcType.NumOut() { case 0: case 1: if funcType.Out(0).Kind() != reflect.Interface { return nil, &ApiFuncArgumentError{ Reason: "only accept function output one argument with error", ApiName: rawInput.Name, } } default: return nil, &ApiFuncArgumentError{Reason: "only accept function output argument num 0,1", ApiName: rawInput.Name} } outValues := funcMeta.Func.Call(inValues) var output interface{} if apiOutputValue.IsValid() && apiOutputValue.CanInterface() { output = apiOutputValue.Interface() } if len(outValues) == 1 { if outValues[0].IsNil() { return output, nil } err, ok := outValues[0].Interface().(error) if ok == false { return nil, &ApiFuncArgumentError{ Reason: "only accept function output one argument with error", ApiName: rawInput.Name, } } return nil, err } return output, nil }
func convertMarshal(val reflect.Value) (bool, string, error) { // Check first for the Marshaler interface if val.Type().NumMethod() > 0 && val.CanInterface() { if marshaler, ok := val.Interface().(Marshaler); ok { ret, err := marshaler.MarshalFlag() return true, ret, err } } return false, "", nil }
// if this value is a Locker, lock it and add it to the locks slice func (w *walker) lock(v reflect.Value) { if !w.useLocks { return } if !v.IsValid() || !v.CanInterface() { return } type rlocker interface { RLocker() sync.Locker } var locker sync.Locker // We can't call Interface() on a value directly, since that requires // a copy. This is OK, since the pointer to a value which is a sync.Locker // is also a sync.Locker. if v.Kind() == reflect.Ptr { switch l := v.Interface().(type) { case rlocker: // don't lock a mutex directly if _, ok := l.(*sync.RWMutex); !ok { locker = l.RLocker() } case sync.Locker: locker = l } } else if v.CanAddr() { switch l := v.Addr().Interface().(type) { case rlocker: // don't lock a mutex directly if _, ok := l.(*sync.RWMutex); !ok { locker = l.RLocker() } case sync.Locker: locker = l } } // still no callable locker if locker == nil { return } // don't lock a mutex directly switch locker.(type) { case *sync.Mutex, *sync.RWMutex: return } locker.Lock() w.locks[w.depth] = locker }
func interfaceFrom(field reflect.Value, fn func(interface{}, *bool)) { // it may be impossible for a struct field to fail this check if !field.CanInterface() { return } var ok bool fn(field.Interface(), &ok) if !ok && field.CanAddr() { fn(field.Addr().Interface(), &ok) } }
// if this value is a Locker, lock it and add it to the locks slice func (w *walker) lock(v reflect.Value) { if !w.useLocks { return } if !v.IsValid() || !v.CanInterface() { return } type rlocker interface { RLocker() sync.Locker } var locker sync.Locker // first check if we can get a locker from the value switch l := v.Interface().(type) { case rlocker: // don't lock a mutex directly if _, ok := l.(*sync.RWMutex); !ok { locker = l.RLocker() } case sync.Locker: locker = l } // the value itself isn't a locker, so check the method on a pointer too if locker == nil && v.CanAddr() { switch l := v.Addr().Interface().(type) { case rlocker: // don't lock a mutex directly if _, ok := l.(*sync.RWMutex); !ok { locker = l.RLocker() } case sync.Locker: locker = l } } // still no callable locker if locker == nil { return } // don't lock a mutex directly switch locker.(type) { case *sync.Mutex, *sync.RWMutex: return } locker.Lock() w.locks[w.depth] = locker }
// encodeInterface examines the interface represented by the passed reflection // value to detect whether it is an interface that can be encoded if it is, // extracts the underlying value to pass back into the encode function for // encoding according to its type. // // A MarshalError is returned if any issues are encountered while encoding // the interface. func (enc *Encoder) encodeInterface(v reflect.Value) (err error) { if v.IsNil() || !v.CanInterface() { msg := fmt.Sprintf("can't encode nil interface") err = marshalError("encodeInterface", ErrNilInterface, msg, nil) return err } // Extract underlying value from the interface and indirect through pointers. ve := reflect.ValueOf(v.Interface()) ve = enc.indirect(ve) return enc.encode(ve) }