2020/05/03

[golang]go.modのreplaceを使ってlocal pathにする

ルールが分かればあきらめが付くはず、というわけで、golangのモジュールを理解しようと努めている。
いつか決定版の記事を書きたいものだが、それまでは試行錯誤が続く・・・。

 

golangで実装する場合、必ずgitなりなんなりを使うとは限らない。
どちらかといえば、使わない場合の方が多いかもしれない。
しかし、golangはおそらくバージョン管理システムを使う前提になっているので、そこで混乱してしまうのだろう(仮説)。

 

というわけで、これだ。

When should I use the replace directive?
https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive

Can I work entirely outside of VCS on my local filesystem?
https://github.com/golang/go/wiki/Modules#can-i-work-entirely-outside-of-vcs-on-my-local-filesystem

Version Control Systemを使ってないローカルファイルシステムでもできますか?というところか。
こういうFAQがあるからVCSを使う前提なのだろうと感じているのだ。Googleはなんでもネット上においてもらう戦略なんだけど抜け道はあるよ、ということなのかしらね。

 

replace自体はそんなに難しいものではなく、左側になっているものを右側とみなしてgoコンパイラというかgoコマンドが処理する、というところだろう。
左側にはimportに書いたものを、右側には置き換えたい先を書く。基本的にネットにあるものを取得する前提なので、ローカルパスを指定する場合は、

  • /で始まるパス(絶対パス)
  • ./で始まるパス(カレントディレクトリからの相対パス)
  • ../で始まるパス(上位ディレクトリからの相対パス)

のいずれかになる。

 


ここまでは、まあいいだろう。

いずれGitHubにアップする予定で、2つのpackageを作っていたとしよう。
github.com/hirokuma/helloとgithub.com/hirokuma/world。
helloはworld側の関数を呼び出して文字列を取得し、それをfmt.Printf()するだけということにする。
world側はwordingとlistというpackageを内部で持っていて、wordingの方はlistから文字列を取得するようにしている。

 

これをGitHubにアップする前にビルドしたい。
そうすると、最終的にこうなった。

 

image

hello/go.mod

01: module github.com/hirokuma/hello
02: 
03: go 1.14
04: 
05: require github.com/hirokuma/world/wording v0.0.0
06: require github.com/hirokuma/world/list v0.0.0
07: 
08: replace github.com/hirokuma/world/wording => ../world/wording
09: replace github.com/hirokuma/world/list => ../world/list
  

 

  • helloからは直接参照していないworld/listについてもgo.modに書かないといけない
  • world/listにもreplaceがいる
  • world/wordingとworld/listにそれぞれgo.modがいる

replaceのwildcard指定については要望にありそうだが、v1.4には入っていないし、今後も不明だ。

 

じゃあ、いっそのことimportの方を相対パスで書けばいいやん、と思ったのだが、それはダメだった。
"non-local package"はエラーらしい。
packageのあるディレクトリにあるファイルはダメだとか、そんな記事があったけど確かめてはいない。

Relative import paths(これの2番目の方)
https://golang.org/cmd/go/#hdr-Relative_import_paths

>To avoid ambiguity, Go programs cannot use relative import paths within a work space.
などといっているので、work space(作業ディレクトリ?)を全然別にしてしまえばよいのかもしれん。

が、なんか面倒なので、gitのsubmoduleにして全部平たくしてしまう方がいいのか。

 

ちなみに、go.modにrequireを書いていない場合、go buildすると勝手に追加された。

01: module github.com/hirokuma/hello
02: 
03: go 1.14
04: 
05: replace (
06:     github.com/hirokuma/world/list => ../world/list
07:     github.com/hirokuma/world/wording => ../world/wording
08: )
09: 
10: require (
11:     github.com/hirokuma/world/list v0.0.0-00010101000000-000000000000 // indirect
12:     github.com/hirokuma/world/wording v0.0.0-00010101000000-000000000000
13: )

勝手に追加しないで、別ファイルにしてくれると非常に助かるのだけどね! せめて更新を許可したときだけ上書きとかにしてほしいんだけどね!

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。

注: コメントを投稿できるのは、このブログのメンバーだけです。