猿问

Go and Gin:传递数据库上下文的结构?

我刚刚开始尝试 Go,我希望用它重新实现一个用 node 编写的 API 服务器。


我在尝试使用依赖注入将数据库上下文作为 gin 中间件传递时遇到了障碍。到目前为止,我已将其设置为:


main.go:


package main


import (

        "fmt"

        "runtime"

        "log"

        "github.com/gin-gonic/gin"

        "votesforschools.com/api/public"

        "votesforschools.com/api/models"

)


type DB struct {

        models.DataStore

}


func main() {

        ConfigRuntime()

        ConfigServer()

}


func Database(connectionString string) gin.HandlerFunc {

        dbInstance, err := models.NewDB(connectionString)

        if err != nil {

                log.Panic(err)

        }


        db := &DB{dbInstance}


        return func(c *gin.Context) {

                c.Set("DB", db)

                c.Next()

        }

}



func ConfigRuntime() {

        nuCPU := runtime.NumCPU()

        runtime.GOMAXPROCS(nuCPU)

        fmt.Printf("Running with %d CPUs\n", nuCPU)

}


func ConfigServer() {


        gin.SetMode(gin.ReleaseMode)


        router := gin.New()

        router.Use(Database("<connectionstring>"))

        router.GET("/public/current-vote-pack", public.GetCurrentVotePack)

        router.Run(":1000")

}

模型/db.go


package models


import (

        "database/sql"

        _ "github.com/go-sql-driver/mysql"

)


type DataStore interface {

        GetVotePack(id string) (*VotePack, error)

}


type DB struct {

        *sql.DB

}


func NewDB(dataSource string) (*DB, error) {

        db, err := sql.Open("mysql", dataSource)

        if err != nil {

                return nil, err

        }

        if err = db.Ping(); err != nil {

                return nil, err

        }

        return &DB{db}, nil

}

但是我得到 public\public.go:10: db.GetVotePack undefined (type interface {} is interface with no methods)

当我在调试器中检查(使用带有插件的 Webstorm)时,db 只是一个空对象。我正在努力做好并避免使用全局变量


jeck猫
浏览 223回答 3
3回答

慕仙森

我认为不context应该用作 DI 容器:https : //golang.org/pkg/context/包上下文定义了上下文类型,它在 API 边界和进程之间携带截止日期、取消信号和其他请求范围的值。我宁愿使用:package publictype PublicController struct {&nbsp; &nbsp; &nbsp; &nbsp; Database *DB}func (c *PublicController) GetCurrentVotePack(context *gin.Context) {&nbsp; &nbsp; &nbsp; &nbsp; votePack, err := c.Database.GetVotePack("c5039ecd-e774-4c19-a2b9-600c2134784d")&nbsp; &nbsp; &nbsp; &nbsp; if err != nil{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; context.String(404, "Votepack Not Found")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; context.JSON(200, votePack)}并在 main 中配置您的控制器:func main() {&nbsp; &nbsp; &nbsp; &nbsp; pCtrl := PublicController { Database: models.NewDB("<connectionstring>") }&nbsp; &nbsp; &nbsp; &nbsp; router := gin.New()&nbsp; &nbsp; &nbsp; &nbsp; router.GET("/public/current-vote-pack", pCtrl.GetCurrentVotePack)&nbsp; &nbsp; &nbsp; &nbsp; router.Run(":1000")}

富国沪深

其中的值context.Keys都是 type interface{},因此在db将 type*DB转换回该类型之前,将无法从 type 调用方法。安全的方法:db, ok := context.Keys["DB"].(*DB)if !ok {&nbsp; &nbsp; &nbsp; &nbsp; //Handle case of no *DB instance}// db is now a *DB value不太安全的方法,如果context.Keys["DB"]不是 type 的值,它会恐慌*DB:db := context.Keys["DB"].(*DB)// db is now a *DB valueEffective Go有一个关于这个的部分。

江户川乱折腾

您需要类型断言才能将接口 (db := context.Keys["DB"]) 转换为有用的东西。例如,参见这篇文章:convert interface{} to int in Golang
随时随地看视频慕课网APP

相关分类

Go
我要回答