k0kubun's blog

railsへの執着はもはや煩悩の域であり、開発者一同は瞑想したほうがいいと思います。

RubyistのためのGolangメタプログラミング

Goでは、reflectパッケージを使うとリフレクションを行うことができる。
そこで、以下のことを任意のstringによる動的な指定で行うことができるかを調べた。

  • send (関数, メソッド呼び出し)
  • define_method (関数, メソッドの定義)
  • const_get (任意の型のオブジェクトの取得)

send (関数, メソッド呼び出し)

stringで関数, メソッド名を指定して呼び出すことができるか?

  • 関数: No
  • メソッド: Yes

関数のsend

変数に関数が入っていればその変数を使って呼び出せるが、普通に定義した関数をstringから参照する手段はない。もしやりたければ手動でmap[string]funcにつっこんでおくしかない。(これやっちゃうとメタプロにならなそう)

メソッドのsend

method := reflect.ValueOf(&receiver).MethodByName("MethodName")
method.Call([]reflect.Value{reflect.ValueOf(arg), ...})

(reflect.Value).MethodByName()でいける。
メソッドも引数もいちいちreflect.Valueでラップする必要があるのがちょっと面倒。

http://play.golang.org/p/9tCV4xAI-l

define_method (関数, メソッドの定義)

stringで指定した名前で呼び出せる関数, メソッド名を定義できるか?

  • 関数: No
  • メソッド: No

関数のdefie_method

reflect.MakeFunc()によって関数を動的に作ることはできる()。このため、関数を返す関数を作るとある程度楽はできる。しかし結局は定義済みの変数にいれなければ参照できない、というか当たり前だけどコンパイル通らない。
なので、Rubyみたいに「stringで指定した名前で呼び出せる」関数は定義できない。

メソッドのdefine_method

最初から目的のメソッドの型のフィールドを用意しておけばそこに動的に生成した関数をいれることはできるが、stringからフィールドを定義できない以上はこれも無理。

const_get (任意の型のオブジェクトの取得)

stringで指定した任意の型をnewできるか?: No

任意型のnew

reflect.New()を使うと、何かしらの値のreflect.Typeからそのnewをとることはできる。 が、stringで指定した型のreflect.Typeを持ってくることができないので、無理。

まとめ

stringによるメソッド呼び出しはできるが、他のことはあまりできない。

reflectについて調べたい人用リンク