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

Go & Versioning(vgo)を読んで大きな変更が入ったなと思った

More than 1 year has passed since last update.

このQiita記事は、Go & Versioningで掲載された一連の記事を読んで、自分なりのまとめと感想です。私の周りはあまり騒いでないけど、これ感覚的なものが大きく変わるなあ、と思ったので、主に表面上に現れる変更をまとめました。

これは、Go 1.11で試験的な導入、Go 1.12で正式サポートとなる予定の機能に関する話です。

@nekketsuuuさんが原文の和訳をされています。

何が変わるのか

バージョン管理機能の導入

goコマンドにバージョン管理の機能が追加されます。バージョンは常にセマンティックバージョニングで表します。今もdepコマンドが(goとは別に)存在しますが、バージョン管理機能が追加されたgoコマンド(以下vgoと表記)は、depglideなどの依存管理ツールとは別のアプローチでバージョンを管理します。とはいえ、目的はどちらもバージョン管理なので、vgoを使う場合はdepを使いません。また、vgovendorディレクトリを使わないためvendorも不要です。

モジュールという単位の追加

バージョン管理機能に伴って、Goのパッケージにモジュールという単位が追加されます。モジュールは複数のパッケージをまとめたもので、go.modというファイルで管理します。Go & Versioningでは以下の例が記されていました。

go.mod
// My hello, world

module "rsc.io/hello"

require (
    "golang.org/x/text" v0.0.0-20180208041248-4e4a3210bb54
    "rsc.io/quote" v1.5.2
)

モジュールは、vgoでバージョン管理を行う基本的な単位となります。1つのリポジトリが1つのモジュールに該当し、タグ(git tag)を使ってモジュールにバージョンを与えます。従って、バージョン管理を行う単位はモジュールです。例えば、上のgo.modでリストされているgolang.org/x/textrsc.io/quoteもモジュールです。今まではパッケージという扱いでしたが、モジュールに変わります。

モジュールのアップデートはvgo get

モジュールはgo.modファイルでバージョンを指定しますが、これを人が維持するのは大変です。vgo getで必要なモジュールを追加したり、vgo get -uでアップデートを行ったりするようです。

たくさんのExampleが書かれているのでA Tour of Versioned Goを眺めてみてください。これだけで雰囲気はつかめると思います。

破壊的変更を加える場合はimport pathを変更する

vgoで扱うパッケージは、全て後方互換性を持たなければなりません。例えばAというパッケージの作者は、メジャーバージョンが同じ間は後方互換性を維持する必要があります。この制約によって、v1.1.0を参照しているプログラムは、v1.2.1が使われた場合でも同じように動作することが保証されます。もしマイナーバージョンのアップデートでビルドが壊れた場合、Av1.2.2で過去の互換性を取り戻すべきです。例えば、関数の動作を変更する場合は、仕様変更ではなく名前を変えて新しい関数として追加しましょう。

とはいえ、どうしても破壊的な変更が避けられないケースは存在します。その場合はimport pathを変更することで別のパッケージとして作成してください。例えば、lufia.org/pkg/xに破壊的変更を加える場合、新しいバージョンはlufia.org/pkg/x/v2のようにメジャーバージョンを含むimport pathにしましょう。そうするとv1v2で重複する部分がソースコードの二重管理になりがちですが、それはtypealias等を使って頑張ってください。

最初からimport pathをlufia.org/pkg/x/v1のようにするべきかについては、最終的にどうなるかは分かりませんが、個人的には「最初はバージョンを含めない」でいいと思います。

$GOPATHが不要になる

これまで$GOPATHはGoワークスペースのルートとして必要でしたが、vgoではgo.modによってモジュールのURLやバージョンが明確に特定できるため、$GOPATHがなくてもソースコードの取得やビルドの再現性には困りません。参照するモジュールのマイナーバージョンは上がるかもしれませんが、マイナーバージョンの変更はモジュール作者の努力によって互換性が維持されるため、最終的な動作は変わらないことが保証できます。

これによって、任意のディレクトリでGoのコードを書くことが可能となります。今までのように、$GOPATH配下にワークスペースを構築する必要は無くなります。

ただこれ疑問なのは、今までの$GOPATH直下には

$ ls $GOPATH
bin pkg src

が存在していて、まあsrcpkgは無くてもいいかなと思うのですが、go getでインストールする場所としての$GOPATHはどうなるんだろう?と思いました。

何が変わらないのか

今までのコードはそのままビルド可能

vgoだからといって今までのコードが壊れることはありません。$GOPATHvendorも、不要になるだけで、そのまま使えます。go.modがないリポジトリもそのままビルドできるはずです。

depvgoが普及するまでは残る

長期的にみればdepは無くなるのかもしれませんが、少なくともvgoがリリースされて、十分に普及するまでは継続することが書かれていました。今すぐ何かが変わることはないので、そのまま使い続けても問題ないと思います。

今後の話

vgoは、この記事の最初にも書きましたけれど、Go 1.11で試験的な導入、Go 1.12で正式サポートとなる予定です。今はまだGo 1.10がリリースされたばかりなので何もしなくても良いと思いますが、半年後にGo 1.11がリリースされたら、特にパッケージ作者は以下のことに注意しましょう。

  • go.modを作成しましょう
  • セマンティックバージョニングでタグを打ちましょう
  • import pathが同一である限り後方互換性を維持しましょう
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした