以下の記事に書いてあることをまとめる。
変数の値を変える
よく考えれば当たり前だが、一度ポインタにしないと変数の値を変えることができない。
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)
}