emahiro/b.log

日々の勉強の記録とか育児の記録とか。

VSCode で delve を使った Debugger の環境を整える

Overview

Go + Delve の利用環境を VSCode について記載します。

動機

普段の開発ではずっと古き良き? print debug を使って動作確認を行ってきていました。 もちろん手元の開発だけでなく remote での動作確認等では今でもこれよりシンプルで一般的な手法はないので、今でもバリバリ現役で使っているのですが、こと手元(local) 環境の開発に限ってはもうちょっとイマドキっぽいデバック環境を整えようかなと思って Go + delve の開発環境を Go で用意しました。

設定方法

多くのエントリで書かれてるとおりですが手順は以下のとおりです。

  1. VSCode で Go の拡張をいれる。
  2. VSCode でプロジェクトを開く: VSCode で Go 言語のプロジェクトを開く。
  3. デバッグ設定ファイルを開き .vscode ディレクトリ内の launch.json ファイルを開く。もし launch.json ファイルが存在しない場合は、デバッグサイドバーから「デバッグの構成を開く」(歯車アイコン) をクリックし、Go を選択して新しい launch.json ファイルを作成する。
  4. 環境変数を設定する: launch.json ファイルに env フィールドを追加し、そこに環境変数をキーと値のペアで設定する。
  5. BreakPoint を仕込む。
  6. TestXXX メソッドで debug test でデバッカーを起動する。

以下のように debugger が起動します。

例えば、特定の API エンドポイントや認証トークンなど、デバッグセッション中に必要な環境変数がある場合、以下のように追加します (*)

※ 後述しますがこの方法だとうまく環境変数が反映されていませんでした。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "go",
            "request": "launch",
            "program": "${fileDirname}",
            "env": {
                "API_ENDPOINT": "https://example.com/api",
                "AUTH_TOKEN": "your_auth_token_here"
            }
        }
    ]
}

設定方法の中で request に launch と attach がありますが、公式には以下のように説明されています。

In VS Code, there are two core debugging modes, Launch and Attach, which handle two different workflows and segments of developers. Depending on your workflow, it can be confusing to know what type of configuration is appropriate for your project.
If you come from a browser Developer Tools background, you might not be used to "launching from your tool," since your browser instance is already open. When you open DevTools, you are simply attaching DevTools to your open browser tab. On the other hand, if you come from a server or desktop background, it's quite normal to have your editor launch your process for you, and your editor automatically attaches its debugger to the newly launched process.
The best way to explain the difference between launch and attach is to think of a launch configuration as a recipe for how to start your app in debug mode before VS Code attaches to it, while an attach configuration is a recipe for how to connect VS Code's debugger to an app or process that's already running.
VS Code debuggers typically support launching a program in debug mode or attaching to an already running program in debug mode. Depending on the request (attach or launch), different attributes are required, and VS Code's launch.json validation and suggestions should help with that.

ref: https://code.visualstudio.com/Docs/editor/debugging#_launch-versus-attach-configurations

debugger を動かすだけであればどちらでも問題なかったです。attach にするとすでに動いてるプロセスに debugger をアタッチして delve を動かせます。attach だと環境変数を設定できないなど、若干の使える設定が異なります。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Package",
      "type": "go",
      "request": "launch",
      "mode": "auto",
      "program": "${fileDirname}",
      "env": {
        "ENV_VAR": "test"
      }
    },
    {
      "name": "Attach to Process",
      "type": "go",
      "request": "attach", // env の設定を使えない。
      "mode": "local",
      "processId": 0
    }
  ]
}

その他各種設定の項目は以下の公式のドキュメントを参照します。env くらいしか使うものないですが、env が多い場合には envFile を load できたり便利です。

code.visualstudio.com

ハマってるところ

launch.json で設定した環境変数が反映されない or 上書きされてしまう

これは自分の動かしていた環境に依存するかもしれませんが、以下のように、環境変数をあらかじめ env で設定した上で debugger を起動しても環境変数を Go のプロセスから取り出せませんでした。
今はこの env で設定した環境変数がどうして反映されないのか?ということはまた調べます。

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Package",
      "type": "go",
      "request": "launch",
      "mode": "auto",
      "program": "${fileDirname}",
      "env": {
        "ENV_VAR": "test"
      }
    }
  ]
}

Go のコードは以下

// main.go
func DoSomething() {
    v := os.Getenv("ENV_VAR") //  v = "" になってしまう。
    fmt.Println(v)
}


// main_test.go
func TestDoSomething(t *testing.T) {
    DoSomething()
}

追記

環境変数が登録できた

gopls の設定で以下の設定を追加すると環境変数が反映されました。

{
  "go.testEnvVars": {
    "ENV_VAR": "value"
  }
}

user 設定の setting.json にこれを追加してもいいですが、私は workspace の setting.json に追記しました。そのほうが取り回しやすいので。

公式のドキュメントには優先順位には Merged with env and go.toolsEnvVars with precedence env > envFile > go.toolsEnvVars. と書いてあるけど、やってみると env と envFile は反映されず、gopls が優先されていました。

Absolute path to a file containing environment variable definitions, formatted as string key=value pairs. Multiple files can be specified by provided an array of absolute paths. Merged with env and go.toolsEnvVars with precedence env > envFile > go.toolsEnvVars.

ref: https://github.com/golang/vscode-go/wiki/debugging#configuration