さまざまなオペレーティングシステムとアーキテクチャ向けのGoアプリケーションの構築
ソフトウェア開発では、バイナリをコンパイルするオペレーティングシステムと基盤となるプロセッサアーキテクチャを考慮することが重要です。 異なるOS/アーキテクチャプラットフォームでバイナリを実行するのは遅いか不可能であることが多いため、プログラムの対象者を最大化するために、多くの異なるプラットフォーム用に最終的なバイナリを構築するのが一般的な方法です。 ただし、開発に使用しているプラットフォームが、プログラムを展開するプラットフォームと異なる場合、これは難しい場合があります。 たとえば、これまでは、Windowsでプログラムを開発し、それをLinuxまたはmacOSマシンにデプロイするには、バイナリが必要な環境ごとにビルドマシンをセットアップする必要がありました。 また、コストを追加し、共同テストと配布をより困難にする他の考慮事項に加えて、ツールの同期を維持する必要があります。
Goは、複数のプラットフォームのサポートを直接に組み込むことで、この問題を解決します。 go build
ツール、およびGoツールチェーンの残りの部分。 環境変数およびビルドタグを使用することで、プラットフォームの包含をすばやく切り替えることができるワークフローをまとめるだけでなく、最終的なバイナリを構築するOSとアーキテクチャを制御できます。コードベースを変更せずに依存するコード。
このチュートリアルでは、文字列をファイルパスに結合するサンプルアプリケーションをまとめ、プラットフォームに依存するスニペットを作成して選択的に含め、独自のシステムで複数のオペレーティングシステムとシステムアーキテクチャのバイナリを構築します。 Goプログラミング言語のこの強力な機能を使用する方法を説明します。
前提条件
この記事の例に従うには、次のものが必要です。
- Goのインストール方法とローカルプログラミング環境のセットアップに従ってセットアップされたGoワークスペース。
可能なプラットフォーム GOOS
と GOARCH
ビルドプロセスを制御してさまざまなプラットフォームのバイナリをビルドする方法を示す前に、まずGoがビルドできるプラットフォームの種類と、Goが環境変数を使用してこれらのプラットフォームを参照する方法を調べてみましょう。 GOOS
と GOARCH
.
Goツールには、Goが構築できる可能なプラットフォームのリストを印刷できるコマンドがあります。 このリストは、新しいGoのリリースごとに変更される可能性があるため、ここで説明する組み合わせは、別のバージョンのGoでは同じではない場合があります。 このチュートリアルを書いている時点で、現在のGoリリースは1.13です。
可能なプラットフォームのこのリストを見つけるには、以下を実行します。
- go tool dist list
次のような出力が表示されます。
Outputaix/ppc64 freebsd/amd64 linux/mipsle openbsd/386
android/386 freebsd/arm linux/ppc64 openbsd/amd64
android/amd64 illumos/amd64 linux/ppc64le openbsd/arm
android/arm js/wasm linux/s390x openbsd/arm64
android/arm64 linux/386 nacl/386 plan9/386
darwin/386 linux/amd64 nacl/amd64p32 plan9/amd64
darwin/amd64 linux/arm nacl/arm plan9/arm
darwin/arm linux/arm64 netbsd/386 solaris/amd64
darwin/arm64 linux/mips netbsd/amd64 windows/386
dragonfly/amd64 linux/mips64 netbsd/arm windows/amd64
freebsd/386 linux/mips64le netbsd/arm64 windows/arm
この出力は、キーと値のペアのセットであり、 /
. 組み合わせの最初の部分、前 /
、はオペレーティングシステムです。 Goでは、これらのオペレーティングシステムは環境変数の可能な値です GOOS
、「goose」と発音します。これは、 Go OperatingSystemの略です。 後の2番目の部分 /
、はアーキテクチャです。 前と同じように、これらはすべて環境変数の可能な値です。 GOARCH
. これは「gore-ch」と発音され、 GoArchitectureの略です。
これらの組み合わせの1つを分解して、それが何を意味し、どのように機能するかを理解しましょう。 linux/386
例として。 キーと値のペアは、 GOOS
、この例では linux
、 LinuxOSを参照してください。 The GOARCH
ここになります 386
、Intel80386マイクロプロセッサの略です。
で利用可能な多くのプラットフォームがあります go build
コマンドですが、ほとんどの場合、使用することになります linux
, windows
、 また darwin
の値として GOOS
. これらは、 Linux 、 Windows 、およびDarwinオペレーティングシステムに基づくmacOSの3つの大きなOSプラットフォームをカバーしています。と呼ばれる darwin
. ただし、Goは、次のような主流ではないプラットフォームもカバーできます。 nacl
、Googleのネイティブクライアントを表します。
次のようなコマンドを実行すると go build
、Goは現在のプラットフォームを使用します GOOS
と GOARCH
バイナリの構築方法を決定します。 プラットフォームの組み合わせを確認するには、 go env
コマンドとパス GOOS
と GOARCH
引数として:
- go env GOOS GOARCH
この例のテストでは、 AMD64アーキテクチャを搭載したマシンのmacOSでこのコマンドを実行したため、次の出力が表示されます。
Outputdarwin
amd64
ここで、コマンドの出力は、私たちのシステムが持っていることを示しています GOOS=darwin
と GOARCH=amd64
.
あなたは今何を知っています GOOS
と GOARCH
Goにあり、それらの可能な値も同様です。 次に、これらの環境変数を使用してタグを作成し、他のプラットフォームのバイナリを作成する方法の例として使用するプログラムをまとめます。
プラットフォームに依存するプログラムを作成する filepath.Join()
他のプラットフォーム用のバイナリの作成を開始する前に、サンプルプログラムを作成しましょう。 この目的のための良いサンプルは Join
Go標準ライブラリのpath/filepathパッケージの関数。 この関数はいくつかの文字列を受け取り、正しいファイルパス区切り文字で結合された1つの文字列を返します。
プログラムの動作は、実行しているOSに依存するため、これは良いサンプルプログラムです。 Windowsでは、パス区切り文字は円記号です。 \
、Unixベースのシステムはスラッシュを使用しますが、 /
.
を使用するアプリケーションの構築から始めましょう filepath.Join()
、および後で、独自の実装を作成します Join()
プラットフォーム固有のバイナリにコードをカスタマイズする関数。
まず、にフォルダを作成します src
アプリの名前のディレクトリ:
- mkdir app
そのディレクトリに移動します。
- cd app
次に、選択したテキストエディタで名前の付いた新しいファイルを作成します main.go
. このチュートリアルでは、Nanoを使用します。
- nano main.go
ファイルが開いたら、次のコードを追加します。
package main
import (
"fmt"
"path/filepath"
)
func main() {
s := filepath.Join("a", "b", "c")
fmt.Println(s)
}
The main()
このファイルの関数は filepath.Join()
3つの文字列を、プラットフォームに依存する正しいパス区切り文字と連結します。
ファイルを保存して終了し、プログラムを実行します。
- go run main.go
このプログラムを実行すると、使用しているプラットフォームに応じて異なる出力を受け取ります。 Windowsでは、文字列はで区切られています \
:
Outputa\b\c
macOSやLinuxなどのUnixシステムでは、次のものを受け取ります。
Outputa/b/c
これは、これらのオペレーティングシステムで使用されるファイルシステムプロトコルが異なるため、プログラムがプラットフォームごとに異なるコードを作成する必要があることを示しています。 ただし、OSによってはすでに異なるファイルセパレータを使用しているため、 filepath.Join()
すでにプラットフォームの違いを説明しています。 これは、Goツールチェーンがマシンのを自動的に検出するためです。 GOOS
と GOARCH
この情報を使用して、適切なビルドタグとファイルセパレータを備えたコードスニペットを使用します。
どこで filepath.Join()
関数はからセパレータを取得します。 次のコマンドを実行して、Goの標準ライブラリから関連するスニペットを調べます。
- less /usr/local/go/src/os/path_unix.go
これにより、の内容が表示されます path_unix.go
. ファイルの次の部分を探します。
. . .
// +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
package os
const (
PathSeparator = '/' // OS-specific path separator
PathListSeparator = ':' // OS-specific path list separator
)
. . .
このセクションでは、 PathSeparator
Goがサポートするあらゆる種類のUnixライクなシステムに対応します。 上部にあるすべてのビルドタグに注目してください。これらはそれぞれ、可能なUnixの1つです。 GOOS
Unixに関連するプラットフォーム。 いつ GOOS
これらの用語に一致すると、プログラムはUnixスタイルのファイルパスセパレータを生成します。
プレス q
コマンドラインに戻ります。
次に、の動作を定義するファイルを開きます filepath.Join()
Windowsで使用する場合:
- less /usr/local/go/src/os/path_windows.go
次のように表示されます。
. . .
package os
const (
PathSeparator = '\\' // OS-specific path separator
PathListSeparator = ';' // OS-specific path list separator
)
. . .
の値が PathSeparator
は \\
ここでは、コードは単一の円記号をレンダリングします(\
)最初の円記号はエスケープ文字としてのみ必要なため、Windowsファイルパスに必要です。
Unixファイルとは異なり、上部にビルドタグがないことに注意してください。 それの訳は GOOS
と GOARCH
に渡すこともできます go build
アンダースコアを追加する(_
)およびファイル名のサフィックスとしての環境変数値については、GOOSおよびGOARCHファイル名のサフィックスの使用のセクションで詳しく説明します。 ここでは、 _windows
一部の path_windows.go
ファイルにビルドタグがあるかのように動作させます // +build windows
ファイルの先頭にあります。 このため、プログラムをWindowsで実行すると、次の定数が使用されます。 PathSeparator
と PathListSeparator
から path_windows.go
コードスニペット。
コマンドラインに戻るには、終了します less
を押すことによって q
.
このステップでは、Goがどのように変換するかを示すプログラムを作成しました GOOS
と GOARCH
ビルドタグに自動的に。 これを念頭に置いて、プログラムを更新し、独自の実装を作成できるようになりました。 filepath.Join()
、ビルドタグを使用して手動で正しい設定を行う PathSeparator
WindowsおよびUnixプラットフォーム用。
プラットフォーム固有の機能の実装
Goの標準ライブラリがプラットフォーム固有のコードを実装する方法がわかったので、ビルドタグを使用して独自にこれを行うことができます app
プログラム。 これを行うには、独自の実装を作成します filepath.Join()
.
あなたの main.go
ファイル:
- nano main.go
の内容を置き換えます main.go
次のように、と呼ばれる独自の関数を使用して Join()
:
package main
import (
"fmt"
"strings"
)
func Join(parts ...string) string {
return strings.Join(parts, PathSeparator)
}
func main() {
s := Join("a", "b", "c")
fmt.Println(s)
}
The Join
関数はいくつかを取ります parts
文字列パッケージのstrings.Join()メソッドを使用してそれらを結合し、 parts
一緒に使用して PathSeparator
.
あなたは定義していません PathSeparator
それでも、別のファイルでそれを実行してください。 保存して終了します main.go
、お気に入りのエディタを開き、という名前の新しいファイルを作成します path.go
:
nano path.go
を定義する PathSeparator
Unixファイルパスセパレータと同じに設定します。 /
:
package main
const PathSeparator = "/"
アプリケーションをコンパイルして実行します。
- go build
- ./app
次の出力が表示されます。
Outputa/b/c
これは正常に実行され、Unixスタイルのファイルパスを取得します。 しかし、これはまだ私たちが望んでいることではありません。出力は常に a/b/c
、実行するプラットフォームに関係なく。 Windowsスタイルのファイルパスを作成する機能を追加するには、Windowsバージョンの PathSeparator
と言う go build
使用するバージョンをコマンドします。 次のセクションでは、ビルドタグを使用してこれを実現します。
使用する GOOS
また GOARCH
タグを作成する
Windowsプラットフォームを説明するために、次の代替ファイルを作成します。 path.go
ビルドタグを使用して、コードスニペットが次の場合にのみ実行されるようにします GOOS
と GOARCH
適切なプラットフォームです。
ただし、最初にビルドタグをに追加します path.go
Windows以外のすべてのためにビルドするように指示します。 ファイルを開きます。
- nano path.go
次の強調表示されたビルドタグをファイルに追加します。
// +build !windows
package main
const PathSeparator = "/"
Goビルドタグでは反転が可能です。つまり、Windowsを除くすべてのプラットフォームでこのファイルをビルドするようにGoに指示できます。 ビルドタグを反転するには、 !
タグの前。
ファイルを保存して終了します。
ここで、このプログラムをWindowsで実行すると、次のエラーが発生します。
Output./main.go:9:29: undefined: PathSeparator
この場合、Goは含めることができません path.go
変数を定義する PathSeparator
.
これで、次のことを確認できました path.go
次の場合は実行されません GOOS
Windowsの場合、新しいファイルを追加します。 windows.go
:
- nano windows.go
の windows.go
、Windowsを定義します PathSeparator
、およびビルドタグを使用して go build
コマンドはそれがWindowsの実装であることを知っています:
// +build windows
package main
const PathSeparator = "\\"
ファイルを保存して、テキストエディタを終了します。 これで、アプリケーションはWindows用に1つの方法でコンパイルでき、他のすべてのプラットフォーム用に別の方法でコンパイルできます。
バイナリはプラットフォーム用に正しくビルドされるようになりましたが、アクセスできないプラットフォーム用にコンパイルするには、さらに変更を加える必要があります。 これを行うには、ローカルを変更します GOOS
と GOARCH
次のステップの環境変数。
ローカルを使用する GOOS
と GOARCH
環境変数
以前、あなたは go env GOOS GOARCH
作業しているOSとアーキテクチャを確認するコマンド。 あなたが実行したとき go env
コマンド、それは2つの環境変数を探しました GOOS
と GOARCH
; 見つかった場合はそれらの値が使用されますが、見つからなかった場合はGoが現在のプラットフォームの情報を設定します。 これはあなたが変えることができることを意味します GOOS
また GOARCH
ローカルOSとアーキテクチャがデフォルトにならないようにします。
The go build
コマンドは、 go env
指図。 どちらかを設定できます GOOS
また GOARCH
を使用して別のプラットフォーム用に構築する環境変数 go build
.
Windowsシステムを使用していない場合は、 windows
のバイナリ app
を設定することによって GOOS
環境変数から windows
実行時 go build
指図:
- GOOS=windows go build
次に、現在のディレクトリ内のファイルを一覧表示します。
- ls
ディレクトリを一覧表示する出力は、現在、 app.exe
プロジェクトディレクトリ内のWindows実行可能ファイル:
Outputapp app.exe main.go path.go windows.go
を使用して file
コマンドを実行すると、このファイルに関する詳細情報を取得して、ビルドを確認できます。
- file app.exe
あなたは受け取るでしょう:
Outputapp.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows
ビルド時に一方または両方の環境変数を設定することもできます。 次を実行します。
- GOOS=linux GOARCH=ppc64 go build
君の app
実行可能ファイルは、別のアーキテクチャのファイルに置き換えられます。 を実行します file
このバイナリに対するコマンド:
- file app
次のような出力が表示されます。
app: ELF 64-bit MSB executable, 64-bit PowerPC or cisco 7500, version 1 (SYSV), statically linked, not stripped
あなたのローカルを設定することによって GOOS
と GOARCH
環境変数を使用すると、複雑な構成やセットアップを行うことなく、Goの互換性のあるプラットフォームのバイナリを構築できるようになります。 次に、ファイル名の規則を使用して、ファイルをきちんと整理し、ビルドタグなしで特定のプラットフォーム用に自動的にビルドします。
使用する GOOS
と GOARCH
ファイル名のサフィックス
前に見たように、Go標準ライブラリはビルドタグを多用して、さまざまなプラットフォーム実装をさまざまなファイルに分離することでコードを簡素化します。 あなたが開いたとき os/path_unix.go
ファイルには、Unixライクなプラットフォームと見なされるすべての可能な組み合わせをリストしたビルドタグがありました。 The os/path_windows.go
ただし、ファイルにはビルドタグが含まれていませんでした。これは、ファイル名のサフィックスが、ファイルの対象となるプラットフォームをGoに伝えるのに十分だったためです。
この機能の構文を見てみましょう。 名前を付けるとき .go
ファイル、追加できます GOOS
と GOARCH
この順序でファイル名のサフィックスとして、値をアンダースコアで区切ります(_
). 名前の付いたGoファイルがある場合 filename.go
、ファイル名を次のように変更することで、OSとアーキテクチャを指定できます。 filename_GOOS_GOARCH.go
. たとえば、64ビット ARMアーキテクチャを使用してWindows用にコンパイルする場合は、ファイルの名前を作成します。 filename_windows_arm64.go
. この命名規則は、コードをきちんと整理するのに役立ちます。
ビルドタグの代わりにファイル名のサフィックスを使用するようにプログラムを更新します。 まず、名前を変更します path.go
と windows.go
で使用される規則を使用するファイル os
パッケージ:
- mv path.go path_unix.go
- mv windows.go path_windows.go
2つのファイル名を変更すると、追加したビルドタグを削除できます path_windows.go
:
- nano path_windows.go
削除する // +build windows
ファイルが次のようになるようにします。
package main
const PathSeparator = "\\"
ファイルを保存して終了します。
なぜなら unix
は有効ではありません GOOS
、 _unix.go
接尾辞は、Goコンパイラには意味がありません。 ただし、ファイルの意図された目的を伝えます。 以下のような os/path_unix.go
ファイル、あなたの path_unix.go
ファイルは引き続きビルドタグを使用する必要があるため、そのファイルは変更しないでください。
ファイル名の規則を使用することで、ソースコードから不要なビルドタグを削除し、ファイルシステムをよりクリーンで明確にしました。
結論
依存関係を必要としない複数のプラットフォーム用のバイナリを生成する機能は、Goツールチェーンの強力な機能です。 このチュートリアルでは、ビルドタグとファイル名のサフィックスを追加してこの機能を使用し、特定のアーキテクチャでのみコンパイルする特定のコードスニペットをマークしました。 独自のplatorm依存プログラムを作成してから、 GOOS
と GOARCH
現在のプラットフォーム以外のプラットフォームのバイナリを生成するための環境変数。 これらの環境変数を自動的に実行してすべてのプラットフォームのバイナリを構築する継続的インテグレーションプロセスを使用するのが一般的な方法であるため、これは貴重なスキルです。
さらなる研究のために go build
、ビルドタグを使用したGoバイナリのカスタマイズチュートリアルをご覧ください。 Goプログラミング言語全般について詳しく知りたい場合は、Goシリーズのコーディング方法全体を確認してください。