Goでstructのinterface実装を検証する方法

0

2022年04月18日 9:51

こんにちは、ISSUEの寒河江です。

日頃Goでの運用知見を貪欲に調べています。今回はGolangでstructがインターフェースの実装を満たしているかを検証する方法について記事を書いてみました。

インタフェースを検証して実装漏れを防ぐ

システムの規模が大きくなると、可読性の低下などから実装漏れをしやすくなります。それがさらに可読性を悪化させる負のスパイラルとなります。

なのでstructのinterface実装漏れを防ぐなど、こういった小さなことの積み重ねが大事になってきます。

インタフェースを満たすUser struct

例を挙げます。下記にPerson interface、そのinterfaceの実装を満たすUser structを定義します。
img

出力
img
正常にコンパイルが通りました。

Go Playground

インタフェースに実装を1つ追加する

今度はPerson interfaceにGetEmailを追加します。今度はUser structにGetEmail()が実装されていないのでPerson interfaceを満たしません。
img
しかし実行してもコンパイルは通ってしまいます。

出力
img

本来ならここでエラーを起こしてinterfaceの実装漏れに気づきたいところです。上記は単純なコードでファイルも1つしかないので実装漏れがあることに気づくのは簡単だと思います。しかし、これが数十ファイルになったらどうでしょうか。1つ1つのstrcutがPersonのinterfaceを満たしているかを確認するのは大変な作業で効率的ではありませんよね。。

Go Playground

structのインタフェース実装検証を追加して、コンパイルで落とす

ここからが本題になります。interfaceを満たさないstructを検証する2つの方法を書いていきます。両方ともinterface実装が確認できなければコンパイルが通りません。

1. Verify Interface Compliance

structをinterfaceの型指定で定義する方法です。これはUberで紹介されている方法で有名だと思います。

img
上記のコードを実行すると、コンパイルエラーになります。

出力
img
Go Playground

もちろんGetEmailを追加すると通ります。
img
出力
img

Go Playground

こちらの方法が一行でかけてシンプルな方法だと思います。

レシーバがポインタ型ではない場合

GetNameとGetEmailは共にレシーバーはポインタ型(*User)です。レシーバーがポインタ型でない場合は下記のような書き方で検証することができます。
img

出力
img
Go Playground

2. 初期化関数で検証する

2つ目の方法です。ある程度の規模のシステムではレイヤードアーキテクチャやクリーンアーキテクチャなどの構造を通ることが多いと思います。その場合、repositoryをusecaseにDIして利用するケースが多いかと思います。その際、初期化関数の返り値をinterfaceに指定することでstructを検証できます。

下記はusecase層のinterface検証になります。
img
こちらの方法でinterfaceの検証を行うこともできます。この方法なら、初期化とinterface検証の両方を同時に行うことができます。

handlerなど、場合によって初期化関数は作らない場合もあるかと思うので状況に応じて使い分けていただければと思います!

以上、Goでstructのinterface実装を検証する方法についてでした!

# Go
0

診断を受けるとあなたの現在の業務委託単価を算出します。今後副業やフリーランスで単価を交渉する際の参考になります。また次の単価レンジに到達するためのヒントも確認できます。

目次を見る