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)
}