首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从go-chi路由处理程序访问数据库实例

从go-chi路由处理程序访问数据库实例
EN

Stack Overflow用户
提问于 2021-07-01 02:27:16
回答 3查看 95关注 0票数 0

我正在尝试用go-chi和Gorm构建一个REST API。

我不确定应该如何将Gorm DB实例传递给路由处理程序。

或者我是否应该为每个处理程序创建一个实例,这对我来说听起来并不正确。

我应该使用中间件、依赖注入还是其他?这里推荐的模式是什么?

代码语言:javascript
复制
package main

import (
    "encoding/json"
    "fmt"
    "github.com/go-chi/chi/v5"
    "log"
    "net/http"
    "os"
    "time"
)

func main() {
    r := chi.NewRouter()

    r.Get("/", indexHandler)


    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
        log.Printf("Defaulting to port %s", port)
    }

    db := Connect()
    migrations(db)
    logStartServer(port)
    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), r))
}

func logStartServer(port string) {
    log.Printf("Listening on port %s", port)
    log.Printf("Open http://localhost:%s in the browser", port)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {

    //How can I access db here?
    //result := db.Find(&users)

    policy := InsurancePolicy{ValidFrom: time.Now()}
    err := json.NewEncoder(w).Encode(policy)

    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-07-01 02:33:01

使用方法而不是函数。这允许您使用这些方法的接收方传递处理程序所需的任何信息:

代码语言:javascript
复制
type MyHandler struct {
  DB *gorm.DB
}

func (m MyHandler) IndexHandler(w http.ResponseWriter, r *http.Request) {
  // Use m.DB here
}

在main中:

代码语言:javascript
复制
handler:=mypkg.MyHandler{DB:gormDB}
r.Get("/", handler.IndexHandler)

在某些情况下,闭包更有意义。

代码语言:javascript
复制
func GetIndexHandler(db *gorm.DB) func(http.ResponseWriter,*http.Request) {
   return func(w http.ResponseWriter,req *http.Request) {
     // Implement index handler here, using db
   }
}

func main() {
  ...
  r.Get("/", GetIndexHandler(db))
票数 2
EN

Stack Overflow用户

发布于 2021-07-01 07:00:53

如果您的项目很小,则将DB实例声明为全局变量非常方便。

许多组织数据库访问的方法在here中都有很好的文档记录。选择一个适合你需要的。

票数 1
EN

Stack Overflow用户

发布于 2021-07-01 10:35:47

在DB/query函数本身中。我个人为控制器和服务创建了一个单独的包。我在控制器(它有我的处理函数)中处理所有的请求、验证和HTTP内容。然后,如果一切正常,我会调用一个服务包。服务包是调用DB以及任何其他服务或API集成的包。

然而,无论您何时调用DB,通常都是调用一个db包,该包具有一系列具有友好名称的查询函数,如db.GetAccountByID或类似的名称。嗯,db函数就是您传递*sql.DB*gorm.DB对象的地方。

一个例子是...

代码语言:javascript
复制
package db

func GetAccountByID(id int, db *gorm.DB) (*model.Account, error) {
  if db == nil {
    db = conn // conn is the package level db connection object
  }      
  //...
}

通常,当服务器启动时,我创建DB连接(作为连接池),因此实际上没有必要将它传递给函数。那么,为什么要这么做呢?好吧,那是因为测试。您不希望DB处理程序访问包级DB连接对象,因为对该函数进行隔离测试会变得更加困难。

因此,此函数签名为您提供了可测试性,如果为DB值传入nil,则初始if条件仍然使用单个中央DB连接对象,除非您正在测试,否则该值始终为nil

这只是一种方法,但我已经成功地使用了很多年。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68199922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档