## 12.5. 通過reflect.Value脩改值

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)


fmt.Println(a.CanAddr()) // "false"


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"


d.Set(reflect.ValueOf(4))
fmt.Println(x) // "4"


Set方法將在運行時執行和編譯時類似的可賦值性約束的檢査。以上代碼，變量和值都是int類型，但是如果變量是int64類型，那麽程序將拋出一個panic異常，所以關鍵問題是要確保改類型的變量可以接受對應的值：

d.Set(reflect.ValueOf(int64(5))) // panic: int64 is not assignable to int


x := 2
b := reflect.ValueOf(x)
b.Set(reflect.ValueOf(3)) // panic: Set using unaddressable value


d := reflect.ValueOf(&x).Elem()
d.SetInt(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"


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"