Go言語において、コードの組織化は**パッケージ(packages)**と可視性システムを通じて重要な役割を果たし、モジュラリティ、再利用性、論理のカプセル化を促進します。
多くのクラシックなオブジェクト指向継承を持つ言語とは異なり、Goは初めからシンプルなモジュールとして設計されており、エクスポートとインポートの明確なルールを持つパッケージとして設計されています。これはミニマリズム、シンプルさ、依存関係の厳格な管理の哲学の遺産です。
コンポーネントに明確な可視性がない場合、名前に混乱が生じ、ファイル間の依存関係を追跡することが難しくなり、プライベートな実装の詳細が誤って使用されるリスクが高まります。エクスポートの組織における誤りは、デバッグが難しいバグやカプセル化の違反を引き起こす可能性があります。
Goでは、各ファイルは必ず何らかのパッケージに属しています(package 名前)。Goにおける可視性は以下によって定義されます:
名前が大文字で始まるすべての関数、型、変数、定数、メソッドは、パッケージからエクスポートされ、インポート後に他のパッケージからアクセス可能です。他のものはパッケージ内でのみアクセス可能です。
構造の例:
project/
│
├── main.go // package main
└── mathutil/
└── mathutil.go // package mathutil
コードの例:
// mathutil/mathutil.go package mathutil // Public - エクスポートされる関数 func Sum(a, b int) int { return a + b } // private - エクスポートされない関数 func subtract(a, b int) int { return a - b }
// main.go package main import ( "fmt" "project/mathutil" ) func main() { fmt.Println(mathutil.Sum(2, 3)) // 5 // fmt.Println(mathutil.subtract(3,2)) // コンパイルエラー! subtractはエクスポートされていません }
重要な特徴:
小文字で宣言された変数や関数を他のメカニズムを使ってエクスポートできますか?
いいえ。Goにはpublicやprivateのようなキーワードはなく、すべては名前の最初の文字(Unicodeカテゴリ—大文字)によって決まります。
同じパッケージ内の異なるファイルからの関数は、プライベート関数を使用できますか?
はい、可視性はファイルではなくパッケージレベルで制限されています。すべてのプライベート要素は同じパッケージのすべてのファイルで利用可能です。
コードの例:
// mathutil/helpers.go package mathutil func hiddenHelper() int { return 42 } // mathutil/mathutil.go package mathutil func UseHelper() int { return hiddenHelper() // 利用可能! }
同じパッケージ内の異なるファイルで同じ名前の関数や型を作成できますか?
いいえ、コンパイルエラーになります—パッケージ内では、名前はユニークである必要があります。たとえ異なるファイルで宣言されていてもです。
xxx_test.goファイルを使用する方が良い)大きなチームがすべての補助関数と型をutilパッケージに入れ、すべてを無差別にエクスポートします:
利点:
欠点:
チームがビジネスエリアごとにコードをモジュール化し、APIのみをエクスポートします:
利点:
欠点: