インターフェースの合理性検証

コンパイル時にインターフェースの準拠を検証します。以下を含みます:

  • インターフェースAPIの一部として特定のインターフェースを実装するエクスポートされた型の検査
  • 同じインターフェースを実装するタイプ(エクスポートされたものおよび非エクスポートされたもの)は実装タイプのコレクションに属する
  • インターフェースの合理性チェックを違反するシナリオがある場合、コンパイルを中止し、ユーザーに通知します

補足:上記の3つのポイントはコンパイラのインターフェースチェックメカニズムです。一般的な考え方は、インターフェースの使用中のエラーはコンパイル時に報告されます。そのため、このメカニズムを使用してコンパイル時に問題を明らかにすることができます。

推奨されないアプローチ:

// Handlerがhttp.Handlerを実装していない場合、ランタイムでエラーが発生します
type Handler struct {
  // ...
}
func (h *Handler) ServeHTTP(
  w http.ResponseWriter,
  r *http.Request,
) {
  ...
}

推奨されるアプローチ:

type Handler struct {
  // ...
}
// コンパイル時にインターフェースの合理性チェックメカニズムをトリガーするために使用
// Handlerがhttp.Handlerを実装していない場合、コンパイル時にエラーが発生します
var _ http.Handler = (*Handler)(nil)
func (h *Handler) ServeHTTP(
  w http.ResponseWriter,
  r *http.Request,
) {
  // ...
}

*Handlerhttp.Handler のインターフェースに一致しない場合、文 var _ http.Handler = (*Handler)(nil) はコンパイルされません。

代入文の右辺は、アサートされた型のゼロ値である必要があります。ポインタ型(例:*Handler)、スライス、マップの場合、これは nil であり、構造体タイプの場合、これは空の構造体です。

type LogHandler struct {
  h   http.Handler
  log *zap.Logger
}
var _ http.Handler = LogHandler{}
func (h LogHandler) ServeHTTP(
  w http.ResponseWriter,
  r *http.Request,
) {
  // ...
}