エラー内容
gopls requires a module at the root of your workspace.
You can work with multiple modules by opening each one as a workspace folder.
Improvements to this workflow will be coming soon, and you can learn more here:
https://github.com/golang/tools/blob/master/gopls/doc/workspace.md.go list
gopls
が吐き出している上記エラーは、2 つの内容に分かれています。
-
gopls requires ... of your workspace.
- 「プロジェクトのルート・ディレクトリに
go.mod
が存在しないため、必要なパッケージが検証できない」という意味
-
You can work with multiple ... go list
- 「プロジェクト内に複数の
go.mod
を設置する必要がある(複数の main.go
がある)場合は go.work
を利用してワークスペースとして定義できます」という意味
今回は、モノリシックなプロジェクトではない(複数の異なるプロジェクトを 1 つのリポジトリで管理するタイプではない)ので、前者のエラー内容が該当します。
原因
gopls
が ./bookputGo/
に Go(以下 golang)のコード(main.go
)を見つけるも、パッケージ情報(go.mod
と go.sum
)がプロジェクトのルートにないため、コードを解析する際に必要なモジュールが事前に読み込めずエラーを表示します。
しかし、サブ・ディレクトリに ./bookputGo/go.mod
を見つけたため、マルチ・モジュールかもしれないと、二つ目のエラーを表示しています。
対策
bookputGo/go.mod
を一階層上のプロジェクトのルートに設置・移動する必要があります。
理由
gopls
は静的解析ツール(プログラムをコンパイルせずに、ソースコードを構文解析するタイプ)なので、あらかじめプロジェクトが必要とするパッケージやモジュールを定義したファイル(go.mod
もしくは go.work
)をプロジェクト・ルートに置いておく必要があります。
つまり、main.go
と同じ階層で go mod init ...
をせずに、プロジェクトのルート(yarn.lock
などと同じ階層)で go mod init github.com/shunsa10/bookput
を実行します。
そして go mod tidy
すると、サブ・ディレクトリを含むディレクトリをスキャンして、各々のパッケージで import
されているモジュールを見つけると go.mod
に追記し、その時点のモジュールのバージョンを go.sum
に記録します。
go.mod
は Node.js でいう package.json
と同じ役割をするものです。つまり、そのプロジェクトで利用されるモジュールを定義したファイルです。
そして、go.sum
は yarn.lock
と同じで、動作確認が取れているモジュール/パッケージのバージョンが記載されたものです。
モジュールとパッケージ
わかりづらいのですが、golang において、他の言語(例えば PHP や Java など)でいうモジュールとパッケージの概念が、最初のうちは感覚的に逆になります(Go に慣れてくると同じものだと気づくのですが)。
-
パッケージとは: 1 つのディレクトリに収まっている Go コードのこと
-
モジュールとは: 上記パッケージを 1 つにまとめたもの(
go.mod
以下にある package
ファイル)
特に、main.go
のトップには package main
と書くものだから、「main
パッケージが必要とするモジュールは同じ階層に go.mod
として置く」と思い込みがちです。
しかし、go.mod
は「そのプロジェクトが必要とするモジュールを定義しているもの」です。
つまり、go get ...
で利用できるライブラリのような main.go
が存在しないプロジェクトであっても go.mod
は存在します。
そのため、golang においては、「パッケージとは、モジュールとして利用できる単位(package main
を除く)」と考えるといいかもしれません。