パッケージについて
Go のパッケージは、他のプログラミング言語のライブラリやモジュールのようなものです。 コードをパッケージ化すれば、別の場所で再利用できます。 パッケージのソース コードは、複数の .go
ファイルで配布できます。 これまでは、main
パッケージを記述し、他のネイティブ パッケージをいくつか参照してきました。
このセクションでは、パッケージとは何かについて学びます。 その作成方法と外部パッケージの使用方法についても学びます。
メイン パッケージ
ご存知かもしれませんが、どんなに単純な Go のプログラムでもパッケージの一部でなければなりません。 通常、既定のパッケージは main
パッケージであり、これは今までに扱ってきたものです。 プログラムが main
パッケージの一部である場合、Go によってバイナリ ファイルが生成されます。 このファイルを実行すると、main()
関数が呼び出されます。
言い換えれば、main
パッケージを使用するときは、プログラムによってスタンドアロンの実行可能ファイルが生成されます。 しかし、プログラムが main
以外のパッケージの一部である場合、Go はバイナリ ファイルを生成しません。 パッケージ アーカイブ ファイル (.a
拡張子のファイル) が生成されます。
Go では、パッケージ名には規則があります。 パッケージでは、そのインポート パスの最後の部分が名前として使用されます。 たとえば、Go の標準ライブラリには、複雑な数値を操作する便利なコードがある math/cmplx
というパッケージが含まれています。 このパッケージのインポート パスは math/cmplx
で、これは次のようにインポートします。
import "math/cmplx"
このパッケージ内のオブジェクトを参照するには、cmplx
のようにパッケージ名を使用します。
cmplx.Inf()
パッケージを作成してみましょう。
パッケージを作成する
$GOPATH/src
内に calculator
という名前で新しいディレクトリを作成します。 sum.go
という名前でファイルを作成します。 ツリー ディレクトリは次のディレクトリのようになります。
src/
calculator/
sum.go
パッケージの名前で sum.go
ファイルを初期化します。
package calculator
パッケージの関数と変数を記述する準備ができました。 他のプログラミング言語と違って、Go には、変数または関数をパッケージの外または中のどちらから呼び出せるのかを示す public
または private
キーワードは用意されていません。 しかし、Go では 2 つの簡単な規則に従います。
- プライベートにする要素は、名前の先頭を小文字にします。
- パブリックにする要素は、名前の先頭を大文字にします。
それでは、作成中の calculator パッケージに次のコードを追加してみましょう。
package calculator
var logMessage = "[LOG]"
// Version of the calculator
var Version = "1.0"
func internalSum(number int) int {
return number - 1
}
// Sum two integer numbers
func Sum(number1, number2 int) int {
return number1 + number2
}
コード内のいくつかの点に注目してください。
logMessage
変数はパッケージの中からしか呼び出せません。Version
変数はどこからでもアクセスできます。 この変数の目的を説明したコメントを含めることをお勧めします。 (この説明はパッケージを使用するすべての人に役立ちます。)internalSum
関数はパッケージの中からしか呼び出せません。Sum
関数はどこからでもアクセスできます。 関数の目的を説明したコメントを含めることをお勧めします。
calculator
ディレクトリで go build
コマンドを実行して、何も問題がないことを確認します。 実行しても、実行可能バイナリは生成されないことに注意してください。
モジュールを作成する
パッケージに電卓機能を配置できました。 今度は、パッケージをモジュールに入れます。 Go のモジュールには、関連機能を提供するパッケージが通常含まれています。 パッケージのモジュールには、グループ化したコードを実行するために Go が必要なコンテキストも指定されています。 このコンテキスト情報には、コードを記述した対象の Go のバージョンが含まれます。
また、モジュールにより、他の開発者がコードの特定のバージョンを参照しやすくなり、依存関係の管理が容易になります。 もう 1 つの利点は、プログラムのソース コードが厳密に $GOPATH/src
ディレクトリに存在する必要がないことです。 この制限から解放されることで、さまざまなパッケージ バージョンを他のプロジェクトで同時に、より便利に扱えるようになります。
さて、calculator
パッケージのモジュールを作成するには、ルート ディレクトリ ($GOPATH/src/calculator
) で次のコマンドを実行します。
go mod init github.com/myuser/calculator
このコマンドを実行すると、github.com/myuser/calculator
がモジュール名になります。 他のプログラムで参照するには、この名前を使用します。 このコマンドにより、go.mod
という名前の新しいファイルも作成します。 最後に、ツリー ディレクトリは次のディレクトリのようになります。
src/
calculator/
go.mod
sum.go
go.mod
ファイルの内容は次のコードのようになります。 (Go バージョンは異なっている可能性があります。)
module github.com/myuser/calculator
go 1.14
他のプログラムでご自分の calculator
パッケージを参照するには、そのモジュール名を使用してインポートします。 この場合、名前は github.com/myuser/calculator
です。 では、このパッケージの使用方法の例を見てみましょう。
Note
歴史的に、Go での依存関係の管理は簡単ではありませんでした。 依存関係管理システムはまだ発展途上です。 モジュールについてさらに理解を深めるには、こちらの Go ブログで公開中の一連の記事をご覧ください。
ローカル パッケージ (モジュール) の参照
それでは、パッケージを使ってみましょう。 これまで扱ってきたサンプル アプリケーションの続きです。 今回は、sum
関数を main
パッケージに入れるのではなく、前に calculator
パッケージに作成したものを使ってみましょう。
ツリー ファイルの構造は次のようになります。
src/
calculator/
go.mod
sum.go
helloworld/
main.go
$GOPATH/src/helloworld/main.go
ファイルには次のコードを使用します。
package main
import (
"fmt"
"github.com/myuser/calculator"
)
func main() {
total := calculator.Sum(3, 5)
fmt.Println(total)
fmt.Println("Version: ", calculator.Version)
}
作成済みパッケージの名前 (calculator
) を import ステートメントで使用していることに注意してください。 そのパッケージから Sum
関数を呼び出すには、パッケージ名を calculator.Sum
のように含める必要があります。 最終的に、Version
変数にもアクセスできるようになりました。 calculator.Version
のように呼び出します。
ここでプログラムを実行しようとしても、動作しません。 モジュールを使用して他のパッケージを参照することを Go に知らせる必要があります。 これを行うには、$GOPATH/src/helloworld
ディレクトリで次のコマンドを実行します。
go mod init helloworld
前のコマンドでは、helloworld
はプロジェクトの名前です。 このコマンドにより新しい go.mod
ファイルが作成され、ツリー ディレクトリは次のようになります。
src/
calculator/
go.mod
sum.go
helloworld/
go.mod
main.go
go.mod
ファイルを開くと、次のコードのような内容があります。 (Go バージョンは異なっている可能性があります。)
module helloworld
go 1.14
モジュールのローカル コピーを参照しているので、リモートの場所を使用しないことを Go に知らせる必要があります。 そのため、次のように、go.mod
ファイルを手動で修正して参照を含める必要があります。
module helloworld
go 1.14
require github.com/myuser/calculator v0.0.0
replace github.com/myuser/calculator => ../calculator
replace
キーワードでは、モジュールのリモートの場所ではなくローカル ディレクトリを使用するように指定します。 この場合、helloworld
および calculator
プログラムは $GOPATH/src
にあるため、場所は単に ../calculator
となっています。 モジュールのソースが別の場所にある場合は、ここでローカル パスを定義します。
次のコマンドを使用してプログラムを実行します。
go run main.go
出力は次のようになります。
8
Version: 1.0
課題 1
main アプリケーションで calculator
パッケージの logMessage
変数または internalSum
関数を呼び出そうとするとどうなるでしょうか。 実行されるでしょうか。 試してみる
課題のソリューション:
package main import ( "fmt" "github.com/myuser/calculator" ) func main() { total := calculator.internalSum(5) fmt.Println(total) fmt.Println("Version: ", calculator.logMessage) }
パッケージの公開
Go パッケージの公開はごく簡単です。 必要なのは、パッケージのソース コードを公開することだけです。 ほとんどの開発者は GitHub を使用して、パッケージを一般公開します。そのため、import ステートメントで github.com
への参照が見つかる場合があります。
たとえば、calculator
パッケージを GitHub アカウントに公開する場合、calculator
という名前のリポジトリを作成する必要があります。 URL は次のようになります。
https://github.com/myuser/calculator
次のように、リポジトリにタグを付けてパッケージのバージョンを指定します。
git tag v0.1.0
git push origin v0.1.0
(自分も含め) このパッケージを使用する開発者は、次のようにして参照します。
import "github.com/myuser/calculator"
サードパーティのパッケージを参照する方法について、もう少し詳しく説明します。
外部 (サードパーティ) パッケージを参照する
プログラムで、他の開発者が記述したパッケージを参照することが必要な場合があります。 通常、これらのパッケージは GitHub にあります。 パッケージ (main
以外のパッケージ) とスタンドアロン プログラム (main
パッケージ) のどちらを開発している場合でも、次の手順でサードパーティのパッケージを参照できます。
rsc.io/quote
パッケージへの参照を追加してみましょう。
package main
import (
"fmt"
"github.com/myuser/calculator"
"rsc.io/quote"
)
func main() {
total := calculator.Sum(3, 5)
fmt.Println(total)
fmt.Println("Version: ", calculator.Version)
fmt.Println(quote.Hello())
}
Visual Studio Code を使用している場合、go.mod
ファイルはファイルの保存時に更新されます。 次のように表示されます。
module helloworld
go 1.14
require (
github.com/myuser/calculator v0.0.0
rsc.io/quote v1.5.2
)
replace github.com/myuser/calculator => ../calculator
rsc.io/quote
でパッケージの特定のバージョンを参照する方法に注目してください。 プログラムの依存関係をアップグレードする必要がある場合は、ここでバージョンを変更する必要があります。
次のコマンドを使用してプログラムを再実行します。
go run main.go
出力は次のようになります。
8
Version: 1.0
Hello, world.
サードパーティ パッケージへの将来の参照はすべて、go.mod
ファイルに含まれている必要があります。 アプリケーションを実行またはコンパイルすると、その依存関係のすべてが Go によってダウンロードされます。