如何在 go-gin 中调用接口函数?
How to call Interface function in go-gin?
这是存储库 + 控制器
package brand
import (
"path/to/models"
"gorm.io/gorm"
"github.com/gin-gonic/gin"
)
type ResponseBrand struct {
Items []models.MasterBrand `json:"items"`
TotalCount int `json:"total"`
}
type Repository interface {
GetAll() (ResponseBrand, error)
}
type DBRepo struct {
db *gorm.DB
}
func (repo *DBRepo) GetAll() (ResponseBrand, error) {
var response ResponseBrand
var brands []models.MasterBrand
repo.db.Find(&brands)
response.Items = brands
response.TotalCount = len(brands)
return response, nil
}
func list(c *gin.Context) {
// this is an error
res, _ := Repository.GetAll()
}
这用于路由组
func ApplyRoutes(r *gin.RouterGroup) {
brand := r.Group("/brand") {
brand.GET("/", list)
}
}
我尝试在我的项目中实现存储库,但仍然坚持在我们的控制器函数 list[=20= 中调用 Repository.GetAll() ].我用 gin & gorm 来做这个
接口只是一组方法签名,类型必须具有这些方法签名才能实现该特定接口。所以不能调用接口。
在您的示例代码中,DBRepo
应该实现 Repository
接口和函数 list()
是一个允许列出实现 Repository
的任何类型的内容的函数。这样做显然 list()
需要知道要列出哪个 Repository
-like 类型的实例 - 例如接收它作为参数。像这样:
func list(ctx *gin.Context, repo Repository) {
// here call GetAll() which MUST exist on all types passed (otherwise they don't
// implement Repository interface
res, _ := repo.GetAll()
// ...
}
现在 gin
将无法将修改后的列表作为路由器函数,因为这样的签名只是 (ctx *gin.Context)
但您可以使用匿名函数并包装您的存储库感知 list()
在里面。
func ApplyRoutes(repo Repository, r *gin.RouterGroup) {
brand := r.Group("/brand") {
brand.GET("/", func(ctx *gin.Context) {
list(repo)
})
}
}
此外,您的 ApplyRoutes()
函数需要知道应该在哪些 Repository 路由上运行 - 为了简单起见,我将其添加到此处作为参数,其他优雅的解决方案是将整个控制器包装在类型中并获得 Repository
实例作为接收者的字段。
这是存储库 + 控制器
package brand
import (
"path/to/models"
"gorm.io/gorm"
"github.com/gin-gonic/gin"
)
type ResponseBrand struct {
Items []models.MasterBrand `json:"items"`
TotalCount int `json:"total"`
}
type Repository interface {
GetAll() (ResponseBrand, error)
}
type DBRepo struct {
db *gorm.DB
}
func (repo *DBRepo) GetAll() (ResponseBrand, error) {
var response ResponseBrand
var brands []models.MasterBrand
repo.db.Find(&brands)
response.Items = brands
response.TotalCount = len(brands)
return response, nil
}
func list(c *gin.Context) {
// this is an error
res, _ := Repository.GetAll()
}
这用于路由组
func ApplyRoutes(r *gin.RouterGroup) {
brand := r.Group("/brand") {
brand.GET("/", list)
}
}
我尝试在我的项目中实现存储库,但仍然坚持在我们的控制器函数 list[=20= 中调用 Repository.GetAll() ].我用 gin & gorm 来做这个
接口只是一组方法签名,类型必须具有这些方法签名才能实现该特定接口。所以不能调用接口。
在您的示例代码中,DBRepo
应该实现 Repository
接口和函数 list()
是一个允许列出实现 Repository
的任何类型的内容的函数。这样做显然 list()
需要知道要列出哪个 Repository
-like 类型的实例 - 例如接收它作为参数。像这样:
func list(ctx *gin.Context, repo Repository) {
// here call GetAll() which MUST exist on all types passed (otherwise they don't
// implement Repository interface
res, _ := repo.GetAll()
// ...
}
现在 gin
将无法将修改后的列表作为路由器函数,因为这样的签名只是 (ctx *gin.Context)
但您可以使用匿名函数并包装您的存储库感知 list()
在里面。
func ApplyRoutes(repo Repository, r *gin.RouterGroup) {
brand := r.Group("/brand") {
brand.GET("/", func(ctx *gin.Context) {
list(repo)
})
}
}
此外,您的 ApplyRoutes()
函数需要知道应该在哪些 Repository 路由上运行 - 为了简单起见,我将其添加到此处作为参数,其他优雅的解决方案是将整个控制器包装在类型中并获得 Repository
实例作为接收者的字段。