Goでパッケージを作成する方法
パッケージは、同じディレクトリにあり、最初に同じパッケージステートメントを持つGoファイルで構成されています。 パッケージに追加機能を組み込んで、プログラムをより洗練されたものにすることができます。 一部のパッケージはGo標準ライブラリから入手できるため、Goインストールとともにインストールされます。 その他は、Goのgo getコマンドでインストールできます。 必要なパッケージステートメントを使用して、コードを共有するのと同じディレクトリにGoファイルを作成することにより、独自のGoパッケージを構築することもできます。
このチュートリアルでは、他のプログラミングファイル内で使用するGoパッケージの作成について説明します。
前提条件
- Goシリーズのローカルプログラミング環境をインストールしてセットアップする方法のチュートリアルの1つに従ってGoプログラミング環境をセットアップします。 ローカルプログラミング環境チュートリアルのステップ5に従って、Goワークスペースを作成します。 この記事の例と命名規則に従うには、最初のセクション「パッケージの作成とインポート」をお読みください。
- GOPATHの知識を深めるには、記事GOPATHについてお読みください。
パッケージの作成とインポート
パッケージの作成は、他のGoファイルの作成と同じです。 パッケージには、他のGoプログラムで使用できる関数、タイプ、および変数の定義を含めることができます。
新しいパッケージを作成する前に、Goワークスペースにいる必要があります。 これは通常、gopathの下にあります。 たとえば、このチュートリアルでは、パッケージをgreetと呼びます。 これを行うために、プロジェクトスペースの下のgopathにgreetというディレクトリを作成しました。 組織がgopherguidesであり、Githubをコードリポジトリとして使用しながら組織の下にgreetパッケージを作成したい場合、ディレクトリは次のようになります。
└── $GOPATH
└── src
└── github.com
└── gopherguides
greetディレクトリはgopherguidesディレクトリ内にあります。
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── greet
最後に、ディレクトリに最初のファイルを追加できます。 パッケージ内のprimaryまたはentry pointファイルは、ディレクトリの名前にちなんで名付けられるのが一般的な方法と考えられています。 この場合、greetディレクトリ内にgreet.goというファイルを作成します。
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── greet
└── greet.go
作成したファイルを使用して、プロジェクト間で再利用または共有するコードの記述を開始できます。 この場合、Hello Worldを出力するHelloという関数を作成します。
テキストエディタでgreet.goファイルを開き、次のコードを追加します。
greet.go
package greet
import "fmt"
func Hello() {
fmt.Println("Hello, World!")
}
この最初のファイルを分解してみましょう。 各ファイルの最初の行には、作業しているpackageの名前が必要です。 greetパッケージを使用しているため、packageキーワードの後にパッケージ名を使用します。
package greet
これにより、ファイル内のすべてがgreetパッケージの一部として扱われるようにコンパイラーに指示されます。
次に、importステートメントで使用する必要のある他のパッケージを宣言します。 このファイルで使用しているのは、fmtパッケージの1つだけです。
import "fmt"
最後に、関数Helloを作成します。 fmtパッケージを使用してHello, World!を印刷します。
func Hello() {
fmt.Println("Hello, World!")
}
greetパッケージを作成したので、作成した他のパッケージで使用できます。 greetパッケージを使用する新しいパッケージを作成しましょう。
exampleというパッケージを作成します。これは、exampleというディレクトリが必要であることを意味します。 gopherguides組織でこのパッケージを作成すると、ディレクトリ構造は次のようになります。
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── example
新しいパッケージ用のディレクトリができたので、エントリポイントファイルを作成できます。 これは実行可能プログラムになるため、エントリポイントファイルにmain.goという名前を付けるのがベストプラクティスと見なされます。
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── example
└── main.go
テキストエディタでmain.goを開き、次のコードを追加してgreetパッケージを呼び出します。
main.go
package main
import "github.com/gopherguides/greet"
func main() {
greet.Hello()
}
パッケージをインポートするため、ドット表記でパッケージ名を参照して関数を呼び出す必要があります。 ドット表記は、使用しているパッケージの名前とそのパッケージ内で使用したいリソースの間にピリオド.を入れる方法です。 たとえば、greetパッケージには、リソースとしてHello関数があります。 そのリソースを呼び出す場合は、greet.Hello()のドット表記を使用します。
これで、ターミナルを開いて、コマンドラインでプログラムを実行できます。
go run main.go
これを行うと、次の出力が表示されます。
OutputHello, World!
パッケージで変数を使用する方法を確認するために、greet.goファイルに変数定義を追加しましょう。
greet.go
package greet
import "fmt"
var Shark = "Sammy"
func Hello() {
fmt.Println("Hello, World!")
}
次に、main.goファイルを開き、次の強調表示された行を追加して、fmt.Println()関数のgreet.goから変数を呼び出します。
main.go
package main
import (
"fmt"
"github.com/gopherguides/greet"
)
func main() {
greet.Hello()
fmt.Println(greet.Shark)
}
プログラムを再度実行すると、次のようになります。
go run main.go
次の出力が表示されます。
OutputHello, World! Sammy
最後に、greet.goファイルでタイプも定義しましょう。 nameおよびcolorフィールドと、呼び出されたときにフィールドを出力する関数を使用して、タイプOctopusを作成します。
greet.go
package greet
import "fmt"
var Shark = "Sammy"
type Octopus struct {
Name string
Color string
}
func (o Octopus) String() string {
return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}
func Hello() {
fmt.Println("Hello, World!")
}
main.goを開いて、ファイルの最後にそのタイプのインスタンスを作成します。
main.go
package main
import (
"fmt"
"github.com/gopherguides/greet"
)
func main() {
greet.Hello()
fmt.Println(greet.Shark)
oct := greet.Octopus{
Name: "Jesse",
Color: "orange",
}
fmt.Println(oct.String())
}
oct := greet.Octopusを使用してOctopusタイプのインスタンスを作成すると、main.goファイルの名前空間内のタイプの関数とフィールドにアクセスできます。 これにより、greetを呼び出さずに、最後の行にoct.String()を書き込むことができます。 たとえば、greetパッケージの名前を参照せずに、oct.Colorなどのタイプフィールドの1つを呼び出すこともできます。
OctopusタイプのStringメソッドは、fmt.Sprintf関数を使用して文を作成し、returns結果(文字列)を呼び出し元に送信します(この場合ケース、あなたのメインプログラム)。
プログラムを実行すると、次の出力が表示されます。
go run main.go
OutputHello, World! Sammy The octopus's name is "Jesse" and is the color orange.
OctopusでStringメソッドを作成することにより、カスタムタイプに関する情報を印刷するための再利用可能な方法が得られます。 将来このメソッドの動作を変更したい場合は、この1つのメソッドを編集するだけで済みます。
エクスポートされたコード
呼び出したgreet.goファイルのすべての宣言が大文字になっていることに気付いたかもしれません。 Goには、他の言語のようにpublic、private、またはprotected修飾子の概念がありません。 外部の可視性は、大文字と小文字の区別によって制御されます。 大文字で始まるタイプ、変数、関数などは、現在のパッケージの外部で公開されています。 パッケージの外側に表示されるシンボルは、exportedと見なされます。
Octopusにresetという新しいメソッドを追加すると、greetパッケージ内から呼び出すことができますが、main.goファイルから呼び出すことはできません。 greetパッケージの外部:
greet.go
package greet
import "fmt"
var Shark = "Sammy"
type Octopus struct {
Name string
Color string
}
func (o Octopus) String() string {
return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}
func (o *Octopus) reset() {
o.Name = ""
o.Color = ""
}
func Hello() {
fmt.Println("Hello, World!")
}
main.goファイルからresetを呼び出そうとすると、次のようになります。
main.go
package main
import (
"fmt"
"github.com/gopherguides/greet"
)
func main() {
greet.Hello()
fmt.Println(greet.Shark)
oct := greet.Octopus{
Name: "Jesse",
Color: "orange",
}
fmt.Println(oct.String())
oct.reset()
}
次のコンパイルエラーが発生します。
Outputoct.reset undefined (cannot refer to unexported field or method greet.Octopus.reset)
Octopusからexportreset機能を使用するには、resetのRを大文字にします。
greet.go
package greet
import "fmt"
var Shark = "Sammy"
type Octopus struct {
Name string
Color string
}
func (o Octopus) String() string {
return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}
func (o *Octopus) Reset() {
o.Name = ""
o.Color = ""
}
func Hello() {
fmt.Println("Hello, World!")
}
その結果、エラーが発生することなく、他のパッケージからResetを呼び出すことができます。
main.go
package main
import (
"fmt"
"github.com/gopherguides/greet"
)
func main() {
greet.Hello()
fmt.Println(greet.Shark)
oct := greet.Octopus{
Name: "Jesse",
Color: "orange",
}
fmt.Println(oct.String())
oct.Reset()
fmt.Println(oct.String())
}
プログラムを実行すると、次のようになります。
go run main.go
次の出力が表示されます。
OutputHello, World! Sammy The octopus's name is "Jesse" and is the color orange The octopus's name is "" and is the color .
Resetを呼び出すことにより、NameおよびColorフィールドのすべての情報をクリアしました。 Stringメソッドを呼び出すと、フィールドが空になっているため、NameとColorが通常表示される場所には何も出力されません。
結論
Goパッケージの作成は、他のGoファイルの作成と同じですが、別のディレクトリに配置すると、コードを分離して他の場所で再利用できます。 このチュートリアルでは、パッケージ内で定義を作成する方法、別のGoプログラミングファイル内でそれらの定義を使用する方法を示し、パッケージにアクセスするためにパッケージを保持する場所のオプションについて説明しました。