如何在 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 实例作为接收者的字段。