🐈

go.modは構造宣言、tidyは再整合、replaceは応急処置

に公開

本記事の要点

  • go.mod=構造宣言、tidy=再整合
  • replace=応急処置、恒久禁止

go.modの正体

go.mod ファイルは依存関係を記述するファイルと思われがちですが、実は構造を宣言するファイルです。

誤解パターン

正解パターン

go mod tidyによる再整合

go mod tidy は、このメインモジュール配下の 全パッケージ(テスト・ツール含む)を読み込み、依存を再整合します。
不要な依存は削除され、go.sum ファイルも更新されます。

ただし、この時に 下層フォルダに別の go.mod(別モジュール) が混ざっていると、go.mod ファイルの不整合を引き起こすことがあります。

再整合時の不整合対策

go mod tidy の前に、構造のねじれを解消します。前提は 単一モジュール(下層に go.mod を置かない)です。

症状(よくあるパターン)

  • tidy 後に 意図しない追加/削除 が大量発生する
  • go.sum が毎回大きく変わる
  • 下層フォルダにも 別の go.mod がある

手順(3ステップ)

  1. 混在検知
    • find . -name go.mod -not -path "./go.mod" で下層の go.mod を洗い出します。
    • 見つかったら 退避(リネーム or 別リポへ移動)。必要なら後日 go work へ昇格します。
  2. 前提を揃える
    • rm -rf vendor/(使っていれば後で再生成)
    • git restore --staged go.mod go.sum(一度きれいに)
    • キャッシュ由来なら go clean -modcache
  3. 再整合→差分確認
    • go mod tidy を実行
    • git diff go.mod go.sum追加/削除のみ を確認
    • 使っていない require を外し、replace応急処置のみ(コミットしない)

検証(軽量)

  • go build ./...go list -m all で整合を確認します。
  • vendor を使う場合は go mod vendor で再生成します。

replaceの役割

replace応急処置です。ローカル検証や一時差し替えに限り、恒久化しません
本流は「構造=go.mod/整合=tidy」。
replace はそれを壊さないための短期手段です。

定義

  • 応急処置:一時的に依存の解決先を差し替える(ローカル or 特定版にピン留め)

使うとき

  • リリース前の ローカル検証(開発中ブランチを当てたい)
  • キャッシュ破損などの 一時的な不具合回避
  • 上流のタグ公開待ちで 短期間だけ固定 したい

そもそも使わない

  • 長期運用の固定化(将来の更新で破綻しやすい)
  • 複数モジュールの接着(必要なら go work へ)
  • 依存の機能差分を恒常的に吸収(設計の問題)

推奨運用ルール

  1. 期限を決める:PRやIssue番号と撤去条件をコメントに明記
  2. コミットしない:原則ローカルのみ。やむを得ずコミットする場合は即撤去の期限をセット
  3. 再整合で戻すgo mod tidy → 差分確認 → replace 撤去

設定例

# 一時的にローカルの修正ブランチへ
replace example.com/lib => ../lib

# タグ公開待ちの短期ピン留め
replace example.com/lib v1.2.3 => example.com/lib v1.2.3-fixed

実務の手順

以下の手順で確認していくことで不整合のリスクを下げることができます。

  1. tidyの前提を固定(下層の go.mod 排除/vendor・go.sum の不一致解消)
  2. go mod tidy 実行 → git diff go.mod go.sum で追加/削除のみ確認
  3. 使っていない require を外す。replace は応急処置のみ(コミットしない)

まとめ

go.mod ファイルはモジュール全体を管理する宣言と位置付けて、依存の追加・削除時にはgo mod tidyで整合性を取りつつ、必要に応じてreplaceで構成が崩れないようにしましょう。
日頃からそう心がけていくことでモジュールの安定性が段違いに向上すると思います。

(相互リンク:本編の背景・設計・考察)
Qiita本編 → https://qiita.com/akio_asano/items/ac3a1f398c2939c96fc7

Discussion