序章

Goでは、ビルドタグ、つまりビルド制約は、buildプロセス中にファイルをパッケージに含めるタイミングを決定するコードに追加される識別子です。 これにより、同じソースコードから異なるバージョンのGoアプリケーションを構築し、それらをすばやく整理された方法で切り替えることができます。 多くの開発者は、ビルドタグを使用して、異なるオペレーティングシステム間の差異を考慮してコードを変更する必要があるプログラムなど、クロスプラットフォーム互換のアプリケーションを構築するワークフローを改善します。 ビルドタグは統合テストにも使用され、統合コードとモックサービスまたはスタブを使用したコードをすばやく切り替えたり、アプリケーション内のさまざまなレベルの機能セットに使用したりできます。 。

例として、顧客の機能セットが異なるという問題を取り上げましょう。 一部のアプリケーションを作成する場合、 Free Pro 、および Enterprise レベルを提供するアプリケーションなど、バイナリに含める機能を制御したい場合があります。 顧客がこれらのアプリケーションのサブスクリプションレベルを上げると、より多くの機能がロック解除されて利用可能になります。 この問題を解決するには、importステートメントを使用して、別々のプロジェクトを維持し、それらの同期を維持しようとすることができます。 このアプローチは機能しますが、時間の経過とともに退屈でエラーが発生しやすくなります。 別のアプローチは、ビルドタグを使用することです。

この記事では、Goでビルドタグを使用して、サンプルアプリケーションのFree、Pro、およびEnterprise機能セットを提供するさまざまな実行可能バイナリを生成します。 それぞれに異なる機能セットがあり、デフォルトは無料バージョンです。

前提条件

この記事の例に従うには、次のものが必要です。

無料版の作成

ビルドタグなしでgo buildを実行するとデフォルトになるため、アプリケーションの無料バージョンをビルドすることから始めましょう。 後で、ビルドタグを使用して、プログラムに他の部分を選択的に追加します。

srcディレクトリに、アプリケーションの名前でフォルダを作成します。 このチュートリアルでは、appを使用します。

  1. mkdir app

このフォルダに移動します:

  1. cd app

次に、選択したテキストエディタでmain.goという名前の新しいテキストファイルを作成します。

  1. nano main.go

次に、アプリケーションの無料バージョンを定義します。 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スライスを介してを範囲指定し、画面で使用可能なすべての機能を印刷します。

ファイルを保存して終了します。 このファイルが保存されたので、記事の残りの部分で編集する必要はありません。 代わりに、ビルドタグを使用して、そこからビルドするバイナリの機能を変更します。

プログラムをビルドして実行します。

  1. go build
  2. ./app

次の出力が表示されます。

Output
> Free Feature #1 > Free Feature #2

プログラムは2つの無料機能を印刷し、アプリの無料バージョンを完成させました。

これまで、非常に基本的な機能セットを備えたアプリケーションを作成しました。 次に、ビルド時にアプリケーションに機能を追加する方法を構築します。

go buildでプロ機能を追加する

これまでのところ、main.goに変更を加えることは避けており、メインコードを変更したり、場合によっては壊したりせずにコードを追加する必要がある一般的な本番環境をシミュレートしています。 main.goファイルは編集できないため、ビルドタグを使用してfeaturesスライスにさらに多くの機能を挿入するための別のメカニズムを使用する必要があります。

init()関数を使用してfeaturesスライスに機能を追加するpro.goという新しいファイルを作成しましょう。

  1. nano pro.go

エディタがファイルを開いたら、次の行を追加します。

pro.go
package main

func init() {
  features = append(features,
    "Pro Feature #1",
    "Pro Feature #2",
  )
}

このコードでは、init()を使用して、アプリケーションのmain()関数の前にコードを実行し、続いてappend()を使用して、Pro機能をfeaturesスライスに追加しました。 。 ファイルを保存して終了します。

go buildを使用してアプリケーションをコンパイルして実行します。

  1. go build

現在のディレクトリに2つのファイル(pro.gomain.go)があるため、go buildは両方からバイナリを作成します。 このバイナリを実行します。

  1. ./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コマンドに無視するように指示して、これが実際に動作することを確認しましょう。 テキストエディタでファイルを開きます。

  1. nano pro.go

次に、次の強調表示された行を追加します。

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ファイルのみが含まれるようになります。

アプリケーションをコンパイルして再度実行します。

  1. go build
  2. ./app

次の出力が表示されます。

Output
> Free Feature #1 > Free Feature #2

pro.goファイルにはproタグが存在する必要があるため、ファイルは無視され、アプリケーションはそれなしでコンパイルされます。

go buildコマンドを実行する場合、-tagsフラグを使用して、タグ自体を引数として追加することにより、コンパイルされたソースに条件付きでコードを含めることができます。 proタグに対してこれを実行しましょう。

  1. 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を作成します。

  1. nano enterprise.go

enterprise.goの内容は、pro.goとほぼ同じように見えますが、新しい機能が含まれています。 次の行をファイルに追加します。

Enterprise.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に追加しましょう。 テキストエディタでファイルを開きます。

  1. nano enterprise.go

次に、package main宣言の前にビルドタグを追加し、ビルドタグの後に改行を含めるようにしてください。

Enterprise.go
// +build pro

package main

func init() {
  features = append(features,
    "Enterprise Feature #1",
    "Enterprise Feature #2",
  )
}

ファイルを保存して終了します。

タグなしでアプリケーションをコンパイルして実行します。

  1. go build
  2. ./app

次の出力が表示されます。

Output
> Free Feature #1 > Free Feature #2

エンタープライズ機能は、無料バージョンでは表示されなくなりました。 次に、proビルドタグを追加し、アプリケーションをビルドして再度実行します。

  1. go build -tags pro
  2. ./app

次の出力が表示されます。

Output
> Free Feature #1 > Free Feature #2 > Enterprise Feature #1 > Enterprise Feature #2 > Pro Feature #1 > Pro Feature #2

これはまだ正確には必要なものではありません。Proバージョンをビルドしようとすると、Enterprise機能が表示されるようになりました。 これを解決するには、別のビルドタグを使用する必要があります。 ただし、proタグとは異なり、proenterpriseの両方の機能が使用可能であることを確認する必要があります。

Goビルドシステムは、ビルドタグシステムでいくつかの基本的なブールロジックの使用を許可することにより、この状況を説明します。

enterprise.goをもう一度開きましょう。

  1. nano enterprise.go

proタグと同じ行に、別のビルドタグenterpriseを追加します。

Enterprise.go
// +build pro enterprise

package main

func init() {
  features = append(features,
    "Enterprise Feature #1",
    "Enterprise Feature #2",
  )
}

ファイルを保存して閉じます。

次に、新しいenterpriseビルドタグを使用してアプリケーションをコンパイルして実行しましょう。

  1. go build -tags enterprise
  2. ./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 buildANDロジックを使用してそれらのタグを解釈します。

enterprise.goをもう一度開き、ビルドタグを複数の行に分けましょう。

Enterprise.go
// +build pro
// +build enterprise

package main

func init() {
  features = append(features,
    "Enterprise Feature #1",
    "Enterprise Feature #2",
  )
}

次に、新しいenterpriseビルドタグを使用してアプリケーションをコンパイルして実行します。

  1. go build -tags enterprise
  2. ./app

次の出力が表示されます。

Output
> Free Feature #1 > Free Feature #2

まだ完全ではありません。ANDステートメントでは両方の要素をtrueと見なす必要があるため、proenterpriseの両方のビルドタグを使用する必要があります。

もう一度試してみましょう:

  1. go build -tags "enterprise pro"
  2. ./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シリーズのコーディング方法を引き続き参照してください。