パッケージは、同じディレクトリにあり、最初に同じパッケージステートメントを持つGoファイルで構成されています。 パッケージに追加機能を組み込んで、プログラムをより洗練されたものにすることができます。 一部のパッケージはGo標準ライブラリから入手できるため、Goインストールとともにインストールされます。 その他は、Goのgo get
コマンドでインストールできます。 必要なpackageステートメントを使用して、コードを共有するのと同じディレクトリに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
ファイルを開き、次のコードを追加します。
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
パッケージを呼び出します。
package main
import "github.com/gopherguides/greet"
func main() {
greet.Hello()
}
パッケージをインポートするため、ドット表記でパッケージ名を参照して関数を呼び出す必要があります。 ドット表記は、使用しているパッケージの名前とそのパッケージ内で使用したいリソースの間にピリオド.
を入れる方法です。 たとえば、greet
パッケージには、リソースとしてHello
関数があります。 そのリソースを呼び出す場合は、greet.Hello()
のドット表記を使用します。
これで、ターミナルを開いて、コマンドラインでプログラムを実行できます。
- go run main.go
これを行うと、次の出力が表示されます。
OutputHello, World!
パッケージで変数を使用する方法を確認するために、greet.go
ファイルに変数定義を追加しましょう。
package greet
import "fmt"
var Shark = "Sammy"
func Hello() {
fmt.Println("Hello, World!")
}
次に、main.go
ファイルを開き、次の強調表示された行を追加して、fmt.Println()
関数のgreet.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
を作成します。
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
を開いて、ファイルの最後にそのタイプのインスタンスを作成します。
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
パッケージの外部:
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
を呼び出そうとした場合:
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
のreset
機能をexport
するには、reset
のR
を大文字にします。
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
を呼び出すことができます。
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プログラミングファイル内でそれらの定義を使用する方法を示し、パッケージにアクセスするためにパッケージを保持する場所のオプションについて説明しました。