Visual Studio CodeによるGo言語のデバッグ
はじめに
藤本です。
最近、仕事じゃないことでGo言語を書く機会が増えています。
業務上、プログラムを触ることがそんなに多くないせいか、記憶力が弱いせいか、基本的にプログラミングはIDEがないと辛いです。
私がIDEに特に期待することは、以下となります。
- 自動補完
- デバッグ
- ジャンプ(というのかな?EclipseでCtrl + Clickで飛ぶやつ)
IntelliJ IDEAやEclipseのGo言語Pluginを試してみましたが、EclipseによるJava開発やPyCharmによるPython開発のような感動は得られず、Atomエディタで開発していました。
そんな中、Visual Studio CodeでGo言語Extensionがあり、使い易いとの噂を聞いて、早速試してみました。結果、今のところはあまり不満ありません。
Visual Studio Codeについては下記記事をご参照ください。
概要
今回はVisual Studio Codeを利用して、Goプログラムをデバッグ実行するまでの手順をご紹介します。
環境
- OS : OSX YOSEMITE (10.10.5)
- Visual Studio Code : 0.10.11
- Go : 1.6
やってみた
Visual Studio Codeのインストール手順は「Setting up Visual Studio Code」をご参照ください。
サンプルプロジェクト
環境変数GOPATH配下にプロジェクトディレクトリを作成します。
今回は以下のような構成とします。
$ tree $GOPATH /Users/fujimoto.shinji/vscode └── src └── github.com └── s-fujimoto └── project
Visual Studio Code起動
プロジェクトディレクトリへ移動し、Visual Studio Codeを起動します。
$ cd $GOPATH/src/github.com/s-fujimoto/project $ code .
Visual Studio Codeが起動しました。
Go言語Extensionのインストール
MicrosoftのGithubリポジトリで提供されているvscode-goをインストールします。vscode-goは以下の機能を提供します。
- カラー化
- 自動補完 (using gocode)
- Signature Help (using godoc)
- スニペット
- Quick Info (using godef)
- 参照を開く (using godef)(私の中のジャンプ)
- 参照検索 (using go-find-references)
- アウトライン表示 (using go-outline)
- ワークスペースシンボル検索 (using go-symbols)
- 名称変更 (using gorename)
- 保存 -> ビルド (using go build and go test)
- フォーマット (using goreturns or goimports or gofmt)
- インポートの追加 (using gopkgs)
- デバッグ [partially implemented] (using delve)
[cmd+shift+p]でコマンドパレットを開き、[Extensions: Install Extension]を実行します。
候補に出てくる[Go]をインストールします。
インストール完了後、再起動を促されますので実施します。
これだけでインストールは完了です。
各種機能
簡単にいくつかの機能をご紹介します。
カラー化
白文字だったgoファイルのソースコードがカラフルになって見やすくなっています。
自動補完
文字入力すると、候補が表示され、選択すると自動補完されます。
クイックインフォ
マウスオーバーすると、使い方が表示されます。
ジャンプ
Commandキーを押しながら、クリックするとその実装箇所へ移動します。
(キャプチャから抜けていますが、マウスカーソルが指アイコンになっています)
インポートを追加
importを書き忘れても、、、
補完してくれます。
Goの実行
[Command + n]で新規ファイルを作成します。
main.go
package main import ( "fmt" ) func main() { fmt.Println("Go!!!") }
[F5]、もしくはコマンドパレットから[Debug: Start]を実行します。
最初に実行のConfigurationを定義するlaunch.json
というJSONファイルが生成されます。
もう一度、[F5]、もしくはコマンドパレットから[Debug: Start]を実行します。
DEBUG CONSOLEに「Go!!!」と表示され、実行を確認できます。
デバッグ
ようやく、本題。Go言語のデバッグです。
デバッグにはGo言語のデバッガーであるDELVEを利用します。Visual Studio Codeが裏でDELVEを実行し、デバッグポイントで止めてくれたり、ステップ実行といった機能を提供してくれます。
DELVEを使ったデバッグをOSXで利用する場合、コードサイニング証明書を使ってビルドする必要があります。OSXの標準ユーザーではセキュリティレベルの問題で実行することができません。
コードサイニング証明証作成
OSXはKeychain Accessで自己証明書を作成できます。
Keychain Accessを起動します。
メニューの[キーチェーンアクセス] -> [証明書アシスタント] -> [証明書を作成...]を選択し、証明書作成ウィザードを起動します。
下記を設定し、[続ける]を選択します。
名前:delve(任意)
固有名のタイプ:自己署名ルート
証明書のタイプ:コード署名
デフォルトを無効化:on
有効期限は適当に伸ばしておきます。
そのままウィザードを進めます
証明書の場所のキーチェーンにシステムを指定します。
自己署名コードサイニング証明書が作成されました。
コードサイニング証明書にアクセスするたびに確認が出るのが面倒なので、証明書のアクセス権限に信頼を与えます。変な証明書を信頼しないように気をつけてください。
証明書を右クリックし、「情報を見る」を選択します。
「信頼」を展開し、この証明書を使用するときを「常に信頼」を設定します。
DELVEインストール
まずはDELVEをGithubリポジトリからダウンロードします。
$ git clone https://github.com/derekparker/delve Cloning into 'delve'... remote: Counting objects: 6420, done. remote: Compressing objects: 100% (6/6), done. remote: Total 6420 (delta 0), reused 0 (delta 0), pack-reused 6414 Receiving objects: 100% (6420/6420), 10.18 MiB | 2.42 MiB/s, done. Resolving deltas: 100% (3758/3758), done. Checking connectivity... done.
環境変数CERTに作成したコードサイニング証明書の名前を指定し、make install
を実行します。
$ cd delve $ CERT=delve make install go install -ldflags="-s -X main.Build=a20bdf4b3b884122ec665b8638c1ff337afd008d" github.com/derekparker/delve/cmd/dlv # github.com/derekparker/delve/proc clang: warning: argument unused during compilation: '-pthread' # github.com/derekparker/delve/proc clang: warning: argument unused during compilation: '-pthread' codesign -s "delve" /Users/fujimoto.shinji/vscode/bin/dlv
GOPATH/bin配下にdlvが作成されていることを確認します。
$ ls -l $GOPATH/bin/dlv -rwxr-xr-x 1 fujimoto.shinji staff 10758240 4 5 11:47 /Users/fujimoto.shinji/vscode/bin/dlv
簡単に動作確認。
$ cd $GOPATH/src/github.com/s-fujimoto/project $ $GOPATH/bin/dlv debug main.go could not launch process: could not fork/exec
Oh...forkできない。
調べたところ、Keychainの変更を有効にするためにはtaskgated
を再起動しなくてはいけないようです。
$ sudo kill `pgrep taskgated` $ $GOPATH/bin/dlv debug main.go Type 'help' for list of commands. (dlv)
実行できました。
(dlv) help The following commands are available: help (alias: h) ------------- Prints the help message. break (alias: b) ------------ break [name] <linespec> trace (alias: t) ------------ Set tracepoint, takes the same arguments as break. restart (alias: r) ---------- Restart process. continue (alias: c) --------- Run until breakpoint or program termination. step (alias: s) ------------- Single step through program. step-instruction (alias: si) Single step a single cpu instruction. next (alias: n) ------------- Step over to next source line. threads --------------------- Print out info for every traced thread. thread (alias: tr) ---------- Switch to the specified thread. clear ----------------------- Deletes breakpoint. clearall -------------------- clearall [<linespec>]. Deletes all breakpoints. If <linespec> is provided, only matching breakpoints will be deleted. goroutines ------------------ goroutines [-u (default: user location)|-r (runtime location)|-g (go statement location)] Print out info for every goroutine. goroutine ------------------- Sets current goroutine. breakpoints (alias: bp) ----- Print out info for active breakpoints. print (alias: p) ------------ Evaluate a variable. set ------------------------- Changes the value of a variable. sources --------------------- Print list of source files, optionally filtered by a regexp. funcs ----------------------- Print list of functions, optionally filtered by a regexp. types ----------------------- Print list of types, optionally filtered by a regexp. args ------------------------ Print function arguments, optionally filtered by a regexp. locals ---------------------- Print function locals, optionally filtered by a regexp. vars ------------------------ Print package variables, optionally filtered by a regexp. regs ------------------------ Print contents of CPU registers. exit (alias: quit | q) ------ Exit the debugger. list (alias: ls) ------------ list <linespec>. Show source around current point or provided linespec. stack (alias: bt) ----------- stack [<depth>] [-full]. Prints stack. frame ----------------------- Sets current stack frame (0 is the top of the stack) source ---------------------- Executes a file containing a list of delve commands disassemble (alias: disass) - Displays disassembly of specific function or address range: disassemble [-a <start> <end>] [-l <locspec>] on -------------------------- on <breakpoint name or id> <command>. Executes command when the specified breakpoint is hit (supported commands: print <expression>, stack [<depth>] [-full] and goroutine) condition (alias: cond) ----- cond <breakpoint name or id> <boolean expression>. Specifies that the breakpoint or tracepoint should break only if the boolean expression is true. (dlv) step > _rt0_amd64_darwin() /usr/local/Cellar/go/1.6/libexec/src/runtime/rt0_darwin_amd64.s:8 (PC: 0x55de0) 3: // license that can be found in the LICENSE file. 4: 5: #include "textflag.h" 6: 7: TEXT _rt0_amd64_darwin(SB),NOSPLIT,$-8 => 8: LEAQ 8(SP), SI // argv 9: MOVQ 0(SP), DI // argc 10: MOVQ $main(SB), AX 11: JMP AX 12: 13: // When linking with -shared, this symbol is called when the shared library (dlv) continue Go!!! Process 23126 has exited with status 0
うん、Step実行もできますし、実行結果も確認できます。
Visual Studio Codeからのデバッグ
Visual Studio Codeに戻りまして、動作確認します。
まずはブレイクポイントを設定します。
[F5]キーでデバッグ実行します。
デバッグポイントで止まっています。
上のパネルでContinue、Step Over、Step In、Step Out、Restart、Stopが操作できます。
左ペインに変数の中身を確認できます。
他にもWatchで変数の遷移を追いかけたり、CALL STACKで追いかけたり、Exceptionで止めたりとIDEに求めるデバッグの機能は備わっています。
感想
これこれ!こういうのを求めてました。
まだサンプルコードしか書いていないですが良さ気!
地味ですが、code .
でプロジェクトを開き、.vscode
ディレクトリ内でプロジェクト固有の設定が簡単にできるところが好きです。
これからドシドシ使ってみて良い機能があればブログでまとめてレポートします。