ビルドタグを使用したGoバイナリのカスタマイズ
序章
Goでは、ビルドタグ、つまりビルド制約は、build
プロセス中にファイルをパッケージに含めるタイミングを決定するコードに追加される識別子です。 これにより、同じソースコードから異なるバージョンのGoアプリケーションを構築し、それらをすばやく整理された方法で切り替えることができます。 多くの開発者は、ビルドタグを使用して、異なるオペレーティングシステム間の差異を考慮してコードを変更する必要があるプログラムなど、クロスプラットフォーム互換のアプリケーションを構築するワークフローを改善します。 ビルドタグは統合テストにも使用され、統合コードとモックサービスまたはスタブを使用したコードをすばやく切り替えたり、アプリケーション内のさまざまなレベルの機能セットに使用したりできます。 。
例として、顧客の機能セットが異なるという問題を取り上げましょう。 一部のアプリケーションを作成する場合、 Free 、 Pro 、および Enterprise レベルを提供するアプリケーションなど、バイナリに含める機能を制御したい場合があります。 顧客がこれらのアプリケーションのサブスクリプションレベルを上げると、より多くの機能がロック解除されて利用可能になります。 この問題を解決するには、import
ステートメントを使用して、別々のプロジェクトを維持し、それらの同期を維持しようとすることができます。 このアプローチは機能しますが、時間の経過とともに退屈でエラーが発生しやすくなります。 別のアプローチは、ビルドタグを使用することです。
この記事では、Goでビルドタグを使用して、サンプルアプリケーションのFree、Pro、およびEnterprise機能セットを提供するさまざまな実行可能バイナリを生成します。 それぞれに異なる機能セットがあり、デフォルトは無料バージョンです。
前提条件
この記事の例に従うには、次のものが必要です。
- Goのインストール方法とローカルプログラミング環境のセットアップに従ってセットアップされたGoワークスペース。
無料版の作成
ビルドタグなしでgo build
を実行するとデフォルトになるため、アプリケーションの無料バージョンをビルドすることから始めましょう。 後で、ビルドタグを使用して、プログラムに他の部分を選択的に追加します。
src
ディレクトリに、アプリケーションの名前でフォルダを作成します。 このチュートリアルでは、app
を使用します。
- mkdir app
このフォルダに移動します:
- cd app
次に、選択したテキストエディタでmain.go
という名前の新しいテキストファイルを作成します。
- nano main.go
次に、アプリケーションの無料バージョンを定義します。 main.go
に次の内容を追加します。
package main
import "fmt"
var features = []string{
"Free Feature #1",
"Free Feature #2",
}
func main() {
for _, f := range features {
fmt.Println(">", f)
}
}
このファイルでは、Freeアプリケーションの機能を表す2つの文字列を保持するfeatures
という名前のスライスを宣言するプログラムを作成しました。 アプリケーションのmain()
関数は、 forループを使用して、features
スライスを介してを範囲指定し、画面で使用可能なすべての機能を印刷します。
ファイルを保存して終了します。 このファイルが保存されたので、記事の残りの部分で編集する必要はありません。 代わりに、ビルドタグを使用して、そこからビルドするバイナリの機能を変更します。
プログラムをビルドして実行します。
- go build
- ./app
次の出力が表示されます。
Output> Free Feature #1
> Free Feature #2
プログラムは2つの無料機能を印刷し、アプリの無料バージョンを完成させました。
これまで、非常に基本的な機能セットを備えたアプリケーションを作成しました。 次に、ビルド時にアプリケーションに機能を追加する方法を構築します。
go build
でプロ機能を追加する
これまでのところ、main.go
に変更を加えることは避けており、メインコードを変更したり、場合によっては壊したりせずにコードを追加する必要がある一般的な本番環境をシミュレートしています。 main.go
ファイルは編集できないため、ビルドタグを使用してfeatures
スライスにさらに多くの機能を挿入するための別のメカニズムを使用する必要があります。
init()関数を使用してfeatures
スライスに機能を追加するpro.go
という新しいファイルを作成しましょう。
- nano pro.go
エディタがファイルを開いたら、次の行を追加します。
package main
func init() {
features = append(features,
"Pro Feature #1",
"Pro Feature #2",
)
}
このコードでは、init()
を使用して、アプリケーションのmain()
関数の前にコードを実行し、続いてappend()
を使用して、Pro機能をfeatures
スライスに追加しました。 。 ファイルを保存して終了します。
go build
を使用してアプリケーションをコンパイルして実行します。
- go build
現在のディレクトリに2つのファイル(pro.go
とmain.go
)があるため、go build
は両方からバイナリを作成します。 このバイナリを実行します。
- ./app
これにより、次の機能セットが提供されます。
Output> Free Feature #1
> Free Feature #2
> Pro Feature #1
> Pro Feature #2
アプリケーションには、Pro機能とFree機能の両方が含まれるようになりました。 ただし、これは望ましくありません。バージョン間の区別がないため、無料バージョンには、Proバージョンでのみ使用できるはずの機能が含まれるようになりました。 これを修正するには、アプリケーションのさまざまな層を管理するコードを追加するか、ビルドタグを使用して、ビルドする.go
ファイルと無視するファイルをGoツールチェーンに指示します。 次のステップでビルドタグを追加しましょう。
ビルドタグの追加
これで、ビルドタグを使用して、アプリケーションのProバージョンとFreeバージョンを区別できます。
ビルドタグがどのように見えるかを調べることから始めましょう:
// +build tag_name
このコード行をパッケージの最初の行として配置し、tag_name
をビルドタグの名前に置き換えることで、このパッケージに、最終的なバイナリに選択的に含めることができるコードとしてタグを付けることができます。 pro.go
ファイルにビルドタグを追加して、タグが指定されていない限りgo build
コマンドに無視するように指示して、これが実際に動作することを確認しましょう。 テキストエディタでファイルを開きます。
- nano pro.go
次に、次の強調表示された行を追加します。
// +build pro
package main
func init() {
features = append(features,
"Pro Feature #1",
"Pro Feature #2",
)
}
pro.go
ファイルの先頭に、// +build pro
の後に空白の改行を追加しました。 この末尾の改行は必須です。それ以外の場合、Goはこれをコメントとして解釈します。 ビルドタグの宣言も、.go
ファイルの一番上にある必要があります。 ビルドタグの上にあるものはなく、コメントもありません。
+build
宣言は、go build
コマンドに、これはコメントではなく、ビルドタグであることを通知します。 2番目の部分はpro
タグです。 pro.go
ファイルの先頭にこのタグを追加することにより、go build
コマンドには、pro
タグが存在するpro.go
ファイルのみが含まれるようになります。
アプリケーションをコンパイルして再度実行します。
- go build
- ./app
次の出力が表示されます。
Output> Free Feature #1
> Free Feature #2
pro.go
ファイルにはpro
タグが存在する必要があるため、ファイルは無視され、アプリケーションはそれなしでコンパイルされます。
go build
コマンドを実行する場合、-tags
フラグを使用して、タグ自体を引数として追加することにより、コンパイルされたソースに条件付きでコードを含めることができます。 pro
タグに対してこれを実行しましょう。
- go build -tags pro
これにより、次のように出力されます。
Output> Free Feature #1
> Free Feature #2
> Pro Feature #1
> Pro Feature #2
これで、pro
ビルドタグを使用してアプリケーションをビルドするときにのみ追加機能を取得できます。
バージョンが2つしかない場合は問題ありませんが、タグを追加すると複雑になります。 次のステップでアプリのエンタープライズバージョンを追加するには、ブール論理で結合された複数のビルドタグを使用します。
タグブール論理を構築する
Goパッケージに複数のビルドタグがある場合、タグはブール論理を使用して相互に作用します。 これを実証するために、pro
タグとenterprise
タグの両方を使用してアプリケーションのエンタープライズレベルを追加します。
Enterpriseバイナリを構築するには、デフォルト機能、Proレベルの機能、およびEnterpriseの新しい機能セットの両方を含める必要があります。 まず、エディターを開き、新しいエンタープライズ機能を追加する新しいファイルenterprise.go
を作成します。
- nano enterprise.go
enterprise.go
の内容は、pro.go
とほぼ同じように見えますが、新しい機能が含まれています。 次の行をファイルに追加します。
package main
func init() {
features = append(features,
"Enterprise Feature #1",
"Enterprise Feature #2",
)
}
ファイルを保存して終了します。
現在、enterprise.go
ファイルにはビルドタグがありません。pro.go
を追加したときに学んだように、これはgo.build
の実行時にこれらの機能が無料バージョンに追加されることを意味します。 。 pro.go
の場合、ファイルの先頭に// +build pro
と改行を追加して、-tags pro
が使用されている場合にのみ含める必要があることをgo build
に通知します。 この状況では、目標を達成するために必要なビルドタグは1つだけです。 ただし、新しいEnterprise機能を追加するときは、最初にPro機能も必要です。
まず、pro
ビルドタグのサポートをenterprise.go
に追加しましょう。 テキストエディタでファイルを開きます。
- nano enterprise.go
次に、package main
宣言の前にビルドタグを追加し、ビルドタグの後に改行を含めるようにしてください。
// +build pro
package main
func init() {
features = append(features,
"Enterprise Feature #1",
"Enterprise Feature #2",
)
}
ファイルを保存して終了します。
タグなしでアプリケーションをコンパイルして実行します。
- go build
- ./app
次の出力が表示されます。
Output> Free Feature #1
> Free Feature #2
エンタープライズ機能は、無料バージョンでは表示されなくなりました。 次に、pro
ビルドタグを追加し、アプリケーションをビルドして再度実行します。
- go build -tags pro
- ./app
次の出力が表示されます。
Output> Free Feature #1
> Free Feature #2
> Enterprise Feature #1
> Enterprise Feature #2
> Pro Feature #1
> Pro Feature #2
これはまだ正確には必要なものではありません。Proバージョンをビルドしようとすると、Enterprise機能が表示されるようになりました。 これを解決するには、別のビルドタグを使用する必要があります。 ただし、pro
タグとは異なり、pro
とenterprise
の両方の機能が使用可能であることを確認する必要があります。
Goビルドシステムは、ビルドタグシステムでいくつかの基本的なブールロジックの使用を許可することにより、この状況を説明します。
enterprise.go
をもう一度開きましょう。
- nano enterprise.go
pro
タグと同じ行に、別のビルドタグenterprise
を追加します。
// +build pro enterprise
package main
func init() {
features = append(features,
"Enterprise Feature #1",
"Enterprise Feature #2",
)
}
ファイルを保存して閉じます。
次に、新しいenterprise
ビルドタグを使用してアプリケーションをコンパイルして実行しましょう。
- go build -tags enterprise
- ./app
これにより、次のようになります。
Output> Free Feature #1
> Free Feature #2
> Enterprise Feature #1
> Enterprise Feature #2
これで、Proの機能が失われました。 これは、.go
ファイルの同じ行に複数のビルドタグを配置すると、go build
がそれらをOR
ロジックを使用していると解釈するためです。 // +build pro enterprise
の行を追加すると、 pro
ビルドタグまたはenterprise
ビルドの場合、enterprise.go
ファイルがビルドされます。タグが存在します。 両方を必要とし、代わりにAND
ロジックを使用するには、ビルドタグを正しく設定する必要があります。
両方のタグを同じ行に配置する代わりに、別々の行に配置すると、go build
はAND
ロジックを使用してそれらのタグを解釈します。
enterprise.go
をもう一度開き、ビルドタグを複数の行に分けましょう。
// +build pro
// +build enterprise
package main
func init() {
features = append(features,
"Enterprise Feature #1",
"Enterprise Feature #2",
)
}
次に、新しいenterprise
ビルドタグを使用してアプリケーションをコンパイルして実行します。
- go build -tags enterprise
- ./app
次の出力が表示されます。
Output> Free Feature #1
> Free Feature #2
まだ完全ではありません。AND
ステートメントでは両方の要素をtrue
と見なす必要があるため、pro
とenterprise
の両方のビルドタグを使用する必要があります。
もう一度試してみましょう:
- go build -tags "enterprise pro"
- ./app
次の出力が表示されます。
Output> Free Feature #1
> Free Feature #2
> Enterprise Feature #1
> Enterprise Feature #2
> Pro Feature #1
> Pro Feature #2
これで、同じソースツリーから複数の方法でアプリケーションを構築し、それに応じてアプリケーションの機能のロックを解除できます。
この例では、新しい// +build
タグを使用してAND
ロジックを示していますが、ビルドタグを使用してブールロジックを表す別の方法があります。 次の表は、ビルドタグの他の構文フォーマットの例と、それに相当するブール値を示しています。
ビルドタグ構文 | ビルドタグサンプル | ブール式 |
---|---|---|
スペースで区切られた要素 | // +build pro enterprise |
pro またはenterprise |
カンマ区切りの要素 | // +build pro,enterprise |
pro およびenterprise |
感嘆符の要素 | // +build !pro |
pro ではありません |
結論
このチュートリアルでは、ビルドタグを使用して、どのコードをバイナリにコンパイルするかを制御できるようにしました。 最初に、ビルドタグを宣言し、それらをgo build
で使用し、次にブール論理で複数のタグを組み合わせました。 次に、Free、Pro、およびEnterpriseバージョンのさまざまな機能セットを表すプログラムを作成し、ビルドタグがプロジェクトを制御できる強力なレベルを示しました。
ビルドタグについて詳しく知りたい場合は、Golangのドキュメントを参照するか、Goシリーズのコーディング方法を引き続き参照してください。