Help us understand the problem. What is going on with this article?

Go1.16からの go get と go install について

この記事はGo Advent Calendar 2020 16日目の代打記事です。奇しくも16日目にGo1.16の話をすることになりました。

はじめに

Go1.16では、Modulesに関する様々なアップデートが入ります。cf. https://tip.golang.org/doc/go1.16#tools

  • ツールのグローバルインストールを簡単にするため、go install に新たな機能が追加されました。今後は「バイナリのビルドとインストールのための go install」、「go.mod 編集のための go get」と役割が整理されていくことになりました。(issueはこちら。)
  • GO111MODULE はデフォルトでon、つまり常にModuleモードが有効になりました。GOPATHモードにお別れを。
  • go buildgo test で自動的に go.mod が更新されることがなくなりました。go.mod の編集は go get , go mod tidy , あるいは手作業で行います。

この記事では、Go1.16以降のgo get / go install の使い方、抑えておきたいポイントを解説します。ちなみに、以下はすべてGOPATHモードではなくModuleモード前提で解説しています。(でないと複雑になりすぎるので)

抑えておきたいポイント

  • 基本的に、ツールのグローバルインストールには go install <package>@<version> を使用します。
    • 例: go install golang.org/x/tools/gopls@latest
    • スクリプトなどに書いていた方はごめんなさい、修正をお勧めします。
  • go get のバイナリインストールの機能は今後のバージョンで削除される予定です。
  • go getgo.mod に依存性を追記するためだけのコマンドとして整理されていきますが、go.mod の編集には go get 以外の方法も用意されているので、go get を使う機会は今後少なくなっていきそうです。

Go1.16で解決されるツールのインストール問題

今までGoでグローバル ($GOPATH/bin) にツールをインストールするにはお馴染みの go get コマンドが使われてきましたが、一つ問題を抱えていました。go getgo.mod を編集する役割も兼ねているため、go.mod を触らずにツールだけをインストールするには「go.mod のあるディレクトリを抜けて」「ツール側の go.mod を有効にし」go get する、という手順が必要でした。一つにまとめると以下のようになります。

$ cd $(mktemp -d); GO111MODULE=on go get golang.org/x/tools/gopls

流石にインストール一つにこんな手間は掛けたくないし、何よりModulesについてよく知らずに go get を行い不本意な go.mod の更新を行ってしまう事故が絶えませんでした。(ソースは筆者)

というわけで、Go1.16からは以下のようになります。

$ go install golang.org/x/tools/gopls@latest

とてもすっきりしましたね。

実はこの go install <package>@<version> という書式がGo1.16で新たに導入されたものです。この書式では、Module配下であろうとなかろうと、一貫して指定したversionを $GOPATH/bin にインストールします。

Go1.16では GO111MODULE はデフォルトでonになっているし、go installgo.mod を編集しなくなるため、もろもろの事故が起こることもなくなりました。

注意

  • @version つきでインストールできるのはmain packageのみです。非main packageはこの書式の対象ではありません。

補足: version指定なしの go install <package> について

  • Module外で @version なしの go install <package> は出来ません。
  • Module配下では、@version なしのインストールも可能(go.mod のバージョンが反映される)ですが、main packageを go.mod に記載しておくにはひと手間必要なので、Module配下であろうと go install <package>@<version> を行うのがシンプルでよいかと思います。
    • 非main packageのインストールについては、次の項目をご覧ください。

go install のその他の機能について

go install のその他の機能、つまり、

  • 作業ディレクトリをビルドして $GOPATH/bin に配置する機能
  • 非main packageをビルドしてキャッシュする機能(Module配下で、version指定せずに go install <package>

については、従来のまま変わりありません。これらは無くても生きていける代物ではありますが、たまに思い出すと便利かもしれません。

go get, go.mod について

一方の go get は、バイナリインストールの役割を go install に譲り、go.mod を編集するためだけのコマンドとして整理されていきます。Go1.16より後のリリース(Go1.17予定)では、go get によるバイナリインストールの機能は削除され、go get はすべて go get -d 相当の、ソースをダウンロードし go.mod に追記するだけの挙動になる予定です。

go.mod を編集する方法

Go1.16では他にも、go buildgo test で自動的に go.mod が編集されないという挙動の変更がありました。これらを踏まえて、Go1.16で go.mod を扱う方法は以下の通りになります。

A) コードにimport文を書いてから go.mod に反映する方法

  • go get # 引数なし
    • 新規モジュール追加のみ
  • go mod tidy
    • 不要モジュールの削除と新規モジュールの追加を行ってくれる

B) importされていないモジュールを go.mod に追加する方法

  • go get <package>[@<version>]
  • 手作業で go.mod を編集

4つ挙げましたが、実際のところ go mod tidy がすべて賄っているので、go mod tidy 一本で行ってもよさそうです。

Go1.15からの変更点

先に述べている通り、go build などによる go.mod の自動編集の機能はGo1.16から無効になるため、Go1.15までのユーザーは、go.mod が変更されるのに期待して go build するとあれっ?となるかもしれません。go mod tidy しておきましょう。

また、Go1.17以降で go get のバイナリインストールの機能が削除されるため、それまでに各種手順書やスクリプトを修正する必要がありそうです。

goplsv0.6.0からGo1.16に追従して go.mod の自動編集を行わなくなる変更が入っています。順次開発フローに関しても、新しいModulesに寄せて整っていくのではないかと思われます。

まとめ

ツール周りで一部非互換な変更が入りますが、Go1.16からのModulesは大幅に簡潔かつハマりどころも少なくなっているため、より初心者には勧めやすくなったのではないでしょうか。Goを布教したい気持ちが強い筆者としては、ハマりどころが少なくなると非常にやりやすくなるし、布教のモチベも高まります。

他にも embed やら io/fs やら目玉機能が目白押しのGo1.16が待ち遠しいところです。リリース予定は来年の2月頃です。

eihigh
denagames
ユーザーファーストを掲げ、アプリ・ブラウザゲームの運営に特化したDeNAのグループ会社です
https://denagames-tokyo.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away