golang におけるパッケージパスへの苦情
今日は、ただの愚痴です。
golang で開発する上で、「パッケージパス」からは逃げられない。
- 全てのファイルは、パッケージに所属していなければいけない。
- パッケージパスは、フォルダ構造に依存する。
そして、パッケージパスは、悲しいことに、「インターネット」から逃げられない。
- 外部パッケージのパッケージパスは、Web の URI に依存する。
これをちょっと整理して、苦情を述べる。 (主に3つ目に対して)
結論
パッケージパスは自由に決めさせてくれ!
パッケージパスとフォルダ構造
まず最初に、全てのファイルはパッケージに所属していなければいけない。
・・・が、これはさほど問題ではない。
package main func main() { // hello ... }
問題になるのは、パッケージパスである。
以下が、標準(?)的なgolangのフォルダ構造である。
$GOPATH + src/ + hoge.com/ + mycmd/ + libA/ | + lib_a1.go | + lib_a2.go + libB/ | + lib_b.go + main.go
まず、全てのファイルは $GOPATH/src
配下にあることを期待される。 *1
次に、「同じフォルダに属するファイルは、全て同じパッケージ名」でないといけない。
つまり、パッケージ名を分けたい場合は、フォルダを分けなければいけない。
// mycmd/libA/lib_a1.go package libA1 // mycmd/libA/lib_a2.go package libA2 // ERROR!!
また、別パッケージを取り込む場合は、子孫フォルダにあるファイルでも、絶対パス でないといけない。 *2
// mycmd/main.go import ( "hoge.com/mycmd/libA" // 自分の内部パッケージを使うのに、 "hoge.com/mycmd/libB" // なんで絶対パスなんだよ・・・ )
パッケージパスとWeb URI
そして、ここが最悪なことに、パッケージパスは「Webでアクセス可能な場所」であることを要求される。
実例で言うと、上記の mycmd
の場合、以下のコマンドが動くことを要求されるのである。
go get hoge.com/mycmd
なぜこうなったか予想だけど (文献サーチ5秒じゃ、ちゃんと見つからなかった)
- 外部パッケージパスの衝突を防げる
- ビルド時に、必要なパッケージを発見&入手を自動化できる
という利点があるからだろう。
かなり大きな利点である。
しかし、これが大きな弊害にもなる。
- 自分の内部パッケージを使うのに、Web URI が必要になる。
- fork した際に、内部パッケージの パッケージパス を変更する必要がある。
- 開発リポジトリを複数持ちたいけど、パッケージパスは 1つしか入らない。
1つ目が、個人的に一番嫌い。
個人的なリポジトリで開発してるから、開発初期は、適当なパッケージパス hoge.com/mycmd
を入れておく。
後日、github で公開すると決めた場合、そのパッケージパスを github.com/hidez8891/mycmd
に書き換える必要がある。
しかし、git のログには hoge.com/mycmd
が残ったままになる・・・大変かっこ悪いのである!!
2つ目も、だいたい同じ理由。
ライブラリの修正のために fork して別リポジトリにした場合 (githubでよくある)、
ビルドを通すためには、内部パッケージのパッケージパスを (いちいち) 書き換える必要がある。
3つ目は、公開と非公開リポジトリ運用をしてる場合に出会う。
たとえば、github と bitbucket で開発してる場合とか。
全て突き詰めると 「パッケージパスと配布場所を紐付ける」 ことに問題があることになる。
まとめ
結局、まとめると パッケージパスは自由に決めさせてくれ! に尽きる。
パッケージは自動取得は、go.mod
があるんだから、もうそっちでいいじゃんと。
go 1.12 以降で、ここらへん、変わってくれないかなー・・・