できない.dev

Go の go.mod の replace でローカルモジュールが参照できない

replace の右辺がローカルパスのとき、参照先に go.mod が無い・バージョンを書いてしまう・相対パスの基準がズレる、のいずれかで効かないことが多い。
go.mod を用意し、ローカル参照ではバージョンを省くと解決する。

公開: 更新:

実行例あり(2026-09-23 に実環境で検証)

要約

replace は、あるモジュールの内容を別のパス(別モジュールやローカルディレクトリ)へ置き換えるディレクティブです。

ローカル開発で隣のディレクトリを参照したいのに効かない場合、原因はほぼ「参照先に go.mod が無い」「ローカル参照なのにバージョンを書いた」「相対パスの基準ズレ」の 3 つです。

ローカルパス(./ や ../ 始まり)を右辺に書くときは、その先にモジュールルート(go.mod)が必要で、バージョンは省きます。

実行例

コンテナ(golang:1.23)で試すと、参照先の foo に go.mod が無い状態では go build が reading ../foo/go.mod で失敗し、foo で go mod init を済ませると同じビルドが通って go run . が hello from foo を出した。
右辺に @v1.0.0 を付けた replace は ../foo@v1.0.0 というディレクトリを探して失敗し、バージョンを外して go mod tidy した後の go list -m all には => ../foo が表示されている。

$ cat go.mod
module example.com/myapp
 
go 1.23
 
require example.com/foo v0.0.0
 
replace example.com/foo => ../foo
$ go build ./...
main.go:6:2: module ../foo: reading ../foo/go.mod: open /tmp/tmp.BX44IFPz3G/foo/go.mod: no such file or directory
終了コード: 1
$ go mod init example.com/foo
go: creating new go.mod: module example.com/foo
go: to add module requirements and sums:
	go mod tidy
$ go build ./...
終了コード: 0
$ go run .
hello from foo
$ go mod edit -replace=example.com/foo=../foo@v1.0.0
$ go build ./...
main.go:6:2: example.com/foo@v0.0.0: replacement directory ../foo@v1.0.0 does not exist
終了コード: 1
$ go mod edit -replace=example.com/foo=../foo
$ go mod tidy
$ go list -m all
example.com/myapp
example.com/foo v0.0.0 => ../foo
$ go run .
hello from foo
終了コード: 0

— 2026-09-23 時点の出力

検証環境

検証日
実行環境
golang:1.23Debian GNU/Linux 12 (bookworm)
バージョン
  • Python 3.11.2
  • Git 2.39.5
  • Go 1.23.12

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. 参照先に go.mod が無く、置き換え対象がモジュールとして認識されない。
  2. ローカルパス参照に v1.0.0 のようなバージョンを付けている。
  3. ../foo の基準が、編集している go.mod の場所と食い違っている。

解決策

1. 参照先に go.mod を用意する

cd ../foo
go mod init example.com/foo

ローカルパスの右辺は「go.mod を含むディレクトリ」である必要があります。

2. replace をローカルパスで書く(バージョンなし)

require example.com/foo v0.0.0
 
replace example.com/foo => ../foo

コマンドで追記しても同じです。

go mod edit -replace=example.com/foo=../foo

ローカルパス参照のときは右辺にバージョンを書かないのがポイントです。

3. 反映を確認する

go mod tidy
go list -m all

go list -m all の出力で対象が => ../foo に置き換わっていれば成功です。
公式の Go Modules Reference(新しいタブで開く) の replace 節も参照してください。

この記事は役立ちましたか?