LoginSignup
9
3

More than 5 years have passed since last update.

複数のGolangバージョンに対応したパッケージを書く

Last updated at Posted at 2016-12-20

GoにはGo 1 promise of compatibilityがあり基本的にGo1.xでAPIのインターフェースが変更されることはない.そのため過去に書いたコードを新しいGoでビルドしてもぶっ壊れることは(おそらく)ない.ただリリースごとに新しいパッケージや関数/メソッドはどんどん追加されていくため古いGoで新しいコードをビルドすることはできないことがある(例えば,標準のcontextパッケージを使っているコードはGo1.7以降でしかビルドすることができない).

GoはリリースごとにGC(e.g., Sub-millisecond GC pauses)やコンパイラ(e.g, SSAの導入)や各標準パッケージの改善が行われる.そのため自分は「どんどんバージョン上げていけば良い.だからパッケージも同じく最新のバージョンで動くものを提供すれば良い」と思う.がこれは個人的な思想で誰かが使える形でインターネットに公開している限りは横暴でもある.少なくとも移行期(以下の図でいうとStage2)を持たせるのが真摯な姿勢だと思う.

https://talks.golang.org/2016/refactor.article

新しいバージョンのGoを使っているユーザには新たに追加された関数/メソッドを利用可能にしつつ,古いバージョンのGoを使っているユーザのビルドを壊さないようにするにはBuild Constraintsを使えば良い.

例えば以下のようなmain関数を考える.

func main() {
    fmt.Println(Hello())
}

このときGo1.8以降でしか使えない関数/メソッドを使ったHelloとそれ以前のバージョン用のHelloを提供するには以下のように2つのファイルを準備すれば良い.

// +build go1.8

package main

func Hello() string {
    return "Hello (after go1.8)"
}
// +build !go1.8

package main

func Hello() string {
    return "Hello (old version)"
}

go1.8のビルドタグを持つファイルはGo1.8以降(betaも含む)のビルドに使われ!go1.8のタグを持つファイルはそれ以前の古いバージョンのビルドにのみ利用される.

まとめ

特に最近は標準パッケージがcontext対応を始めているのでこれを利用する機会は増えるのではないか.やりすぎは良くない気もするのであくまで移行期のための手段とするのが良いと思う.ある程度経ったら古いバージョンは切り捨てればいい.

参考

Build ConstraintsについてはみんなのGo言語mattnさんの章に詳しい解説がある.またmattnさんはgo-sqlite3で同様の対応をしている(sqlite3_go18.go).自分も最近go-httpstatで同様にGo1.8の対応をした(#10).

標準パッケージだとxのcontextパッケージが同様のことをしている.

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3