構造体の変数に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の可能性のある構造体のメンバにアクセスしないといけないようなとき等に使える。