以下の記事に書いてあることをまとめる。
変数の値を変える
よく考えれば当たり前だが、一度ポインタにしないと変数の値を変えることができない。
package main
import (
"fmt"
"reflect"
)
func main() {
n := 100
// ダメ
nv := reflect.ValueOf(n)
fmt.Println(nv.CanSet())
// ポインタを使う
npv := reflect.ValueOf(&n)
fmt.Println(npv.Elem().CanSet())
npv.Elem().SetInt(200)
fmt.Println(n)
}
一度ポインタにして、Elemメソッドでまたポインタの指す先に戻しているあたりが気持ち悪い。
Elemメソッドのソースを見ると、flagRO フラグは元のValueの物を保持して、flagAddrフラグとflagIndirフラグを立てている。そのため、CanSetメソッドでtrueが返る(つまり、代入可能にしている)ことが分かる。
一方、reflect.ValueOf(100)のようにした場合は、flagIndirしかフラグがたてられない。よって、CanSetはfalseとなり、Setできない。
構造体のフィールドの値を変える
上記と同様に、構造体のフィールドの値を変えるのにも一度ポインタに変換する必要がある。
package main
import (
"fmt"
"reflect"
)
type Hoge struct {
N int
}
func main() {
h := Hoge{10}
hpv := reflect.ValueOf(&h)
hpv.Elem().FieldByName("N").SetInt(200)
fmt.Println(h)
}