Goにおいてのパッケージとは
モジュール性、カプセル化、分離されたコンパイル、再利用をサポートするものです。
それぞれの言葉の意味を掘り下げるとすごい長くなるので、ざっくり言うと、
機能を分離して、ごちゃごちゃな状態にするのをやめよう。そして、必要最低限の公開範囲にしよう。という感じです。
それぞれのパッケージ同士の公開範囲の設定(export)
個々のパッケージはその宣言に対して名前空間としての機能を果たします。
例として以下のようなものを考えてみました。
足し算パッケージ「add」と引き算パッケージ「sub」があるとします。それぞれに識別子の答えを出す「Ans」があるとします。もし、パッケージ外から識別子が参照するこの関数を指定する時には、明示的に以下のように修飾しなければいけません。
add.Ans
sub.Ans
また、パッケージでは、どの名前がパッケージの外から見えるを制御することができます。
これはとても簡単で、上記に例として書いたAnsは識別次の最初の文字が大文字なので、外部から参照が可能ということになります。
Ans // 外部から参照できる
ans // 隠蔽されているので、見えない
インポート(import)
次に実際にインポートする例を書いてみると、先程はバラバラになっていた。「Add」と「Sub」パッケージをもし統合したとして、大きな枠の「calc」という計算パッケージがあり、その中に識別子として「Add」と「Sub」に紐づく計算関数があるとします。ディレクトリ構成は以下のような想定とします。
test
|----calc/calc.go
|
|----main.go
package calc
func Add(atai1 int, atai2 int) int {
return atai1 + atai2
}
func sub(atai1 int, atai2 int) int {
return atai1 - atai2
}
package main
import (
"./calc" // calcパッケージ
"fmt"
)
func main() {
fmt.Println(calc.Add(1, 2)) // 成功
fmt.Println(calc.sub(1, 2)) // 失敗
}
上記のように、別パッケージであってもimportをした上でアクセスが許容されたものは、外部からでも参照することができます。逆に「sub」のように、大文字始まりでないものはアクセスが許容されません。
ここでいくつかポイントがあるので、箇条書きします。
- calcパッケージ内では、Addからsubの参照は可能です。
- calcパッケージではimportされていないfmtという出力系をまとめたパッケージはimportされていないが、import先でfmtを使うことが出来る。
注意点としては、importしたのにそのpackageが使用されていない場合はエラーとなります。
手作業でimportするのが面倒なあなた!goimportsを調べれば幸せになれます。
ちなみに、importするパッケージ名が長かったり、競合が発生する場合は別名していもできます。