Goのユーザーとしてちょっと辟易していたこととして、開発チームがGoそのものの文法や標準ライブラリのAPIをガツガツ変更することが挙げられる。いやホントに良く変わる。発表されてからもう1年経ったけど、まだ当分安定するようには見えない。
で変更されて何が困るかというと、古いコードのコンパイルが通らなくなること。自分が書いたコードならいざしらず、他人が書いたコードのコンパイルが通らなくなってしまうと結構厄介。メンテナー次第では下手すると当分コードがアップデートされずにそのままなんてこともありうる。じゃあ自分で直そうにも、もしかしたらエンバグするかもしれないし、そもそもが面倒だからあんまりヤル気にならない。そうすると自分が使ってたパッケージが使えなくなって、でもかといって古いバージョンのGoを使う気にもなれなくて、開発に対するモチベーションが下がって…という酷い悪循環におちいる。自分は。
Gofix
そういう状況を開発チームも理解していたのか、ちょっと前にGofixなんていうツールが発表された。詳しくはRussの書いたブログを読んでもらうとして、Gofixがやってくれるのは簡単に言うと「コードの自動修復」だ。どうやら古いAPIやら文法が使われているコードを自動的に修復して、ナウいバージョンに仕立てなおしてくれるらしい。
Go fix Thrift
ということで、実益と実験も兼ねてThriftのGoコードをGofixにかける実験をやってみた。なお使用したバージョンはGoがr8131、Thriftがr1093950。
Thrift修正前
Thriftの修正前ライブラリを普通にコンパイルしようとしたら、以下のようになる。net.DialあたりのAPIが変わったせいでコンパイルが通らない。
$ make cd thrift/ && gomake install make[1]: Entering directory `/home/masato/lib/thrift/lib/go/thrift' 8g -o _go_.8 tapplication_exception.go tbase.go tbinary_protocol.go tcompact_protocol.go tcompare.go tcontainer.go texception.go tfield.go tframed_transport.go thttp_client.go tiostream_transport.go tlist.go tjson_protocol.go tmap.go tmemory_buffer.go tmessage.go tmessagetype.go tnonblocking_server.go tnonblocking_server_socket.go tnonblocking_socket.go tnonblocking_transport.go tnumeric.go tprocessor.go tprocessor_factory.go tprotocol.go tprotocol_exception.go tprotocol_factory.go tserver.go tserver_socket.go tserver_transport.go tset.go tsimple_server.go tsimple_json_protocol.go tsocket.go tstruct.go ttransport.go ttransport_exception.go ttransport_factory.go ttype.go tnonblocking_socket.go:111: too many arguments in call to net.Dial tsocket.go:137: too many arguments in call to net.Dial make[1]: *** [_go_.8] Error 1 make[1]: Leaving directory `/home/masato/lib/thrift/lib/go/thrift' make: *** [thrift/.install] Error 2
Thrift修正後
この状況から、まずGofixを走らせた上でmakeすると…
$ gofix . thrift/tnonblocking_socket.go: fixed netdial thrift/tsocket.go: fixed netdial $ make cd thrift/ && gomake install make[1]: Entering directory `/home/masato/lib/thrift/lib/go/thrift' 8g -o _go_.8 tapplication_exception.go tbase.go tbinary_protocol.go tcompact_protocol.go tcompare.go tcontainer.go texception.go tfield.go tframed_transport.go thttp_client.go tiostream_transport.go tlist.go tjson_protocol.go tmap.go tmemory_buffer.go tmessage.go tmessagetype.go tnonblocking_server.go tnonblocking_server_socket.go tnonblocking_socket.go tnonblocking_transport.go tnumeric.go tprocessor.go tprocessor_factory.go tprotocol.go tprotocol_exception.go tprotocol_factory.go tserver.go tserver_socket.go tserver_transport.go tset.go tsimple_server.go tsimple_json_protocol.go tsocket.go tstruct.go ttransport.go ttransport_exception.go ttransport_factory.go ttype.go rm -f _obj/thrift.a gopack grc _obj/thrift.a _go_.8 cp _obj/thrift.a "/home/masato/lib/google-go/pkg/linux_386/thrift.a" make[1]: Leaving directory `/home/masato/lib/thrift/lib/go/thrift'
こんな感じで上手く行く。スバラシイ。
Thrift修正差分
ついでにどういう差分が適用されたかを見てみる。下はdiffをとった結果の一部だけど、net.Dialのところに注目するとちゃんと引数が減らされてる。
- var err os.Error - if p.conn, err = net.Dial(p.addr.Network(), "", p.addr.String()); err != nil { - LOGGER.Print("Could not open socket", err.String()) - return NewTTransportException(NOT_OPEN, err.String()) - } - if p.conn != nil { - p.conn.SetTimeout(p.nsecTimeout) - } - return nil + var err os.Error + if p.conn, err = net.Dial(p.addr.Network(), p.addr.String()); err != nil { + LOGGER.Print("Could not open socket", err.String()) + return NewTTransportException(NOT_OPEN, err.String()) + } + if p.conn != nil { + p.conn.SetTimeout(p.nsecTimeout) + } + return nil
まとめ
ということで、Thriftという実例をつかってGofixの便利さを体感してみた。こういう便利ツールが公式に提供されて、かつほとんどが自動的に修正されるのであればAPIやら文法の変更もバンバンやってくれて構わないかも。
ちなみに、Thriftが生成したCassandraへのインタフェースライブラリをGofixしてもコンパイルが通らなかったことに関しては、また別の話。これThriftのバグなのか…? いまいち追う気になれない。
0 件のコメント:
コメントを投稿