Go言語の開発環境を作成して簡単なスクリプトを書いてみました。
過去2回ほどGo言語にチャレンジして挫折したので3回目のチャレンジになります。

Table of Contents

はじめに

以前に以下の記事でGo言語をCLIツール作成言語の選択肢から外した経緯があります。

そう..あまりにも言語に面白みがなく泥臭かったためRustを選んだのです。
しかし、そんなGo言語を見る目が変わる出来事がありました。

vim-goとの出会いです。
Go言語を書くためにVimを使うのではなく、Vimで開発するためにGoを使うのです!

Vimの話は開発環境構築のセクションで後ほど紹介します。

インストール

まずはGo言語をインストールします。
公式サイトからバイナリがダウンロードできます。

Ansibleを使っている場合は以下のようにplaybookを作成します。

- name: Download golang
  get_url:
    url: https://storage.googleapis.com/golang/go{{ version }}.linux-amd64.tar.gz
    dest: /tmp/go.tar-{{ version }}.gz

- name: Extract go.tar.gz
  unarchive:
    src: /tmp/go.tar-{{ version }}.gz
    dest: /usr/local

versionは1.10.3にしました。

なぜ最新版の1.11を使わないのか?
リリース直後のせいかvim-goが上手く動作しなかったためです。
1.11から追加されたGo modulesの機能に対するIssueが作成されていますが実現は厳しいかもしれません…

環境変数の設定

上記に記載していませんが別途$GOPATH$PATHを設定する必要があります。
fishの場合はconfig.fishに記載しておきます。

set -x GOPATH "$HOME/.go"
export PATH= "$PATH:/usr/local/go/bin:$GOPATH/bin"

動作確認

バージョンが表示されれば問題ありません。

$ go version
go version go1.10.3 linux/amd64

開発環境構築

Vimをベースとして開発環境の準備をします。
以下のプラグインをそれぞれインストールします。

なぜVimを使うのか

いくつか理由がありますが、半分くらいは好みの問題になります。

  • 起動が速い
  • Vimmerであれば操作も速くテンションが上がる
  • Go言語は使用がシンプルなのでIDEを使うメリットが多言語ほど大きくない

vim-go

VimでGo言語を開発するためのプラグインです。
読むだけならvim-goだけで十分だと思います。

dein.tomlの設定です。
Go言語の場合はインデントがタブであるため、setl nolistでタブが目立たないようにしています。

[[plugins]]
# golang
repo = 'fatih/vim-go'
on_ft = ['go']
hook_add = '''
autocmd FileType go setl nolist

dein_lazy.tomlに記載した場合はmain.goがテンプレートから作成されませんでした。

ツールのインストール

vim-goインストール後にVimを開き、:GoUpdateBinariesを実行してツールをインストールします。
ツールには例えば以下の様なものがあります。

  • guru (静的解析)
  • golint (構文解析)
  • dlv (デバッガ)

これらがインストールされていないとvim-goの機能をフル活用することができません。

UltiSnips

開発速度を爆速にするためのスニペットを利用できるプラグインです。

以前はNeosnippetを使っていましたがスターの数が多かったので乗り換えてみました。
Deopleteとの連携を考えるとNeosnippetの方が良かったかもしれません..

dein.tomlの設定は以下です。

[[plugins]]
repo = 'SirVer/ultisnips'
hook_add = '''
let g:UltiSnipsSnippetDirectories=[$HOME.'/.vim-snippets/UltiSnips', 'UltiSnips']

" snippet 次へ
let g:UltiSnipsJumpForwardTrigger="<tab>"
" snippet 前へ
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"
'''

[[plugins]]
repo = 'honza/vim-snippets'

Deoplete

最後は補完候補を助けるプラグインです。
Vimの標準補完に慣れていると戸惑うかもしれませんが、とても賢い補完をしてくれます。

dein.tomlの設定は以下です。
Deopleteは2つのプラグインを依存関係に持つため計3つをインストールする必要があります。

[[plugins]]
repo = 'roxma/nvim-yarp'

[[plugins]]
repo = 'roxma/vim-hug-neovim-rpc'

[[plugins]]
repo = 'Shougo/deoplete.nvim'
depends = ['nvim-yarp', 'vim-hug-neovim-rpc']
hook_add = '''
let g:python3_host_prog = '/usr/bin/python3'
let g:deoplete#enable_at_startup = 0
let g:deoplete#auto_complete_delay = 0

nnoremap <Space>a :call deoplete#enable()<CR>
'''

<Space>aを押さないとDeopleteは有効にならないようにしています。
これにはパフォーマンス上の理由があります。

はじめは起動時に有効になるようdeoplete#enable_at_startup = 1を設定していました。
しかし、起動時に0.5~1秒ほどラグを感じるため設定を解除しました。

次に挿入モードに入った時、初めて文字を入力した時に有効になるよう設定してみました。
これも引っかかりのような違和感を感じたため解除しています。

Hello World

構築した開発環境でHello Worldを出力するプログラムを書いてみました。

記載から実行までわずか10秒程度です。
main.goを作成するとvim-goが自動でテンプレをベースにしてくれます。
こういうところにGoとVimの哲学を感じますね 😄

ターミナルから実行する場合はgo runを使います。

$ go run main.go
Hello World

コマンドライン引数

最後は標準モジュールでコマンド引数を処理する方法を紹介します。

var value = flag.型(フラグ名, デフォルト値, 説明)と書いてParseをするだけです。

package main

import (
	"flag"
	"fmt"
)

func main() {
	var id = flag.Int("id", 777, "Your ID")
	var name = flag.String("name", "hoge", "Your Name")

	flag.Parse()

	fmt.Printf("%d: %s\n", *id, *name)
}

使用するときに*を付けるのが気持ち悪い場合は以下のように書くこともできます。
変数の宣言とflagの適応を別にしなければいけないので一長一短だとは思います。

package main

import (
	"flag"
	"fmt"
)

func main() {
	var (
		id   int
		name string
	)

	flag.IntVar(&id, "id", 777, "Your ID")
	flag.StringVar(&name, "name", "hoge", "Your Name")

	flag.Parse()

	fmt.Printf("%d: %s\n", id, name)
}

Vimからは以下の様に実行することができます。

:GoRun % --id 7 --name yuta

コマンドプロンプトだと以下の様になります。どれでもOK。

$ go run main.go --id 7 --name yuta
7: yuta
$ go run main.go -id 7 -name yuta
7: yuta
$ go run main.go -id=7 -name=yuta
7: yuta

--helpでUsageを表示することができます。

$ go run main.go --help                                                                                                 194ms  Tue 28 Aug 201
Usage of /tmp/go-build669378413/b001/exe/main:
  -id int
        Your ID (default 777)
  -name string
        Your Name (default "hoge")
exit status 2

総括

Go言語の開発環境を作成して簡単なスクリプトを書いてみました。

次はもう少し本格的なもの..GitHubにアクセスして情報を取得するCLIを作ってみようと思います。