概要
今回のブログポストではGolangのPackage
(パッケージ)を詳しく説明して、使う方法についても説明します。このブログポストで紹介するコードは次のリンクで確認できます。
パッケージ
Golangでパッケージはコードをまとめる基本単位です。したがって、全てのコードは必ずパッケージ中に入れる必要があります。
また、Golangでプログラムを作成する場合、必ずmain
パッケージが存在する必要があり、main
パッケージ中にmain
関数が定義される必要があります。Golangではこのmainパッケージのmain関数がプログラムのエントリーポイントとなります。
mainパッケージ以外のパッケージはエントリーポイント(main関数)がないパッケージで、mainパッケージの補助パッケージで使います。
このように全てのパッケージを持ってるものがモジュールです。モジュールについては下記のリンクを参考してください。
パッケージの使い方
そしたら、パッケージを使う方法について確認するため、main.go
ファイルを次のように修正します。
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println(rand.Int())
}
この例題ではfmt
パッケージとmath
パッケージの配下のrand
パッケージを持ってきて、画面にランダムな数字を表示します。このように作成したコードを実行すると、次のような結果が表示されます。
# go run main.
5577006791947779410
パッケージの外部共有
Golangではパッケージ内のタイプ、グローバル変数、定数、関数、メソードなどを外部に公開して他のパッケージで使うことができます。パッケージで外部で公開したいものは大文字で始まって、外部で公開しないものは小文字で始まります。
パッケージを外部で公開して公開されたパッケージを使う時にはモジュールを使う必要があります。モジュールについて詳しい内容は下記のリンクを参考してください。
外部で公開するパッケージを作ってみるため、greeting
フォルダを作ってgreeting.go
ファイルを生成して次のように修正します。
package greeting
import "fmt"
const PI = 3.14
func PrintGreeting() {
print()
}
func print() {
fmt.Println("Hello, World!")
}
このように修正したら、次のコマンドを使ってgreeting
モジュールを生成します。
go mod init github.com/dev-yakuza/study-golang/package/greeting
このgreeting
パッケージはgreeting
モジュールを通じて共有される予定です。このように共有されたgreeting
パッケージを使うmain
パッケージを作ってみましょう。
greeting
フォルダと同じ位置にmain
フォルダを生成して当該フォルダにmain.go
ファイルを作って次のように修正します。
package main
import (
"fmt"
"github.com/dev-yakuza/study-golang/package/greeting"
)
func main() {
fmt.Println(greeting.PI)
greeting.PrintGreeting()
}
次は下記のコマンドを使ってモジュールを生成します。
go mod init github.com/dev-yakuza/study-golang/package/main
モジュールを生成したら、ローカルに存在するgreeting
モジューロを使うため下記のコマンドを実行します。
go mod edit -replace github.com/dev-yakuza/study-golang/package/greeting=../greeting
最後の次のコマンドを実行してモジュールを設定します。
go mod tidy
このように作ったプログラムを実行すると次のような結果を確認できます。
# go run main.go
3.14
Hello, World!
init関数
パッケージはinit
関数を定義することが出来て、init
関数はパッケージがimport
される時1回コールされます。パッケージのinit
関数はパッケージ内のグローバル変数を初期化する時使います。
これを確認するためgreeting/greeting.go
ファイルを次のように修正します。
package greeting
import "fmt"
const PI = 3.14
var globalVal = 0
func init() {
fmt.Println("init()", globalVal)
globalVal++
}
func PrintGreeting() {
print()
}
func print() {
fmt.Println("Hello, World!", globalVal)
}
そしてmain
フォルダで下記のコマンドを実行して修正した内容を確認します。
go run main.go
プログラムが実行されると次のような結果が表示されます。
init() 0
3.14
Hello, World! 1
エイリアスパッケージ名
Golangではこのように既に作られったパッケージを使ってプログラムを作成します。しかし、全ての開発者が約束をしてパッケージを作成するわけではないので、たまにパッケージ名が重複される時があります。
import (
"text/template"
"html/template"
)
template.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
template.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
このように重複されるパッケージ名を使う場合、エイリアスパッケージ名
(Alias Package Name)を使います。
import (
htmlplate "html/template"
"text/template"
)
template.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
htmlplate.New("foo").Parse(`{{define "T"}}Hello{{end}}`)
これを確認するためmain.go
ファイルを下記のように修正します。
package main
import (
"fmt"
htmlplate "html/template"
"text/template"
)
func main() {
fmt.Println(template.New("foo").Parse(`{{define "T"}}Hello{{end}}`))
fmt.Println(htmlplate.New("foo").Parse(`{{define "T"}}Hello{{end}}`))
}
これを実行すると次のような結果が表示されます。
# go run main.go
&{foo 0xc00010e480 0xc00006c050 } <nil>
&{<nil> 0xc000104140 0xc00010e900 0xc00006c0a0} <nil>
空白識別子
Golangではパッケージも変数と同じように宣言したら必ず使う必要があります。そしないと、コンパイルエラーが発生します。しかし、パッケージを直接使わないけど、importをしてinit()
関数を実行して、パッケージを初期化する場合があります。この時、エイリアスパッケージ名
と空白識別子
(Blank identifier, _
)を使ってエラーを解決することが出来ます。
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
パッケージをimportすると基本的パッケージ中のinit()
関数がコールされます。つまり、パッケージをimportしてinit()
関数をコールする必要はありますが、他の機能を使わない時、上のようにエイリアスパッケージ名と空白識別子を活用します。
これを確認するためinit関数の例題でmain.go
ファイルを次のように修正します。
package main
import (
"fmt"
_ "github.com/dev-yakuza/study-golang/package/greeting"
)
func main() {
fmt.Println("Hello")
}
これを実行すると下記のような結果が表示されます。
# go run main.go
init() 0
Hello
import cycle
Golangでは異なるパッケージがお互いimportをするとimportが繰り返されため、import cycle
エラーが発生します。
これを確認するためgreeting/greeting.go
ファイルを生成して、次のように修正します。
package greeting
import (
"fmt"
"github.com/dev-yakuza/study-golang/package/name"
)
func Print() {
fmt.Println("Hello, ", name.Name)
}
次は下記のコマンドを実行してモジュールを生成します。
# cd greeting
go mod init github.com/dev-yakuza/study-golang/package/greeting
次はimport cycle
エラーを発生させるため、greeting
フォルダと同じ位置にname/name.go
ファイルを生成して、次のように修正します。
package name
import (
"github.com/dev-yakuza/study-golang/package/greeting"
)
var Name = "John"
func print() {
greeting.Print()
}
このように生成したname
パッケージも次のコマンドを実行してモジュールを生成します。
# cd name
go mod init github.com/dev-yakuza/study-golang/package/name
このように作ったそれそれのモジュールをお互いに参照するモジュールを連結するため次のコマンドを実行します。
cd greeting
go mod edit -replace github.com/dev-yakuza/study-golang/package/name=../name
go mod tidy
cd ..
cd name
go mod edit -replace github.com/dev-yakuza/study-golang/package/greeting=../greeting
go mod tidy
このように設定をしたら、name.go
ファイルを開いてgreeting
パッケージを追加するところを見ると、次のようにimport cycle not allowed
エラーが発生することが確認できます。
完了
これでGolangでパッケージが何か、どう使うのかについてみてみました。これからパッケージを作って外部に共有したら、共有された外部パッケージを使ってプログラムを作成してみてください。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Deku
が開発したアプリを使ってみてください。Deku
が開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。