My External Storage

May 30, 2018 - 5 minute read - Comments - go vim

[Go]vim-goとDelveでVim上からGoのデバッグを行う #vim #golang

VimでGoを使う人は大半の人がvim-goプラグインをインストールしているだろう。

fatih/vim-go
https://github.com/fatih/vim-go

今年の3月、ついにvim-godelveをサポートした(他のVimプラグインを使えばすでにVimから使えたようだが)。
VimからGoのプログラムをデバッグする方法をまとめる。

https://github.com/fatih/vim-go/blob/master/CHANGELOG.md#117---march-27-2018

1.17 - (March 27, 2018)
FEATURES:
Debugger support! Add integrated support for the delve debugger. Use :GoInstallBinaries to install dlv, and see :help go-debug to get started. [GH-1390]

なお、vim-goはチュートリアルを読めば大半の機能を理解することが出来るが、最近追加された機能まではチュートリアルに載っていない。

fatih/vim-go-tutorial
https://github.com/fatih/vim-go-tutorial

@hnakamur2さんが日本語翻訳版も公開してくれている。

hnakamur/vim-go-tutorial-ja
https://github.com/hnakamur/vim-go-tutorial-ja

TL;DR

  • vim-goのデバッグ機能をヘルプからまとめた

ほぼヘルプのコマンドを動かした通りなので、英語に抵抗がないならば、Vimを開いて:h go-debugとすれば良い。
見つからない場合はvim-goが古い状態になっている。

https://github.com/fatih/vim-go/blob/7ac1e62fa30d84946e93a3820bb6cf6a431186ed/doc/vim-go.txt#L1872

なお、今回基本的なデバッグ用語(ブレークポイント、ステップインなど)の説明は省略する。
以下のgif動画は以下の操作を行った際の画面を記録したものである。

  • Vimを起動
  • デバッグモードを開始
  • ブレークポイントを設置
  • コンテニューでデバッグを開始
  • スタックを確認
  • ローカル変数配列を展開
  • 実行中の変数の中身をデバッグプリント
  • デバッグモードを終了

vim-debug-demo

事前準備

まずは最新版のvim-goに更新しておく。vim-godelve周りに5月に一度更新が入っているので最新版を取得しておいたほうがよい。
dein.vimでpluginをアップデートするときはvimを起動して以下のコマンドを実行する。

1
:call dein#update()

:h go-debugと入力してDEBUGGERのヘルプが表示されたならばvim-goでデバッグが出来るようになっている。

delveが動くことも確認しておこう。ターミナルで一通り動くことを確認しておいたほうが良い。
自分の場合、Macで使うとdelveの起動は出来てもデバッグの開始に失敗することがあった。

Vim上でのデバッグ

今回のデバッグ対象のサンプルとして次のコードを利用した。

https://github.com/budougumi0617/gopl/blob/master/ch01/ex02/echo.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import (
	"fmt"
	"io"
	"os"
	"strconv"
)

var out io.Writer = os.Stdout // modified during testing

func main() {
	for index, arg := range os.Args {
		s := "[" + strconv.Itoa(index) + "] " + arg // Convert integert to string
		fmt.Fprintln(out, s)
	}
}

ローカルにある上記のコードをリポジトリルート上をカレントディレクトリとしてvimで開いた。

1
2
$ cd $GOPATH/src/github.com/budougumi0617/gopl/
$ vim ch01/ex02/echo.go

:GoDebugStart デバッグを開始する

まず、デバッグモードの起動の仕方だ。 デバッグを開始するときは以下のように:GoDebugStartを実行する。(testをデバッグする場合は:GoDebugTest)

:GoDebugStart [pkg] [program-args]

たとえば、今回の例の場合はデバッグ対象のパッケージがカレントディレクトリではないので、以下のようになる。

:GoDebugStart ./ch01/ex02 test test2

デバッグ実行時にプログラムへ引数やフラグを渡すときはパッケージ名のあとに指定する。
ブレークポイントを指定していた場合、そこでプログラムが止まった状態でデバッグモードに移行しているはずだ。

GoDebugStart また、もしここでデバッグモードの起動に失敗する場合、:messagesを実行することで起動時のログを確認することができる。

:GoDebugBreakpoint | ブレークポイントを設定する

次に、ブレークポイントを設定する。なお、ブレークポイントの設置はデバッグモードに入る前に実施することも出来る。 ブレークポイントを設定したい行の上にカーソルを移動して:GoDebugBreakpointを実行するか、 ブレークポイントを設定したLINE_NUM行目を引数にして:GoDebugBreakpoint $LINE_NUMと実行する。 成功すると、左端に>とマーキングがされる。 ブレークポイントを解除したい場合はやはりカーソルを該当行に置くか、引数で指定して:GoDebugBreakpointを実行する。

デバッガで挙動を確認する

デバッグモード起動後は一般的なデバッグのようにステップ実行することが出来る。それぞれのコマンドにはデフォルトでキーバインドも設定されている。

コマンド キーバインド 説明
:GoDebugContinue F5 ブレークポイントまでプログラムを実行する
:GoDebugNext F10 ステップオーバー実行。プログラム未開始時は:GoDebugContinue相当
:GoDebugStep F11 ステップイン実行。プログラム未開始時は:GoDebugContinue相当
:GoDebugStepOut なし ステップアウト実行
:GoDebugSet なし delveがサポートしている一部のプリミティブ型に値をセットできる
:GoDebugPrint F6 引数に指定された変数もしくはカーソル下の変数の値を確認できる

デバッグ中は右下のウインドウでログや出力情報を確認することができる。

GoDebugPrint

変数の情報を確認する

左下のウインドウに変数情報が表示されている。配列情報はその変数にカーソルを合わせてエンターを押下すれば情報を展開することも出来る。

スタック情報を確認する

左のウインドウはスタック情報であり、変数名と同様に、確認したいスタック名でエンターをクリックすれば、呼び出し元の情報を確認することも可能。

:GoDebugRestart | デバッグを再開始する

ブレークポイントなどを不用意に通過してしまった場合はリスタートすることもできる。

:GoDebugStop | デバッグを終了する

デバッグを終了する場合は:GoDebugStopを実行する。 デバッグ用のウインドウやブレークポイント情報がすべて取り除かれ、通常表示のVimに戻るはずだ。

終わりに

以上でVim-godelveでデバッグする方法をまとめた。 UIに関してはdelveをそのまま使うより、圧倒的にvim-goのほうがリッチだった気がする。 ますますVimでGoを書くのが楽しくなった。

関連