首页 > 解决方案 > 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)
    }
}

我尝试在我的项目中实现存储库,但仍然坚持在我们的控制器函数列表中调用Repository.GetAll()。我为此使用杜松子酒和戈姆

标签: gointerfacego-gin

解决方案


接口只是类型为了实现该特定接口而必须具有的一组方法签名。所以你不能调用接口。

在您的示例代码DBRepo中应该实现Repositoryinterface 和 functionlist()是一个允许列出实现的任何类型的内容的函数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实例作为接收器的字段。


推荐阅读