在编译时验证接口的合理性,这包括:
(1)导出类型的部分 API 实现了接口;
(2)导出或非导出类型实现了接口且属于某类型的一部分(匿名嵌套);
(3)任何其他情况都违反接口合理性检查,终止编译并通知用户。
上面这三条是编译器对接口的检查机制, 错误地使用接口会在编译期报错。所以可以利用这个机制让部分问题在编译期暴露。
// Bad
type Handler struct {
// ...
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// ...
}
// Good
type Handler struct {
// ...
}
var _ http.Handler = (*Handler)(nil)
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// ...
}
如果*Handler
与http.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) {
// ...
}