为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
jeck猫 2021-12-20 10:13:20
我刚刚开始尝试 Go,我希望用它重新实现一个用 node 编写的 API 服务器。我在尝试使用依赖注入将数据库上下文作为 gin 中间件传递时遇到了障碍。到目前为止,我已将其设置为:main.go:package mainimport (        "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.gopackage modelsimport (        "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 只是一个空对象。我正在努力做好并避免使用全局变量
查看完整描述

3 回答

?
慕仙森

TA贡献1827条经验 获得超7个赞

我认为不context应该用作 DI 容器:https : //golang.org/pkg/context/


包上下文定义了上下文类型,它在 API 边界和进程之间携带截止日期、取消信号和其他请求范围的值。


我宁愿使用:


package public


type PublicController struct {

        Database *DB

}


func (c *PublicController) GetCurrentVotePack(context *gin.Context) {

        votePack, err := c.Database.GetVotePack("c5039ecd-e774-4c19-a2b9-600c2134784d")

        if err != nil{

                context.String(404, "Votepack Not Found")

        }

        context.JSON(200, votePack)

}

并在 main 中配置您的控制器:


func main() {

        pCtrl := PublicController { Database: models.NewDB("<connectionstring>") }


        router := gin.New()

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

        router.Run(":1000")

}


查看完整回答
反对 回复 2021-12-20
?
富国沪深

TA贡献1790条经验 获得超9个赞

其中的值context.Keys都是 type interface{},因此在db将 type*DB转换回该类型之前,将无法从 type 调用方法。


安全的方法:


db, ok := context.Keys["DB"].(*DB)

if !ok {

        //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 value

Effective Go有一个关于这个的部分。


查看完整回答
反对 回复 2021-12-20
?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

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


查看完整回答
反对 回复 2021-12-20
  • 3 回答
  • 0 关注
  • 222 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信