デバッガを扱う前にGoのmodule関連でつまづいた
go get で dlv
をinstallしたらビルド時にエラーが出た。
go: inconsistent vendoring in /go/src/app/xxxx:
github.com/go-delve/delve@v1.8.0: is explicitly required in go.mod, but not marked as explicit in vendor/modules.txt
golang.org/x/sys@v0.0.0-xxxxxxxx: is marked as explicit in vendor/modules.txt, but not explicitly required in go.mod
To ignore the vendor directory, use -mod=readonly or -mod=mod.
To sync the vendor directory, run:
go mod vendor
go: /go/src/app/xxxx でベンダリングに矛盾があります。github.com/go-delve/delve@v1.8.0: は go.mod で明示的に要求されていますが、 vendor/modules.txt では明示的にマークされていません。
golang.org/x/sys@v0.0.0-xxxxxx vendor/modules.txt では明示的にマークされていますが、go.mod では明示的に必要ではありません。
ベンダーディレクトリを無視するには、-mod=readonly または -mod=mod を使ってください。vendor ディレクトリを同期させるには、以下を実行します。
go mod vendor
vendor ディレクトリとは?
対応する概念として、module cacheがある。
vendor が使われるかどうかは、go.mod ファイルのバージョン記述に依存し、Go 1.14 以降は vendor が優先して使用される。1.14 未満の場合は module cache が優先される。
つまり、エラー内容としては、go get
によってdelve moduleが$GOPATH/binにinstallされ、go.modファイルにも明示的に示されているが、go.modファイルのversionは1.16となっているためデフォルトでvenderディレクトリ内のmoduleを参照しに行った結果、venderディレクトリには、「delve moduleはないよ」と言われてしまっている。
解決策としては、$GOPATH/binにinstallされてしまったdelve moduleをvenderディレクトリに移動させるようなことをすればいい。
go mod vendorは何をするか
go mod vendor
すると外部の依存モジュールを vendor ディレクトリにダウンロードする。
おそらく、$GOPATH/binをきれいにしてくれたりするわけではない。
go mod vendor
を実行するとエラーはなくなった。
想定通り、$GOPATH/binにinstallしてしまったものは消えてはくれない。
ようやくエラーがなくなったので、デバッガの取り扱いに戻る。
golangアプリケーションはdocker上で動作しているため、リモートデバッグという方法になるらしい。(2021/11/27の記事)
仕組みとしては、コンテナで動くdelve
に対して、DAPというデバッグ用のプロトコルで、エディターからのデバッグ命令を受けて実行する。といったアーキテクチャのようです。
vimではcliでのデバッグが前提とされていますが、プラグインを導入することで解決できるようなので、今回は対応しないことにします。
デバッガを動かせるコンテナを作る
ゼロから上記の記事に従ってコンテナを構築してみる。
上記記事の go-remote-debug → delve_sample に変えて試しにコンテナを起動してみる。
すると以下のようなエラーや他にもいろいろエラーが出た。
Build Error: go build -o /var/folders/wh/xxxx/T/__debug_binxxxxxxx -gcflags all=-N -l .
go: cannot find main module, but found .git/config in /Users/xxxxx
to create a module there, run:
cd ../.. && go mod init (exit status 1)
最終構成
最終的には、3つの手順で接続してデバッグまでできるようになった。
①右のコマンドでコンテナを起動 DEBUG=dap DEBUG_PORT=9998 docker compose up -d
②以下の構成のlaunch.jsonでデバッグ実行を試みるとvsCodeの下がオレンジになる。
(しかしデバッガは動かず、リロードすると接続が切れるので③の手順を追加)
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug API Container",
"type": "go",
"debugAdapter": "dlv-dap",
"request": "launch",
"port": 9998,
"host": "localhost",
"mode": "exec",
"program": "/dev/delve_sample/app",
"substitutePath": [
{
"from": "${workspaceFolder}",
"to": "/dev/delve_sample"
}
]
}
]
}
③下記の構成で再度接続を試みる。
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}"
}
]
}
③の手順を追加した理由
本来の想定では、手順②までで完了すると思っていたが、できたりできなかったりして、いろいろ触っているうちに③の手順を追加することで接続を再現できるようになった。
しかし、③の手順だけを②を飛ばして行ってもうまくいきませんでした。
どういった仕組みでこのようなことになっているかまではわかりませんが、もし誰かの参考になればと思います。