0
0

More than 1 year has passed since last update.

【Goのデバッガーdelveを使えるようにするまでの苦労・プロセス】

Posted at

デバッガを扱う前に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}"
        }
    ]
}

③の手順を追加した理由

本来の想定では、手順②までで完了すると思っていたが、できたりできなかったりして、いろいろ触っているうちに③の手順を追加することで接続を再現できるようになった。
しかし、③の手順だけを②を飛ばして行ってもうまくいきませんでした。
どういった仕組みでこのようなことになっているかまではわかりませんが、もし誰かの参考になればと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0