Ubuntuにgoenvを導入したログ

2019-12-02

この記事は Go7 Advent Calendar 2019 2日目の記事です。 想定読者は初級者です。

複数のプロジェクトに携わっている場合、プロジェクトごとにGoのバージョンを切り替えたいことがあると思います。また、Goのバージョンアップ前後の動作確認をしたいこともきっとあるはずです。

そこでGo のバージョンを切り替えるツール goenv のインストールと使い方について書きます。 Goの記事ですがGoのコードはほぼ出現しません。

目次

目次

対象OSはUbuntu18.04です。もうすぐ20.04ですね..(遠い目)

今回利用する環境は以下のファイルで作ります。任意のディレクトリの同じ階層に配置してください。

Dockerfile
FROM ubuntu:18.04 AS ubuntu-for-goenv

WORKDIR /root/
RUN set -x; \
  apt update &&\
  apt install -y git wget python3 python3-pip &&\
  python3 -m pip install ansible
docker-compose.yml
version: '3.7'
services:
  goenv:
    build: .
    container_name: ubuntu18.04-for-goenv
    tty: true
    volumes:
      - .:/root/
    working_dir: /root/

Installation

手順 に従ってインストールしていきます。

root@1800db436399:~# git clone https://github.com/syndbg/goenv.git ~/.goenv
Cloning into '/root/.goenv'...
remote: Enumerating objects: 161, done.
remote: Counting objects: 100% (161/161), done.
remote: Compressing objects: 100% (93/93), done.
remote: Total 13996 (delta 78), reused 119 (delta 55), pack-reused 13835
Receiving objects: 100% (13996/13996), 2.53 MiB | 11.56 MiB/s, done.
Resolving deltas: 100% (9556/9556), done.


root@1800db436399:~# echo 'export GOENV_ROOT="$HOME/.goenv"' >> ~/.bashrc
root@1800db436399:~# echo 'export PATH="$GOENV_ROOT/bin:$PATH"' >> ~/.bashrc
root@1800db436399:~# echo 'eval "$(goenv init -)"' >> ~/.bashrc

# goenv に GOPATH と GOROOT を管理させたい場合は `goenv init` の後ろに来るように以下を書き込む
root@1800db436399:~# echo 'export PATH="$GOROOT/bin:$PATH"' >> ~/.bashrc
root@1800db436399:~# echo 'export PATH="$PATH:$GOPATH/bin"' >> ~/.bashrc

# シェルを再読込すると
root@1800db436399:~# exec $SHELL

# 最新版が入りました
root@1800db436399:~# goenv --version
goenv 2.0.0beta11

これだけでは面白くないので Ansible でインストールできるように Playbook を作ります。

できあがったものがこちらです。ローカルで使うことを前提に作ってあります

provision.yaml
- hosts: localhost
  connection: local
  gather_facts: false
  tasks:
  - name: clone goenv
    git:
      repo: https://github.com/syndbg/goenv.git
      dest: ~/.goenv
      force: yes
      version: "{{ version | default('master') }}"

  - name: set export GOENV_ROOT
    lineinfile:
      path: ~/.bashrc
      regexp: '^export GOENV_ROOT="\$HOME/\.goenv"'
      line: export GOENV_ROOT="$HOME/.goenv"
      insertafter: EOF
  
  - name: set export PATH
    lineinfile:
      path: ~/.bashrc
      regexp: '^export PATH="\$GOENV_ROOT/bin:\$PATH"'
      line: export PATH="$GOENV_ROOT/bin:$PATH"
      insertafter: EOF
  
  - name: set goenv init
    lineinfile:
      path: ~/.bashrc
      regexp: '^eval "\$\(goenv init -\)"'
      line: eval "$(goenv init -)"
      insertafter: EOF
  
  - name: set export PATH
    lineinfile:
      path: ~/.bashrc
      regexp: '^export PATH="\$GOROOT/bin:\$PATH"'
      line: export PATH="$GOROOT/bin:$PATH"
      insertafter: EOF
  
  - name: set eport PATH
    lineinfile:
      path: ~/.bashrc
      regexp: '^export PATH="\$PATH:\$GOPATH/bin"'
      line: export PATH="$PATH:$GOPATH/bin"
      insertafter: EOF
  

実行してみます。

せっかくなのでStableなバージョン(執筆時は1.23.3) を入れてみます。

ただしStable版だと 1.12beta1 までしかインストールできないので、実際に導入する場合はバージョンを指定しないほうがよいでしょう。

備考

.bashrc がないとエラーになった場合は空でもいいので touch .bashrc のように作成してください。

# 一旦まっさらにして
root@8fff234db161:~# goenv
bash: goenv: command not found

# extra-vars でバージョン(タグ)を渡す
root@8fff234db161:~# ansible-playbook provision.yaml --extra-vars "version=1.23.3"
[WARNING]: No inventory was parsed, only implicit localhost is available

[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [clone goenv] *************************************************************
changed: [localhost]

TASK [set export GOENV_ROOT] ***************************************************
changed: [localhost]

TASK [set export PATH] *********************************************************
changed: [localhost]

TASK [set goenv init] **********************************************************
changed: [localhost]

TASK [set export PATH] *********************************************************
changed: [localhost]

TASK [set eport PATH] **********************************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=6    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

# シェルを再読込すると
root@8fff234db161:~# exec $SHELL

# インストールされてますね
root@8fff234db161:~# goenv --version
goenv 1.23.3

多分Ubuntuなら動くと思います。 git とか入ってないとだめですが。

Use

話が横にそれましたが、さっきの続きです。

もう少しコマンドを触ってみましょう。

コマンド一覧
# コマンドの一覧
root@1800db436399:~# goenv commands
--version
commands
completions
exec
global
help
hooks
init
install
local
prefix
rehash
root
shell
shims
uninstall
version
version-file
version-file-read
version-file-write
version-name
version-origin
versions
whence
which
# 1.12.0 をインストール
root@1800db436399:~# goenv install 1.12.0
Downloading go1.12.linux-amd64.tar.gz...
-> https://dl.google.com/go/go1.12.linux-amd64.tar.gz
Installing Go Linux 64bit 1.12.0...
Installed Go Linux 64bit 1.12.0 to /root/.goenv/versions/1.12.0

# 1.13.4 をインストール
root@1800db436399:~# goenv install 1.13.4
Downloading go1.13.4.linux-amd64.tar.gz...
-> https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz
Installing Go Linux 64bit 1.13.4...
Installed Go Linux 64bit 1.13.4 to /root/.goenv/versions/1.13.

# バージョン一覧
root@1800db436399:~# goenv versions
  1.12.0
  1.13.4

root@1800db436399:~# ls ~/.goenv/versions/
1.12.0  1.13.4

# グローバルバージョンを 1.12.0 にセットする
root@1800db436399:~# goenv global 1.12.0
root@1800db436399:~# goenv versions
* 1.12.0 (set by /root/.goenv/version)
  1.13.4

# subディレクトリを作り,ローカルバージョンを 1.13.4 にセットする
root@1800db436399:~# mkdir sub
root@1800db436399:~# cd sub/
root@1800db436399:~/sub# goenv local 1.13.4
root@1800db436399:~/sub# goenv versions
  1.12.0
* 1.13.4 (set by /root/sub/.go-version)

# subディレクトリから出ると1.12.0 に戻る
root@1800db436399:~/sub# cd ..
root@1800db436399:~# goenv exec go version # goenv version でも可
go version go1.12 linux/amd64
root@1800db436399:~# goenv versions
* 1.12.0 (set by /root/.goenv/version)
  1.13.4

# subディレクトリに入ると 1.13.4 が自動的にセットされる
root@1800db436399:~# cd sub/
root@1800db436399:~/sub# goenv exec go version # goenv version でも可
go version go1.13.4 linux/amd64
root@1800db436399:~/sub# goenv versions
  1.12.0
* 1.13.4 (set by /root/sub/.go-version)

goenv のコマンド体系はシンプルでわかりやすいのであまりハマることはないと思いますが、基本的なコマンドくらいはいつでも使えるようにしておきたいところですね

個人的に使いそうなサブコマンドを一覧にしてみました。

exec:

現在のセットされているバージョンの go コマンドを使って色々する

$ goenv exec go run main.go
install:

対象のGoバージョンをインストール

$ goenv install 1.13.4
uninstall:

対象のGoバージョンをアンインストール

$ goenv uninstall 1.12.0
global:

デフォルト(グローバル)のGoバージョンを設定する

$ goenv global 1.12.0
local:

そのディレクトリだけで有効な(ローカルの)Goバージョンを設定する

$ goenv local 1.13.4
versions:

利用可能なGoバージョンの一覧および現在のGoバージョンを表示する

$ goenv versions
which:

実行ファイルが置かれているファイルパスを表示する

$ goenv which gofmt

以上です。明日も書きます。