構造体の変数にreflectでインスタンスを詰める方法メモ。
package main
import (
"fmt"
"reflect"
)
func main() {
var foo *Foo
fmt.Println(foo) // nil
fmt.Println("------------")
// nilにアクセスしようとするのでエラー
// foo.msg = "Hello"
// fooの型を取得
typ := reflect.TypeOf(foo).Elem()
// fooの型の実体を生成
dst := reflect.New(typ).Interface()
// foo変数への参照を取得
src := reflect.ValueOf(&foo).Elem()
fmt.Println(typ) // main.Foo
fmt.Println(src) // nil
fmt.Println(dst) // &{}
fmt.Println("------------")
// foo変数の参照に実体化したfooの型のを設定
src.Set(reflect.ValueOf(dst))
fmt.Println(typ) // main.Foo
fmt.Println(src) // &{}
fmt.Println(dst) // &{}
fmt.Println("------------")
// 生成した変数はすべて同じ構造体を参照している
foo.msg = "Hello"
fmt.Println(src) // &{Hello}
fmt.Println(dst) // &{Hello}
fmt.Println(foo) // &{Hello}
}
type Foo struct {
msg string
}
上記ではわかりやすく分割しているが、以下のように一行で書くことも可能。
package main
import (
"fmt"
"reflect"
)
func main() {
var foo *Foo
fmt.Println(foo) // nil
fmt.Println("------------")
reflect.ValueOf(&foo).Elem().Set(reflect.ValueOf(reflect.New(reflect.TypeOf(foo).Elem()).Interface()))
fmt.Println(foo)
}
type Foo struct {
msg string
}
基本的には使わないほうが良いが、コード生成時にnilの可能性のある構造体のメンバにアクセスしないといけないようなとき等に使える。