Golang開発環境を作成する(module対応) - Ubuntu16.04/VSCode

はじめに
===
自分用メモです。

以下、今回記録を残そうと思った経緯を箇条書きで記載します。

1. 2018/8 頃 go1.11 がリリースされた
2. modules という機能が追加されたため、早速試した
3. 便利だとは思ったが、Visual Studio Codeの補完機能が非常に遅く(1-3秒くらいかかる)使いづらい
4. 時間もないし、自分の環境だし、原因調査するのも面倒だったため`GO111MODULE=off`でしばらく乗り切ることに
5. 最近(2019/5)になって時間も増えたため、補完機能がなぜ遅いのか原因調査開始
6. Visual Studio Code の [Wiki](https://github.com/microsoft/vscode-go/wiki/Go-modules-support-in-Visual-Studio-Code) に理由らしいことが書いてあった
   > Why is code navigation and code completion slow when using Go modules?  
   > Go moduleを使用すると、コードナビゲーションとコード補完が遅くなるのはなぜですか?
   >
   > This is mostly due to the limitation of the tools that power these features which are godef and gocode respectively. The Go tools team at Google are working on improving them and also working on a language server which will be the long term solution for all language features.  
   > これは主に、それぞれgodefとgocodeであるこれらの機能を動かすツールの制限によるものです。 GoogleのGoツールチームはそれらを改善することに取り組んでいます、そしてまたすべての言語機能のための長期的な解決策になるであろう言語サーバー取り組んでいます。

7. gocode, godef は modules 対応中ってことかな?それとももう使われなくて、代わりに言語サーバを使えということかな?
8. Visual Studio CodeのWikiを眺めていると、gopls という名前の言語サーバについて何か言っている
   > To get Go module support in VS Code, ensure that you have the latest Go extension and use the new language server gopls from Google by adding the below in your settings  
   > VS CodeでGoモジュールをサポートするには、最新のGo拡張機能があることを確認し、設定に以下を追加してGoogleの新しい言語サーバーのgoplsを使用してください。
9. やはり言語サーバの gopls を使えということかな? gocode, godef はどうなったんだろうか?と調べていると、下記記事を発見(とても素晴らしい記事でした)。  
[gocode やめます(そして Language Server へ)](https://mattn.kaoriya.net/software/lang/go/20181217000056.htm)
10. なるほど。理解できた。どうやら gocode, godef ではなく、言語サーバを使用する、という流れに変わったらしい
11. bingo という言語サーバもあるらしいので、githubのページを見たところ、どうやら gopls に一本化?したっぽい
    > I am very sorry that I have planned not continue to maintain this project.  
    > このプロジェクトを維持し続けないことを計画していたことを非常に残念に思います。
    >
    > According to the issue #13 collaborating on golsp, I hope that we will eventually have a unified language server: gopls.  
    > golspで共同作業している問題＃13によると、私たちは結局統一された言語サーバーを持つことを願っています：gopls。
    >
    > It is Google's upcoming Go language server. It is in the best interests of the community to only have a single language server.  
    > それはGoogleの次期Go言語サーバーです。単一の言語サーバーのみを持つことは、コミュニティにとって最も利益のあることです。
    > 
    > I have ported some features such as references, rename, workspace symbol, implementation of bingo to gopls.  
    > 参照、名前の変更、ワークスペースのシンボル、bingoの実装などの機能を移植しました。
    > 
    > If you want to use the enhanced version of gopls, try https://github.com/saibing/tools.  
    > 拡張バージョンのgoplsを使用したい場合は、https：//github.com/saibing/toolsを試してください。

一足遅れて状況を理解出来た。忘れそうなので、Go言語の開発環境構築用メモとして、記録を残します。

システム環境
===

* OS - Ubuntu16.04
* Goコンパイラ - go1.12.5
* エディタ - Visual Studio Code(VSCode) 1.33.1
* VSCodeプラグイン - Go 0.10.2
* 実施日 2019/5/14

goコンパイラのインストール
===
`apt`からインストールすると古いバージョンがインストールされてしまうため、公式からインストール。

* [The Go Programming Language](https://golang.org)

インストール先は、`/home/user/.go` ディレクトリ配下にインストールする。

```bash
# goインストール先ディレクトリを作成
[user@go:~]$ mkdir $HOME/.go && cd $HOME/.go && pwd
/home/user/.go

# go1.12.5 をダウンロード(プロキシサーバを経由している人は、https_proxy設定をお忘れなく)
[user@go:go]$ curl -OL https://dl.google.com/go/go1.12.5.linux-amd64.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  122M  100  122M    0     0  2584k      0  0:00:48  0:00:48 --:--:-- 3333k

# go1.12.5 を解凍
[user@go:go]$ tar xvf go1.12.5.linux-amd64.tar.gz
...
[user@go:go]$ rm go1.12.5.linux-amd64.tar.gz
[user@go:go]$ ls
go

# go install/get 時にライブラリやツールが格納されるディレクトリを作成
[user@go:go]$ mkdir vendor
```

## 環境変数の設定
`$HOME/.profile`、または`$HOME/.bashrc`に下記環境変数を追加。

```bash
export GOPATH=$HOME/.go/vendor # GOPATH を設定
export PATH=$HOME/.go/go/bin:$GOPATH/bin:$PATH # go コンパイラのパスを通す
export GO111MODULE=on # go1.13 からはデフォルト on になるそうなので、onにしてしまう
```

ターミナルを立ち上げ直し、goコンパイラが見つかるか確認。

```bash
# .profile を修正した場合は、 `source ~/.profile` が必要
[user@go:go]$ which go
/home/user/.go/go/bin/go
[user@go:go]$ go version
go version go1.12.5 linux/amd64
```
OK!

Visual Studio Code のインストール
===
Visual Studio Codeは公式からインストール。OSがUbuntuなので.debパッケージを選択。

* [Visual Studio Code - Code Editing. Redefined](https://code.visualstudio.com/)
![vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257465/d6ecca04-7d44-014f-01ef-dd748de5c9f0.png)


## VSCodeプラグイン - Goのインストール

1. Visual Studio Code起動
2. `Ctrl` + `Shift` + `X` で拡張機能画面を開く
3. 「Marketplaceで拡張機能を検索する」欄に「Go」と入力

Golangに関連するプラグインが複数表示されるので、下記プラグインを選択しインストールボタンを押下する。
![golang-vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257465/28b08db5-0d0c-0344-1ba2-f884f1d55343.png)

数秒でインストールは完了する。

### Goプラグインの設定
Goプラグインの設定は、Visual Studio Codeの設定画面(GUI)では設定出来ない項目があるため、直接settings.jsonを編集する。

1. `Ctrl` + `,` で設定ファイル画面を開く
2. 「ユーザ設定」をクリック
3. 右上の **`{}`** (設定(JSON)を開く)をクリックし、settings.jsonを開く

![config.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257465/426e0a2f-a667-69c4-659e-d9fec184f8f8.png)

settings.json は、下記サイトを参考に修正。

* https://github.com/saibing/tools

```json
{
    "go.useLanguageServer": true,
    "go.alternateTools": {
        "go-langserver": "gopls"
    },
    "go.languageServerExperimentalFeatures": {
        "format": true,
        "autoComplete": true,
        "rename": true,
        "goToDefinition": true,
        "hover": true,
        "signatureHelp": true,
        "goToTypeDefinition": true,
        "goToImplementation": true,
        "documentSymbols": true,
        "workspaceSymbols": true,
        "findReferences": true,
        "diagnostics": true
    },
    "[go]": {
        "editor.snippetSuggestions": "none",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        },
    },
    "gopls": {
        "usePlaceholders": false,
        "enhancedHover": false
    }
}
```

### Goプラグインに必要な各種ツールをインストール

1. `Ctrl` + `Shift` + `P` でコマンドパレットを開く
2. 「> Go: Install/Update Tools」を入力する
3. Goプラグインに必要なツールをダウンロードする画面が表示される
4. すべてチェックして「OK」ボタンを押下する
5. gocode, godef は使わないかもしれないが、一応チェック入れておく

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257465/9aa9a061-d726-45c5-d759-b039cd7d3d5f.png)

押下後、インストールが始まり、Visual Studio Codeのターミナルにインストール状況が出力がされる。

※インストール先は、$GOPATH配下にインストールされます。

```
Installing 18 tools at /home/user/.go/vendor/bin
  gocode
  gopkgs
  go-outline
  go-symbols
  guru
  gorename
  dlv
  gocode-gomod
  godef
  goreturns
  golint
  gopls
  gotests
  gomodifytags
  impl
  fillstruct
  goplay
  godoctor

Installing github.com/mdempsky/gocode SUCCEEDED
Installing github.com/uudashr/gopkgs/cmd/gopkgs SUCCEEDED
Installing github.com/ramya-rao-a/go-outline SUCCEEDED
Installing github.com/acroca/go-symbols SUCCEEDED
Installing golang.org/x/tools/cmd/guru SUCCEEDED
Installing golang.org/x/tools/cmd/gorename SUCCEEDED
Installing github.com/go-delve/delve/cmd/dlv SUCCEEDED
Installing github.com/stamblerre/gocode SUCCEEDED
Installing github.com/rogpeppe/godef SUCCEEDED
Installing github.com/sqs/goreturns SUCCEEDED
Installing golang.org/x/lint/golint SUCCEEDED
Installing golang.org/x/tools/cmd/gopls SUCCEEDED
Installing github.com/cweill/gotests/... SUCCEEDED
Installing github.com/fatih/gomodifytags SUCCEEDED
Installing github.com/josharian/impl SUCCEEDED
Installing github.com/davidrjenni/reftools/cmd/fillstruct SUCCEEDED
Installing github.com/haya14busa/goplay/cmd/goplay SUCCEEDED
Installing github.com/godoctor/godoctor SUCCEEDED

Reload VS Code window to use the Go language server
All tools successfully installed. You're ready to Go :).
```

gopls に関しては、https://github.com/saibing/tools の手順に沿って git コマンドで入れなおす。

```
[user@go:~]$ git clone -b bingo https://github.com/saibing/tools.git
[user@go:~]$ cd tools/cmd/gopls
[user@go:gopls]$ go install
```

Visual Studio Code を再起動する。

補完機能の動作テスト
===
下記の構成で、go.mod, ソースコードを用意する。

```
project
  +-- go.mod
  `-- app
        `-- main.go
```

go.mod の内容は下記のとおり。

```go.mod
module app

go 1.12.5 // ココ重要! 記載漏れがあるとうまく動作しない
```

app/main.go ファイルを作成し、Sample関数を作成する。Sample関数内で、`fmt.`までうち、関数候補が出力された場合設定は無事成功である。
![app1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257465/03042dd2-1d41-db9c-af82-2c96d2ae7d57.png)
今回は、`Println`を選択。`Println`を選択すると `import` に `fmt` が自動で追加されるはずである。
![app2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257465/f2135968-f78a-6799-5267-dfa63a24933f.png)

---

ちゃんと設定できたかな。補完も早いし、今の所問題なさそう。