Go言語におけるinterface{}とリフレクションを使ったパターン
September 19, 2013
この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。
出力引数としてinterface{}を受け取る
設定したい変数のポインタをinterface{}として受け取る。
interface{}なので、任意の型を渡すことができる。
reflect.ValueOfでreflect.Value型に変換する。
その後、Value.Elem()でポインタが指している先を取得して、Value.Set()で値を設定する。
http://play.golang.org/p/qsTwrL11mu
package main
import (
	"fmt"
	"reflect"
)
func set(p, v interface{}) error {
	pv := reflect.ValueOf(p)
	if pv.Kind() != reflect.Ptr {
		return fmt.Errorf("p must be pointer.")
	}
	vv := reflect.ValueOf(v)
	if pv.Elem().Kind() != vv.Kind() {
		return fmt.Errorf("p type and v type do not mutch")
	}
	pv.Elem().Set(vv)
	return nil
}
func main() {
	var hoge int
	fmt.Println(hoge)
	set(&hoge, 100)
	fmt.Println(hoge)
	fmt.Println(set(&hoge, 10.4))
}関数をinterface{}で受け取る
関数は引数や戻り値を含めて型なので、引数や戻り値が一致しないと同じ型として扱うことができない。そのため、引数の型をinterface{}にしておき、任意の関数を渡し、リフレクションして呼び出す。
http://play.golang.org/p/fFmGNRlqcn
package main
import (
	"fmt"
	"reflect"
)
func call(f interface{}) {
	fv := reflect.ValueOf(f)
	if fv.Kind() != reflect.Func {
		panic("f must be func.")
	}
	fv.Call([]reflect.Value{})
}
func main() {
	f := func() {
		fmt.Println("hello!")
	}
	call(f)
}