我正在使用一个具有Router
接口的软件包,我创建了自己的特定于应用程序的Router
接口,用于包装第三方软件包。
一切都运行良好,但其中一种方法是抛出编译错误:
controllers / auth.go:52:17:不能在f.router.Group的参数中使用func文字(类型为func(router.Router))作为类型func(chi.Router)
这是第三方包(chi)的界面:
type Router interface {
// ...
// Group adds a new inline-Router along the current routing
// path, with a fresh middleware stack for the inline-Router.
Group(fn func(r Router)) Router
// ...
}
这是我的包装界面:
type Router interface {
chi.Router
// Custom methods...
}
我对Group
函数的使用是这样的:
type AuthController struct {
router router.Router
// ...
}
func (c *AuthController) SetRoutes() {
c.router.Group(func(r router.Router) {
r.Use(middleware.Anyone)
r.Post("/auth/register", c.Register)
r.Post("/auth/login", c.Authenticate)
r.Post("/auth/token/refresh", c.RefreshToken)
})
c.router.Group(func(r router.Router) {
r.Use(middleware.Authorized)
r.Get("/auth/ping", c.Ping)
r.Post("/auth/logout", c.Logout)
})
}
为什么它在我的函数回调参数类型中尖叫?我的包装器router.Router
实现了chi.Router
接口,所以它不应该正常工作吗?我误解了Go如何在这里工作吗?
答案 0 :(得分:2)
参数类型不相同,因此函数类型与预期的不匹配,即使您的接口包含来自其他包的接口(类型必须完全匹配)。您需要让函数采用chi.router
,然后使用类型断言(即myRouter := r.(Router)
)转换为您的类型。
答案 1 :(得分:1)
我可以看到这会让人感到困惑,所以我会尝试将其分解。你有这个方法:
Group(fn func(r Router)) Router
此方法将函数作为参数。该功能必须具有特定的签名:
func(r Router)
也就是说,它只需要chi.Router
类型的单个参数,并且没有返回值。但是,当你打电话时:
c.router.Group(func(r router.Router) { /***/ }
你传递了错误签名的功能;你的功能签名是:
func(r router.Router)
这不是您正在调用的方法所需的签名,因此无法编译。如果router.Router
实现chi.Router
,则无关紧要;传递的参数(a func(router.Router)
)不是预期的类型(func(chi.Router)
)。
这一开始可能看起来很愚蠢 - 毕竟,任何router.Router
都必须实施chi.Router
。但是,请想一想:该方法Group
期望接收一个函数,它可以传递任何 chi.Router
。这意味着它可以传递未实现的chi.Router
router.Router
。如果要接受你的函数,它会破坏类型的安全性,而Go中的内容是编译时错误(实际上你得到的错误)将成为运行时错误。基本上,通过传递具有不同(和更严格)参数类型的函数,您期望保证该方法从未提供过。