﻿# 如何在 Windows 平台打造完美的 Go 開發環境 (WSL 2)

自從 Windows 升級到 Windows 10 Version 2004 之後，因為可以採用效能大幅提昇的 WSL 2 執行環境，像是 [.NET Core](https://dot.net/), [Go](https://golang.org/) 與 [Docker](https://docs.docker.com/engine/install/ubuntu/) 都會全部跑在 WSL 2 的 Linux 下。今天這篇文章，我將介紹如何在 Windows 平台打造完美的 Go 開發環境，不但可以讓你享受 Linux 平台執行時無比的順暢，更能享受 Windows 平台絕佳的 VSCode 開發體驗。

### 安裝 Go 版本管理器 (Go Version Manager)

[Go Version Manager](https://github.com/moovweb/gvm) 簡稱 `gvm`，專門用來管理 Go 的執行環境，可以讓你任意切換 Go 的 Runtime 版本，又不會搞亂你的作業系統，這可說是兩全其美！

以下兩行命令，就可以輕鬆裝好 gvm 工具：

```bash
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
source ~/.gvm/scripts/gvm
```

我之前有在 Go 的社群發起過一次問卷調查，調查後發現，有在使用 gvm 的人非常少，大家都不太有「多版本」的需求。主要原因在於，自從 Go 開始支援 Go Module 之後，已經很少有版本升級的問題，例如你要將 Go 1.13 升級到 Go 1.14 就不會太困難，就算有困難，也不會困難到需要同時使用多個 Go 版本。

另一方面來說，[安裝 Go 執行環境](https://golang.org/doc/install)的門檻已經變的超低，尤其是安裝在 Linux / macOS 底下更是如此，官方已經移除了對各家 Linux Distro 的安裝套件支援，一份 tarball 解壓縮，環境變數 `PATH` 設定好就可以立刻開始使用，沒那麼多奇奇怪怪的套件管理器混淆 Linux 初學者的地方。

不過，我認為安裝 gvm 對於打造 Go 開發環境來說，還是有好處的。至少安裝完成後的 Go 執行環境非常乾淨，各種複雜的 `GO____` 環境變數，全部交由 gvm 來管理。不想要 Go 或 gvm 的時候，只要以下兩行就可以清除乾淨：

```bash
chmod u+w -R ~/.gvm/
gvm implode
```

### 安裝 Go 執行環境

1.  先安裝 gvm 所需的必要套件
    
    因為 gvm 可能會用到建置下個版本的 Go 執行環境，所以建議你安裝一些建置工具。
    
    如果你採用 Ubuntu/Debian 系統，請安裝以下套件：
    
    ```bash
    sudo apt-get install binutils bison gcc make build-essential -y
    ```
    
    > 如果有遇到不能執行上述安裝的情況，請用以下命令修復，修復後再重新安裝一次即可！
    > 
    > ```bash
    > sudo sed -i -r -e 's/^(set -e)$/#\1/' /var/lib/dpkg/info/libc6\:amd64.postinst
    > sudo apt --fix-broken install -y
    > ```
    
    如果你採用 RedHat/CentOS 系統，請安裝以下套件：
    
    ```bash
    sudo yum install curl
    sudo yum install git
    sudo yum install make
    sudo yum install bison
    sudo yum install gcc
    sudo yum install glibc-devel
    ```
    
2.  列出目前 gvm 已安裝的所有 Go 版本
    
    ```bash
    gvm listall
    ```
    
    撰文當下的回應內容如下：
    
    ```log
    gvm gos (available)
    
      go1
      go1.0.1
      go1.0.2
      go1.0.3
      go1.1
      go1.1rc2
      go1.1rc3
      go1.1.1
      go1.1.2
      go1.2
      go1.2rc2
      go1.2rc3
      go1.2rc4
      go1.2rc5
      go1.2.1
      go1.2.2
      go1.3
      go1.3beta1
      go1.3beta2
      go1.3rc1
      go1.3rc2
      go1.3.1
      go1.3.2
      go1.3.3
      go1.4
      go1.4beta1
      go1.4rc1
      go1.4rc2
      go1.4.1
      go1.4.2
      go1.4.3
      go1.5
      go1.5beta1
      go1.5beta2
      go1.5beta3
      go1.5rc1
      go1.5.1
      go1.5.2
      go1.5.3
      go1.5.4
      go1.6
      go1.6beta1
      go1.6beta2
      go1.6rc1
      go1.6rc2
      go1.6.1
      go1.6.2
      go1.6.3
      go1.6.4
      go1.7
      go1.7beta1
      go1.7beta2
      go1.7rc1
      go1.7rc2
      go1.7rc3
      go1.7rc4
      go1.7rc5
      go1.7rc6
      go1.7.1
      go1.7.2
      go1.7.3
      go1.7.4
      go1.7.5
      go1.7.6
      go1.8
      go1.8beta1
      go1.8beta2
      go1.8rc1
      go1.8rc2
      go1.8rc3
      go1.8.1
      go1.8.2
      go1.8.3
      go1.8.4
      go1.8.5
      go1.8.5rc4
      go1.8.5rc5
      go1.8.6
      go1.8.7
      go1.9
      go1.9beta1
      go1.9beta2
      go1.9rc1
      go1.9rc2
      go1.9.1
      go1.9.2
      go1.9.3
      go1.9.4
      go1.9.5
      go1.9.6
      go1.9.7
      go1.10
      go1.10beta1
      go1.10beta2
      go1.10rc1
      go1.10rc2
      go1.10.1
      go1.10.2
      go1.10.3
      go1.10.4
      go1.10.5
      go1.10.6
      go1.10.7
      go1.10.8
      go1.11
      go1.11beta1
      go1.11beta2
      go1.11beta3
      go1.11rc1
      go1.11rc2
      go1.11.1
      go1.11.2
      go1.11.3
      go1.11.4
      go1.11.5
      go1.11.6
      go1.11.7
      go1.11.8
      go1.11.9
      go1.11.10
      go1.11.11
      go1.11.12
      go1.11.13
      go1.12
      go1.12beta1
      go1.12beta2
      go1.12rc1
      go1.12.1
      go1.12.2
      go1.12.3
      go1.12.4
      go1.12.5
      go1.12.6
      go1.12.7
      go1.12.8
      go1.12.9
      go1.12.10
      go1.12.11
      go1.12.12
      go1.12.13
      go1.12.14
      go1.12.15
      go1.12.16
      go1.12.17
      go1.13
      go1.13beta1
      go1.13rc1
      go1.13rc2
      go1.13.1
      go1.13.2
      go1.13.3
      go1.13.4
      go1.13.5
      go1.13.6
      go1.13.7
      go1.13.8
      go1.13.9
      go1.13.10
      go1.13.11
      go1.13.12
      go1.13.13
      go1.13.14
      go1.14
      go1.14beta1
      go1.14rc1
      go1.14.1
      go1.14.2
      go1.14.3
      go1.14.4
      go1.14.5
      go1.14.6
      go1.15beta1
      release.r56
      release.r57
      release.r58
      release.r59
      release.r60
      release.r57.1
      release.r57.2
      release.r58.1
      release.r58.2
      release.r60.1
      release.r60.2
      release.r60.3
    ```
    
3.  安裝 `go1.14.6` 版本
    
    ```bash
    gvm install go1.14.6 --binary
    ```
    
4.  列出目前 gvm 已安裝的所有 Go 版本
    
    ```bash
    gvm list
    ```
    
5.  設定目前要用的 Go 版本（並設定為預設版本）
    
    ```bash
    gvm use go1.14.6 --default
    ```
    
6.  確認目前執行的 Go 版本
    
    ```bash
    go version
    ```
    

### 安裝 VSCode 需要的 go modules 與相關工具

-   若要從 VSCode 自動開啟網頁，就必須安裝 [xdg-utils](https://www.freedesktop.org/wiki/Software/xdg-utils/) 套件
    
    ```bash
    sudo apt install xdg-utils -y
    ```
    
-   以下是 [Go 擴充套件](https://marketplace.visualstudio.com/items?itemName=golang.Go) 需要的 go modules
    
    ```bash
    go get github.com/sqs/goreturns
    go get github.com/mdempsky/gocode
    go get github.com/uudashr/gopkgs/v2/cmd/gopkgs
    go get github.com/ramya-rao-a/go-outline
    go get github.com/acroca/go-symbols
    go get golang.org/x/tools/cmd/guru
    go get golang.org/x/tools/cmd/gorename
    go get github.com/cweill/gotests/...
    go get github.com/fatih/gomodifytags
    go get github.com/josharian/impl
    go get github.com/davidrjenni/reftools/cmd/fillstruct
    go get github.com/haya14busa/goplay/cmd/goplay
    go get github.com/godoctor/godoctor
    go get github.com/go-delve/delve/cmd/dlv
    go get github.com/stamblerre/gocode
    go get github.com/rogpeppe/godef
    go get golang.org/x/tools/cmd/goimports
    go get golang.org/x/lint/golint
    go get golang.org/x/tools/gopls
    ```
    
-   啟動 Visual Studio Code 開發工具
    
    你現在可以在任何 WSL Distro 裡面直接輸入 `code .` 就可以開啟 Windows 環境下的 Visual Studio Code 開發工具！
    
    ```bash
    code .
    ```
    
    > 預設會自動安裝並載入 [Visual Studio Code Remote - WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl) 擴充套件。
    
-   安裝 [Will 保哥](https://marketplace.visualstudio.com/publishers/doggy8088) 出品的 [Go Extension Pack](https://marketplace.visualstudio.com/items?itemName=doggy8088.go-extension-pack) 擴充套件
    
    快速鍵：`Ctrl-Shift-X` > 搜尋: `doggy8088.go-extension-pack` 即可找到！
    
    這份擴充套件包含了以下擴充套件：
    
    1.  [Go](https://marketplace.visualstudio.com/items?itemName=golang.Go)
    2.  [Code Runner](https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner)
    3.  [Paste JSON as Code](https://marketplace.visualstudio.com/items?itemName=quicktype.quicktype)
    4.  [Gremlins tracker for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=nhoizey.gremlins)
    5.  [vscode-proto3](https://marketplace.visualstudio.com/items?itemName=zxh404.vscode-proto3)
-   執行 VSCode 中 Go 擴充套件的 `Go: Install/Update Tools` 命令一次
    
    `F1` > `Go: Install/Update Tools`
    
    這個命令會自動安裝遺漏的套件，如果已經安裝過，也會自動更新套件！
    
-   調整 Visual Studio Code 使用者設定
    
    在我的 [Go Extension Pack](https://marketplace.visualstudio.com/items?itemName=doggy8088.go-extension-pack) 擴充套件說明頁面有提到幾個 **Recommended Settings** (建議設定)，請記得要手動調整 Visual Studio Code 使用者設定之後才會好用，尤其是快速鍵部分！
    

### 其他推薦的 Visual Studio Code 擴充套件

-   [Control Snippets](https://github.com/svipas/vscode-control-snippets)
    -   可以關掉你不想要的 Code Snippets，無論是 VSCode 內建或是擴充套件安裝過的，都可以設定停用！
    -   https://github.com/Microsoft/vscode/issues/10565#issuecomment-520171990
-   [Git Graph](https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph)
    -   可用來查看漂亮的 Git 版本線圖

> 有其他推薦的 Visual Studio Code 擴充套件嗎？歡迎留言給我！🎉

### 測試是否安裝成功

-   確認目前執行的 Go 版本
    
    ```bash
    go version
    ```
    
-   抓取 Go 套件原始碼回來測試用 VSCode 開啟專案
    
    ```bash
    git clone https://github.com/appleboy/gorush.git
    cd gorush
    make
    code .
    ```
    
-   新增 `.vscode/tasks.json` 設定檔
    
    預設的「建置」與「測試」命令與參數，每個專案都可能有所不同，請記得手動調整過！
    
    ```json
    {
        // See https://go.microsoft.com/fwlink/?LinkId=733558
        // for the documentation about the tasks.json format
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build",
                "command": "go",
                "type": "shell",
                "args": [
                    "build",
                    "-o",
                    "dist/${workspaceFolderBasename}"
                ],
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "presentation": {
                    "reveal": "silent"
                },
                "problemMatcher": "$msCompile"
            },
            {
                "label": "test",
                "command": "go",
                "type": "shell",
                "args": [
                    "test",
                ],
                "group": {
                    "kind": "test",
                    "isDefault": true
                },
                "presentation": {
                    "reveal": "silent"
                },
                "problemMatcher": "$msCompile"
            }
        ]
    }
    ```
    
-   調整 Visual Studio Code 使用者設定
    
    ```json
    {
        "go.useLanguageServer": true,
    
        "editor.snippetSuggestions": "top",
        "terminal.integrated.shellArgs.linux": ["-l"],
    
        "code-runner.saveAllFilesBeforeRun": true,
        "code-runner.ignoreSelection": true,
        "code-runner.runInTerminal": true
    }
    ```
    

### 相關連結

-   [Go Version Manager](https://github.com/moovweb/gvm) (gvm)
-   [Tasks in Visual Studio Code](https://go.microsoft.com/fwlink/?LinkId=733558)
-   [Visual Studio Code Variables Reference](https://code.visualstudio.com/docs/editor/variables-reference)
-   [Go extension for VS Code](https://github.com/golang/vscode-go/)
    -   [vscode-go - Docs](https://github.com/golang/vscode-go/tree/master/docs)
    -   [vscode-go - Modules](https://github.com/golang/vscode-go/blob/05e1f73483eadb6749f3f1f70f9d71dc8f4d1b4c/docs/modules.md)
