#go.modってどこにおくのがいいのか
先日一からgoでサービスを作っていたのですが、go.modの置き場で迷ってしまい少し時間を無駄遣いした時に、意外と日本語の情報がなかったので残そうと思います。
#結論:ルートディレクトリに置く
結論からいうと、プロジェクトのルートディレクトリにおくのが正解でした。
go modはもともと業務でも使っていたのである程度知識はあると思っていたのですが、いざ自分で初めから作るとなるとどこで go mod init
するんだ?ってなってしまいました。勉強不足です。色々とググってみたのですが、あまりgo.modをおく場所に関する情報はなくて、自分で色々いじってみてなんとか解決しました。
解決した後に1次ソースには当たっていなかったので(まず当たれという話ですが、、)1次ソースをみてみるとそう行った記述がありました。
A module is a collection of Go packages stored in a file tree with a go.mod file at its root.
ざっくり訳すと
モジュールとは、ルートディレクトリにgo.modがあるファイルツリーに保存されたGoのパッケージのコレクションである
という感じでしょうか。つまり、ルートディレクトリにgo.modを置くのが正解。ということでした。
#自分でいじってみて、もうちょっと突っ込んでみる
初め、自分は1次ソースに当たらずに自分で調べたりいじったりしたので、自分なりの理解も得られました。
###そもそも、 go.mod
がルートディレクトリにないとどうなるのか
例えば、こんな構成のコードがあったとします。
Service
|
ー handler
ー model
ー dao
こういう構成であれば、handlerからdaoをimportする時、こう書きたいですよね
import "Service/dao"
ですが、例えば、go.modをhandler,model,daoの各ディレクトリ内に置いてしまうと、コンパイルした時にhandler,model,daoが別の外部パッケージとして見なされてしまい、「gorootかgopath内にそんなパッケージないよ」といった旨のエラーが吐かれます。
(私はこれが、gorootやgopahtにないというエラー内容から、go.modの配置の問題であることに気づくのが遅れました。)
また、エディタ上でもgo.modを参照して依存を解決している場合、赤くなると思います。
これを、Service配下にgo.modを一つ置くようにすることでhandler,model,daoが同一パッケージないのものとみなされ、上のimport文で解決できるようになります。
反対に、自分で作ったパッケージをサブパッケージみたいに外部パッケージとして読み込みたい場合は、上の例であれば、handler,models,dao内にgo.modをおいて、giuhubとかに上げて、
import "github.com/user_name/repository_name/..."
と書いてあげれば、良さそうなこともわかりました。
#最後に
go.modは自分が同一パッケージとして見なしたいもののルートディレクトリに置く、というのが正解でした。
それと、go.modの配置が悪くて依存が解決できない場合、コンパイルエラーのメッセージが
"package_name" is not in GOROOT
みたいに出ます。(goのバージョンで文言が変わる)なので、このエラーメッセージの時は、go.mod周りを疑うといいのかなと思いました。
何かを調べるときは、英語嫌がらずにまず1次ソースに当たるのがやはりいいですね、、