さまざまなオペレーティングシステムとアーキテクチャ向けのGoアプリケーションの構築

提供:Dev Guides
移動先:案内検索

ソフトウェア開発では、バイナリをコンパイルするオペレーティングシステムと基盤となるプロセッサアーキテクチャを考慮することが重要です。 異なるOS/アーキテクチャプラットフォームでバイナリを実行するのは遅いか不可能であることが多いため、プログラムの対象者を最大化するために、多くの異なるプラットフォーム用に最終的なバイナリを構築するのが一般的な方法です。 ただし、開発に使用しているプラットフォームが、プログラムを展開するプラットフォームと異なる場合、これは難しい場合があります。 たとえば、これまでは、Windowsでプログラムを開発し、それをLinuxまたはmacOSマシンにデプロイするには、バイナリが必要な環境ごとにビルドマシンをセットアップする必要がありました。 また、コストを追加し、共同テストと配布をより困難にする他の考慮事項に加えて、ツールの同期を維持する必要があります。

Goは、複数のプラットフォームのサポートをgo buildツールと、残りのGoツールチェーンに直接組み込むことでこの問題を解決します。 環境変数およびビルドタグを使用することで、プラットフォームの包含をすばやく切り替えることができるワークフローをまとめるだけでなく、最終的なバイナリを構築するOSとアーキテクチャを制御できます。コードベースを変更せずに依存するコード。

このチュートリアルでは、文字列をファイルパスに結合するサンプルアプリケーションをまとめ、プラットフォームに依存するスニペットを作成して選択的に含め、独自のシステムで複数のオペレーティングシステムとシステムアーキテクチャのバイナリを構築します。 Goプログラミング言語のこの強力な機能を使用する方法を説明します。

前提条件

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

GOOSおよびGOARCHの可能なプラットフォーム

ビルドプロセスを制御してさまざまなプラットフォームのバイナリをビルドする方法を示す前に、まずGoがビルドできるプラットフォームの種類と、環境変数GOOSおよび[を使用してGoがこれらのプラットフォームを参照する方法を調べます。 X254X]。

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では、これらのオペレーティングシステムは、Goオペレーティングシステムを表す「goose」と発音される環境変数GOOSの可能な値です。 /に続く2番目の部分は、アーキテクチャです。 前と同じように、これらはすべて環境変数の可能な値です:GOARCH。 これは「gore-ch」と発音され、 GoArchitectureの略です。

linux/386を例として使用して、これらの組み合わせの1つを分解して、それが何を意味し、どのように機能するかを理解しましょう。 キーと値のペアはGOOSで始まります。この例では、 LinuxOSを参照してlinuxになります。 ここでのGOARCHは、386であり、Intel80386マイクロプロセッサの略です。

go buildコマンドで使用できるプラットフォームはたくさんありますが、ほとんどの場合、linuxwindows、またはdarwinGOOSの値。 これらは、 LinuxWindows 、およびDarwinオペレーティングシステムに基づくmacOSの3つの大きなOSプラットフォームをカバーしています。 darwinと呼ばれます。 ただし、Goは、Googleのネイティブクライアントを表すnaclのようなあまり主流ではないプラットフォームもカバーできます。

go buildのようなコマンドを実行すると、Goは現在のプラットフォームのGOOSおよびGOARCHを使用して、バイナリの構築方法を決定します。 プラットフォームの組み合わせを確認するには、go envコマンドを使用して、GOOSGOARCHを引数として渡します。

go env GOOS GOARCH

この例のテストでは、 AMD64アーキテクチャを搭載したマシンのmacOSでこのコマンドを実行したため、次の出力が表示されます。

Outputdarwin
amd64

ここで、コマンドの出力は、システムにGOOS=darwinGOARCH=amd64があることを示しています。

これで、GOOSGOARCHがGoに含まれていることと、それらの可能な値がわかりました。 次に、これらの環境変数を使用してタグを作成し、他のプラットフォームのバイナリを作成する方法の例として使用するプログラムをまとめます。

filepath.Join()を使用してプラットフォーム依存プログラムを作成する

他のプラットフォーム用のバイナリの作成を開始する前に、サンプルプログラムを作成しましょう。 この目的に適したサンプルは、Go標準ライブラリの path /filepathパッケージのJoin関数です。 この関数はいくつかの文字列を受け取り、正しいファイルパス区切り文字で結合された1つの文字列を返します。

プログラムの動作は、実行しているOSに依存するため、これは良いサンプルプログラムです。 Windowsでは、パス区切り文字は円記号\ですが、Unixベースのシステムは円記号/を使用します。

filepath.Join()を使用するアプリケーションの構築から始めましょう。その後、プラットフォーム固有のバイナリに合わせてコードをカスタマイズするJoin()関数の独自の実装を作成します。

まず、srcディレクトリにアプリの名前でフォルダを作成します。

mkdir app

そのディレクトリに移動します。

cd app

次に、選択したテキストエディタでmain.goという名前の新しいファイルを作成します。 このチュートリアルでは、Nanoを使用します。

nano main.go

ファイルが開いたら、次のコードを追加します。

src / app / main.go

package main

import (
  "fmt"
  "path/filepath"
)

func main() {
  s := filepath.Join("a", "b", "c")
  fmt.Println(s)
}

このファイルのmain()関数は、filepath.Join()を使用して、プラットフォームに依存する正しいパス区切り文字とともに3つの文字列を連結します。

ファイルを保存して終了し、プログラムを実行します。

go run main.go

このプログラムを実行すると、使用しているプラットフォームに応じて異なる出力を受け取ります。 Windowsでは、\で区切られた文字列が表示されます。

Outputa\b\c

macOSやLinuxなどのUnixシステムでは、次のものを受け取ります。

Outputa/b/c

これは、これらのオペレーティングシステムで使用されるファイルシステムプロトコルが異なるため、プログラムがプラットフォームごとに異なるコードを作成する必要があることを示しています。 ただし、OSによってはすでに異なるファイルセパレータを使用しているため、filepath.Join()がプラットフォームの違いをすでに説明していることがわかります。 これは、GoツールチェーンがマシンのGOOSGOARCHを自動的に検出し、この情報を使用して、適切なビルドタグとファイルセパレーターを含むコードスニペットを使用するためです。

filepath.Join()関数がセパレーターをどこから取得するかを考えてみましょう。 次のコマンドを実行して、Goの標準ライブラリから関連するスニペットを調べます。

less /usr/local/go/src/os/path_unix.go

path_unix.goの内容が表示されます。 ファイルの次の部分を探します。

/usr/local/go/os/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
)
. . .

このセクションでは、Goがサポートするすべての種類のUnixライクなシステムのPathSeparatorを定義します。 上部にあるすべてのビルドタグに注目してください。これらはそれぞれ、Unixに関連付けられている可能性のあるUnixGOOSプラットフォームの1つです。 GOOSがこれらの用語に一致する場合、プログラムはUnixスタイルのファイルパスセパレーターを生成します。

qを押してコマンドラインに戻ります。

次に、Windowsで使用した場合のfilepath.Join()の動作を定義するファイルを開きます。

less /usr/local/go/src/os/path_windows.go

次のように表示されます。

/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ファイルとは異なり、上部にビルドタグがないことに注意してください。 これは、ファイル名にアンダースコア(_)と環境変数値を接尾辞として追加することで、GOOSGOARCHgo buildに渡すこともできるためです。 、セクションGOOSおよびGOARCHファイル名サフィックスの使用で詳しく説明します。 ここで、path_windows.go_windows部分は、ファイルの先頭にビルドタグ// +build windowsがあるかのようにファイルを動作させます。 このため、プログラムをWindowsで実行すると、path_windows.goコードスニペットのPathSeparatorおよびPathListSeparatorの定数が使用されます。

コマンドラインに戻るには、qを押してlessを終了します。

このステップでは、GoがGOOSGOARCHをビルドタグに自動的に変換する方法を示すプログラムをビルドしました。 これを念頭に置いて、ビルドタグを使用してWindowsおよびUnixプラットフォーム用の正しいPathSeparatorを手動で設定し、プログラムを更新してfilepath.Join()の独自の実装を作成できるようになりました。

プラットフォーム固有の機能の実装

Goの標準ライブラリがプラットフォーム固有のコードを実装する方法がわかったので、ビルドタグを使用して独自のappプログラムでこれを行うことができます。 これを行うには、filepath.Join()の独自の実装を作成します。

main.goファイルを開きます。

nano main.go

Join()という独自の関数を使用して、main.goの内容を次のように置き換えます。

src / app / main.go

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)
}

Join関数は、いくつかのpartsを受け取り、文字列パッケージstrings.Join()メソッドを使用してそれらを結合し、[ partsを一緒にPathSeparatorを使用します。

PathSeparatorはまだ定義していないので、別のファイルで定義してください。 main.goを保存して終了し、お気に入りのエディターを開いて、path.goという名前の新しいファイルを作成します。

nano path.go

PathSeparatorを定義し、Unixファイルパスセパレーター/と同じに設定します。

src / app / path.go

package main

const PathSeparator = "/"

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

go build
./app

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

Outputa/b/c

これは正常に実行され、Unixスタイルのファイルパスを取得します。 しかし、これはまだ私たちが望んでいることではありません。出力は、実行されているプラットフォームに関係なく、常にa/b/cです。 Windowsスタイルのファイルパスを作成する機能を追加するには、WindowsバージョンのPathSeparatorを追加し、go buildコマンドに使用するバージョンを指示する必要があります。 次のセクションでは、ビルドタグを使用してこれを実現します。

GOOSまたはGOARCHビルドタグの使用

Windowsプラットフォームを説明するために、path.goの代替ファイルを作成し、ビルドタグを使用して、GOOSGOARCHが適切なプラットフォームである場合にのみコードスニペットが実行されるようにします。 。

ただし、最初に、ビルドタグをpath.goに追加して、Windowsを除くすべてのビルド用にビルドするように指示します。 ファイルを開きます。

nano path.go

次の強調表示されたビルドタグをファイルに追加します。

src / app / path.go

// +build !windows

package main

const PathSeparator = "/"

Goビルドタグでは反転が可能です。つまり、Windowsを除くすべてのプラットフォームでこのファイルをビルドするようにGoに指示できます。 ビルドタグを反転するには、タグの前に!を配置します。

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

ここで、このプログラムをWindowsで実行すると、次のエラーが発生します。

Output./main.go:9:29: undefined: PathSeparator

この場合、Goは変数PathSeparatorを定義するためにpath.goを含めることができません。

GOOSがWindowsの場合、path.goが実行されないことを確認したので、新しいファイルwindows.goを追加します。

nano windows.go

windows.goで、Windows PathSeparatorと、go buildコマンドにWindowsの実装であることを知らせるビルドタグを定義します。

src / app / windows.go

// +build windows

package main

const PathSeparator = "\\"

ファイルを保存して、テキストエディタを終了します。 これで、アプリケーションはWindows用に1つの方法でコンパイルでき、他のすべてのプラットフォーム用に別の方法でコンパイルできます。

バイナリはプラットフォーム用に正しくビルドされるようになりましたが、アクセスできないプラットフォーム用にコンパイルするには、さらに変更を加える必要があります。 これを行うには、次の手順でローカルのGOOSおよびGOARCH環境変数を変更します。

ローカルのGOOSおよびGOARCH環境変数の使用

以前、go env GOOS GOARCHコマンドを実行して、作業しているOSとアーキテクチャを確認しました。 go envコマンドを実行すると、2つの環境変数GOOSGOARCHが検索されました。 見つかった場合はそれらの値が使用されますが、見つからなかった場合はGoが現在のプラットフォームの情報を設定します。 これは、GOOSまたはGOARCHを変更して、ローカルOSおよびアーキテクチャがデフォルトにならないようにすることができることを意味します。

go buildコマンドは、go envコマンドと同じように動作します。 GOOSまたはGOARCH環境変数を設定して、go buildを使用して別のプラットフォーム用に構築できます。

Windowsシステムを使用していない場合は、[の実行時にGOOS環境変数をwindowsに設定して、appwindowsバイナリを作成します。 X157X]コマンド:

GOOS=windows go build

次に、現在のディレクトリ内のファイルを一覧表示します。

ls

ディレクトリを一覧表示する出力は、プロジェクトディレクトリにapp.exeWindows実行可能ファイルがあることを示しています。

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ライクなプラットフォームと見なされるすべての可能な組み合わせをリストしたビルドタグがありました。 ただし、os/path_windows.goファイルにはビルドタグが含まれていませんでした。これは、ファイル名のサフィックスが、ファイルの対象となるプラットフォームをGoに伝えるのに十分だったためです。

この機能の構文を見てみましょう。 .goファイルに名前を付けるときは、ファイル名にGOOSGOARCHをこの順序でサフィックスとして追加し、値をアンダースコア(_)で区切ることができます。 。 filename.goという名前のGoファイルがある場合は、ファイル名をfilename_GOOS_GOARCH.goに変更することで、OSとアーキテクチャを指定できます。 たとえば、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を削除して、ファイルが次のようになるようにします。

path_windows.go

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シリーズのコーディング方法全体を確認してください。