一架梯子,一头程序猿,仰望星空!
Golang开发规范 > 内容正文

指导原则-Interface 合理性验证


Interface 合理性验证

在编译时验证接口的符合性。这包括:

  • 将实现特定接口的导出类型作为接口 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,
) {
  // ...
}