// Any formats any value as a string. funcAny(value interface{})string { return formatAtom(reflect.ValueOf(value)) }
// formatAtom formats a value without inspecting its internal structure. funcformatAtom(v reflect.Value)string { switch v.Kind() { case reflect.Invalid: return"invalid" case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return strconv.FormatInt(v.Int(), 10) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return strconv.FormatUint(v.Uint(), 10) // ...floating-point and complex cases omitted for brevity... case reflect.Bool: return strconv.FormatBool(v.Bool()) case reflect.String: return strconv.Quote(v.String()) case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Slice, reflect.Map: return v.Type().String() + " 0x" + strconv.FormatUint(uint64(v.Pointer()), 16) default: // reflect.Array, reflect.Struct, reflect.Interface return v.Type().String() + " value" } }
通过reflect.Value 修改值
有一些reflect.Values是可取地址的;其它一些则不可以。
1 2 3 4 5 6
x := 2// value type variable? a := reflect.ValueOf(2) // 2 int no b := reflect.ValueOf(x) // 2 int no c := reflect.ValueOf(&x) // &x *int no d := c.Elem() // 2 int yes (x)
x := 2 d := reflect.ValueOf(&x).Elem() // d refers to the variable x // 方法一 px := d.Addr().Interface().(*int) // px := &x *px = 3// x = 3 fmt.Println(x) // "3"
x := 1 rx := reflect.ValueOf(&x).Elem() rx.SetInt(2) // OK, x = 2 rx.Set(reflect.ValueOf(3)) // OK, x = 3 rx.SetString("hello") // panic: string is not assignable to int rx.Set(reflect.ValueOf("hello")) // panic: string is not assignable to int
var y interface{} ry := reflect.ValueOf(&y).Elem() ry.SetInt(2) // panic: SetInt called on interface Value ry.Set(reflect.ValueOf(3)) // OK, y = int(3) ry.SetString("hello") // panic: SetString called on interface Value ry.Set(reflect.ValueOf("hello")) // OK, y = "hello"
通过反射机制可以读取结构体中未导出的成员, 但不可修改
1 2 3 4 5 6 7
stdout := reflect.ValueOf(os.Stdout).Elem() // *os.Stdout, an os.File var fmt.Println(stdout.Type()) // "os.File" fd := stdout.FieldByName("fd") fmt.Println(fd.Int()) // "1" fd.SetInt(2) // panic: unexported field fmt.Println(fd.CanAddr(), fd.CanSet()) // "true false"
应用:下面代码表示如果传入的结构体中有ImageUrl字段则加上一个后缀
1 2 3 4 5 6 7 8 9 10 11 12 13
funccompressImage(req interface{}) { modelType := reflect.TypeOf(req).Elem() modelValue := reflect.ValueOf(req).Elem() _, ok = modelType.FieldByName("ImageUrl") if ok { value := modelValue.FieldByName("ImageUrl") imageUrl := value.String() if strings.HasSuffix(imageUrl, ".jpg"){ value.SetString(imageUrl + "!compress") } } }