前書き

実稼働環境にアプリケーションをデプロイする場合、バージョン情報やその他のメタデータを使用してバイナリを構築すると、識別情報を追加して長期にわたるビルドの追跡に役立つため、監視、ロギング、およびデバッグプロセスが向上します。 このバージョン情報には、ビルド時間、バイナリをビルドするマシンまたはユーザー、https://www.atlassian.com/git/tutorials/what-is-version-control [バージョン管理システム( VCS)]ビルド対象のIDなど。 これらの値は絶えず変化するため、このデータをソースコードに直接コーディングし、新しいビルドがすべて面倒でエラーが発生する前に変更するため、ソースファイルは移動でき、https://www.digitalocean.com/community/tutorials/how -to-use-variables-and-in-go [variables / constants]は、開発プロセス全体でファイルを切り替え、ビルドプロセスを中断する場合があります。

Goでこれを解決する1つの方法は、ソースコードを変更せずに、ビルド時にバイナリに動的情報を挿入するために、「+ go build」コマンドで「+ -ldflags」を使用することです。 このフラグでは、「+ ld 」はhttps://en.wikipedia.org/wiki/Linker_(computing)[_linker_]を表します。これは、コンパイルされたソースコードのさまざまな部分を最終的なバイナリにリンクするプログラムです。 ` ldflags `は、_linker flags_を表します。 基礎となるGoツールチェーンリンカーhttps://golang.org/cmd/link [` cmd / link +`]にフラグを渡すため、これが呼び出されます。これにより、ビルド時にインポートされたパッケージの値を変更できます。コマンドライン。

このチュートリアルでは、ビルド時に変数の値を変更するために `+ -ldflags +`を使用し、バージョン情報を画面に出力するサンプルアプリケーションを使用して、独自の動的情報をバイナリに導入します。

前提条件

この記事の例を実行するには、次のものが必要です。

  • Goのインストール方法に従ってセットアップされたGoワークスペースローカルプログラミング環境のセットアップ]。

サンプルアプリケーションの構築

`+ ldflags +`を使用して動的データを導入する前に、まず情報を挿入するアプリケーションが必要です。 このステップでは、このアプリケーションを作成します。このアプリケーションは、この段階では静的バージョン情報のみを印刷します。 それでは、そのアプリケーションを作成しましょう。

`+ src `ディレクトリで、アプリケーションにちなんだ名前のディレクトリを作成します。 このチュートリアルでは、アプリケーション名「+」を使用します。

mkdir

作業ディレクトリを次のフォルダーに変更します。

cd

次に、選択したテキストエディターを使用して、プログラムのエントリポイント `+ main.go +`を作成します。

nano main.go

次に、次の内容を追加して、アプリケーションにバージョン情報を出力させます。

app / main.go

package main

import (
   "fmt"
)

var Version = "development"

func main() {
   fmt.Println("Version:\t", Version)
}

+ main()+`関数の内部で、 `+ Version +`変数を宣言し、https://www.digitalocean.com/community/tutorials/an-introduction-to-working-with-strings- in-go [string] `+ Version:+、タブ文字、 + \ t +、そして宣​​言された変数が続きます。

この時点で、変数 `+ Version `は ` development +`として定義され、このアプリのデフォルトバージョンになります。 後で、この値をhttps://semver.org/[semantic versioning format]に従って配置された公式のバージョン番号に変更します。

ファイルを保存して終了します。 これが完了したら、アプリケーションをビルドして実行し、正しいバージョンが印刷されることを確認します。

go build
./

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

OutputVersion:     development

これで、デフォルトのバージョン情報を出力するアプリケーションができましたが、ビルド時に現在のバージョン情報を渡す方法はまだありません。 次のステップでは、「-ldflags」と「 go build」を使用してこの問題を解決します。

+ go build`で + ldflags`を使用する

前に述べたように、 `+ ldflags +`は_linker flags_を表し、Goツールチェーンの基礎となるリンカーにフラグを渡すために使用されます。 これは、次の構文に従って機能します。

go build -ldflags="-"

この例では、 `+ go build `の一部として実行される、基礎となる ` go tool link `コマンドに ` flag `を渡しました。 このコマンドは、 ` ldflags `に渡されるコンテンツを二重引用符で囲み、その中の文字、またはコマンドラインが必要なもの以外として解釈する可能性のある文字を壊さないようにします。 ここから、https://golang.org/cmd/link/ [多くの異なる ` link `フラグ]を渡すことができます。 このチュートリアルの目的のために、リンク時に変数に情報を書き込むために ` -X +`フラグを使用し、その後にhttps://www.digitalocean.com/community/tutorials/importing-packages-in-を続けます。 go [package]変数とその新しい値へのパス:

go build -ldflags="-X '.='"

引用符の中に、「-X +」オプションとhttps://www.digitalocean.com/community/tutorials/understanding-maps-in-go#keys-and-values[key-value pair]があります。変更する変数とその新しい値を表します。 `。+`文字はパッケージパスと変数名を区切り、キーと値のペアの文字が壊れないように一重引用符が使用されます。

サンプルアプリケーションの `+ Version +`変数を置き換えるには、最後のコマンドブロックの構文を使用して新しい値を渡し、新しいバイナリをビルドします。

go build -ldflags="-X 'main.Version=v1.0.0'"

このコマンドでは、 `+ main `は ` Version `変数のパッケージパスです。この変数は ` main.go `ファイルにあるためです。 ` Version `は書き込み先の変数で、 ` v1.0.0 +`は新しい値です。

+ ldflags +`を使用するには、変更する値が存在し、 `+ string +`型のパッケージレベル変数である必要があります。 この変数はエクスポートまたはアンエクスポートできます。 値は「+ const +」にすることも、関数呼び出しの結果によって値を設定することもできません。 幸いなことに、 `+ Version +`はこれらの要件のすべてに適合します:すでに `+ main.go +`ファイルで変数として宣言されており、現在の値( `+ development +)と目的の値( `+ v1.0.0 + `)は両方とも文字列です。

新しい `++`バイナリが構築されたら、アプリケーションを実行します。

./

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

OutputVersion:

「+ -ldflags」を使用して、「+ Version 」変数を「 development 」から「 v1.0.0 +」に正常に変更しました。

これで、ビルド時に単純なアプリケーション内で変数「+ string」を変更しました。 `+ ldflags +`を使用すると、コマンドラインのみを使用して、配布の準備ができたバイナリにバージョンの詳細、ライセンス情報などを埋め込むことができます。

この例では、変更した変数は `+ main +`プログラムにあり、パス名を決定する難しさを軽減しています。 ただし、これらの変数へのパスを見つけるのがより複雑な場合があります。 次のステップでは、サブパッケージの変数に値を書き込み、より複雑なパッケージパスを決定する最適な方法を示します。

サブパッケージ変数のターゲティング

最後のセクションでは、アプリケーションのトップレベルパッケージにある `+ Version `変数を操作しました。 しかし、これは常にそうではありません。 ` main `はインポート可能なパッケージではないため、多くの場合、これらの変数を別のパッケージに配置する方が実用的です。 サンプルアプリケーションでこれをシミュレートするために、バイナリがビルドされた時間とビルドコマンドを発行したユーザーの名前に関する情報を保存する新しいサブパッケージ ` / build +`を作成します。

新しいサブパッケージを追加するには、まず、 `+ build +`という名前のプロジェクトに新しいディレクトリを追加します。

mkdir -p build

次に、新しい変数を保持するために、 `+ build.go +`という名前の新しいファイルを作成します。

nano build/build.go

テキストエディターで、 + Time`および + User N`の新しい変数を追加します。

app / build / build.go

package build

var Time string

var User string

`+ Time `変数は、バイナリが構築された時刻の文字列表現を保持します。 ` User `変数は、バイナリをビルドしたユーザーの名前を保持します。 これらの2つの変数には常に値があるため、 ` Version +`の場合のようにこれらの変数をデフォルト値で初期化する必要はありません。

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

次に、 `+ main.go +`を開いてこれらの変数をアプリケーションに追加します。

nano main.go

`+ main.go +`の内部に、次の強調表示された行を追加します。

main.go

package main

import (

   "fmt"
)

var Version = "development"

func main() {
   fmt.Println("Version:\t", Version)


}

これらの行では、最初に + / build`パッケージをインポートし、次に + Version + を印刷したのと同じ方法で + build.Time`と `+ build.User N`を印刷しました。

ファイルを保存し、テキストエディターを終了します。

次に、これらの変数を + ldflags`でターゲットにするには、インポートパスを既に知っているので、インポートパス + / build`の後に `+ .User `または ` .Time `を使用できます。 ただし、変数へのパスが明らかでないより複雑な状況をシミュレートするには、代わりにGoツールチェーンで「 nm +」コマンドを使用します。

`+ go tool nm `コマンドは、指定された実行可能ファイル、オブジェクトファイル、またはアーカイブに含まれる_symbols_を出力します。 この場合、シンボルは、定義またはインポートされた変数や関数など、コード内のオブジェクトを指します。 ` nm `でシンボルテーブルを生成し、 ` grep +`を使用して変数を検索することにより、そのパスに関する情報をすばやく見つけることができます。

このコマンドを使用するには、最初に `++`のバイナリをビルドします。

go build

「+」が作成されたので、「 nm +」ツールをポイントして、出力を検索します。

go tool nm ./ | grep

実行すると、 `+ nm `ツールは大量のデータを出力します。 このため、前述のコマンドは出力を「 | 」を使用して「 grep 」コマンドにパイプし、タイトルにトップレベルの「+」を含む用語を検索しました。

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

Output

 4069a0 T runtime.appendIntStr
 462580 T strconv.appendEscapedRune
. . .

この場合、結果セットの最初の2行には、探している2つの変数へのパスが含まれています: + / build.Time +`と `+ / build.User +

パスがわかったので、アプリケーションを再度ビルドします。今回はビルド時に + Version、` + User`、および `+ Time `を変更します。 これを行うには、複数の ` -X `フラグを ` -ldflags +`に渡します。

go build -v -ldflags="-X 'main.Version=v1.0.0' -X 'app/build.User=$(id -u -n)' -X 'app/build.Time=$(date)'"

ここでは、現在のユーザーをリストするためのBashコマンド `+ id -u -n `と、現在の日付をリストするための ` date +`コマンドを渡しました。

実行可能ファイルがビルドされたら、プログラムを実行します。

./

このコマンドをUnixシステムで実行すると、次と同様の出力が生成されます。

OutputVersion:     v1.0.0
build.Time:
build.User:

これで、バージョン管理とビルド情報を含むバイナリが作成され、問題を解決するときに本番環境で重要な支援を提供できます。

結論

このチュートリアルは、正しく適用されたときに、ビルド時に貴重な情報をバイナリに注入するための強力なツールである「+ ldflags 」を示しました。 これにより、ソースコードに変更を加えることなく、機能フラグ、環境情報、バージョン情報などを制御できます。 現在のビルドワークフローに「 ldflags +」を追加することで、Goの自己完結型バイナリ配布形式の利点を最大限に活用できます。

Goプログラミング言語について詳しく知りたい場合は、https://www.digitalocean.com/community/tutorial_series/how-to-code-in-go [Goのコーディング方法]をご覧ください。 バージョン管理のソリューションをさらにお探しの場合は、https://www.digitalocean.com/community/tutorials/how-to-use-git-a-reference-guide [Gitの使用方法]リファレンスガイドをお試しください。