golangの欠陥

Go(golang)はかなりいろいろなことがよく考えられた良い言語だが、大きな欠陥がある。その欠陥はやはりimport。gitやmercurial等のリモートリポジトリを指定できてそれはそれで大層便利ではあるのだが、タグやブランチ、バージョン等を指定できない(常にmasterのHEADが使われる)ことがしばしば問題となる。

このimport問題の中でもとりわけ大きなものが、local importの問題だ。

リポジトリ上で開発していて、同じリポジトリのサブディレクトリを対象にimportしたいとする。

import "./subdir"

通常はこれで良いのだが、$GOPATH/src以下もgo getでcloneしてくるリポジトリになっていて、ここのソースに対して作業をしていると、相対パスによるimportがエラーになる。

can't load package: /path/to/go/src/github.com/wtnb75/xxxxx/yyyy.go:16:2: local import "./subdir" in non-local package

つまり、$GOPATHにのっとって開発する(実際golangではそれが推奨されている)場合は、こう書かなければならない。

import "github.com/wtnb75/xxxxx/subdir"

それがgithub.com/wtnb75/xxxxxからimportする場合でもそうなのだ。これは時折深刻な問題を引き起こす。xxxxx/subdir以下の関数の引数を変更し、呼び出し元のxxxxxの呼び出し方も追随して変更することを考える。github flowではこのような場合ブランチを切ってcommit, pushし、作業が終了して動くようになったらPull Request(PR)を出し、レビューを受けてマージしてもらう。自分がメンバーに入っていない赤の他人のプロジェクトであればpush先を自分のテンポラリのリポジトリにしてPRを出すし、メンバーに入っていれば元のリポジトリのブランチで作業するわけだ。

このときdroneやtravis(jenkinsも)といったツールを使ってビルド/テストしたり、自分でもローカルでcloneしてビルドするとか、ブランチを切ってテストするといったことをする。$GOPATH以下にpullしてきてテストする場合は良いのだが、別のところにcloneしてしまった場合。このときimport文が元のままだと、この、、、

import "github.com/wtnb75/xxxxx/subdir"

これはmasterのHEADなわけだから、subdir以下のAPIは変更される前であって、呼び出し元はcloneされた新しいものだ。結果として起きるのはビルドの失敗。テストができない。github flowにおいてはmasterは常にデプロイ可能な状態である、という原則がある。そこで質問だが、ビルドもできないものを好んでmasterにマージしたい人はいるだろうか?

だから、私としてはimportは、それが$GOPATH/src以下であっても相対パスで指定できて欲しいと思う。実際go getで取ってきたディレクトリそのままのところでgitで差分を見ながら作業するってのがそれなりに快適なので、それを邪魔するような機能はつけないで欲しいと思う。local import in non-local packageのエラー…それをエラーにする意義はないんじゃないかな。

おそらく現状だとテスト側としては正しいのはgo getで$GOPATH/src以下に持ってきて、git checkoutでブランチを手動で切り替えてテストを続ける、という一手間だろう。go getやgo buildではcloneが起きるときはmasterだけどあと修正されたかどうかは気にしないので、これでうまくいく。

ただ面倒っちゃ面倒だよね。

$GOPATH/src以下でlocal importができるようになれば解決する。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です