LoginSignup
29
12

More than 1 year has passed since last update.

Goのinternalパッケージを使いこなそう

Last updated at Posted at 2022-12-14

はじめに

どうもナレッジワークtenntennです。

Goのinternalパッケージはご存知でしょうか?
本記事では、うまく使うととても便利なinternalパッケージについてご紹介します。

internalパッケージとは

Goパッケージは、基本的には外部のモジュールに公開されます。
パッケージ内のどの識別子を公開するかは、先頭の文字を大文字にするかどうかで決まりますが、パッケージにはその機能はありません。

しかし、Goにはinternalパッケージ(内部パッケージ)という特別なパッケージがあります。internalパッケージは、モジュール外には公開されません。
また、internalパッケージの親パッケージおよびその子パッケージ以下からしか参照できません。

たとえば、以下のようなパッケージ構成があった場合を考えます。

a
├── b
│   ├── d
│   └── internal
│       └── e
├── c
└── go.mod

a/b/internalパッケージ直下の識別子やa/b/internal/eパッケージの識別子は、一部のパッケージからしか参照できません。
パッケージbとパッケージd以下およびinternalパッケージ以下のパッケージからの参照に限定されます。
パッケージaやパッケージcからは参照できません。

もちろん、internalパッケージ以下のパッケージで識別子を非公開(小文字で始める)にした場合は、そのパッケージ内だけからしか参照できません。
なお、internalパッケージはモジュール以下にいくつでも作れます。

テストをしやすくする

筆者は、テストコードはテスト対象のパッケージとは別のパッケージにした方が良いと考えています。
つまり、aパッケージをテストしたい場合は、テストコードはa_testパッケージにする方が良いということです。

テストコードを別パッケージにすることで次のような利点が得られます。

  • 単体テストがパッケージの初めてユーザになる
  • 使い勝手や使用した場合可読性を図りやすい
  • 早めに設計ミスなどに気づける

また、一方で次のような煩わしさが残ります。

  • 非公開な機能を使ったテストがしづらい
  • わざわざ、別のパッケージにするのがめんどくさい

非公開な機能のテストは、export_test.goを使ったパターンでほとんどの場合は解決します。
テストで使用する非公開な機能をAllowリスト形式で並べることにもなるため、テストのときだけの特別扱いを避けやすくなります。

しかし、非公開な機能で複雑な処理をしている場合、どうしてもテストがしたくなります。
その場合に有効なのがinternalパッケージです。

複雑な処理をしている非公開な機能をモジュール内ライブラリのような形で切り出し、internalパッケージ以下に配置することで特定のパッケージからしか参照できないように制限できます。
そして、internalパッケージ以下では公開された機能としてテストすればexport_test.goを使う必要もありません。

モジュールやパッケージ間を疎結合にする

実はGoチームが管理しているモジュールの多くでinternalパッケージが利用されています。
公開する必要がない場合はinternalパッケージ以下に置くようなレベルで管理されているモジュールもあります。

たとえば、Webアプリのようなものであれば、エントリーポイントとなるmainパッケージを含むパッケージのみ公開し、他のパッケージはモジュール直下にあるinternalパッケージ以下に配置するという方法がとられます。
pkg.go.devソースコードを見てもモジュール直下にinternalパッケージがあることが分かります。

他のモジュールやパッケージから参照されてほしくないパッケージはinternalパッケージに置いておくと、後方互換を気にせずに破壊的変更が行える利点があります。
ライブラリでもWebアプリでもこの利点は効いてくるでしょう。

おわりに

本記事ではinternalパッケージの活用について紹介しました。

29
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
12