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

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

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

Go
慕妹3146593 2022-09-12 16:31:19
我正在尝试使用go-chi和Gorm构建一个REST API。我不确定应如何将 Gorm 数据库实例传递给路由处理程序。或者,如果我应该为每个处理程序创建一个实例,这听起来不对。我应该使用中间件、依赖注入还是其他?这里推荐的模式是什么?package mainimport (    "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)    }}
查看完整描述

3 回答

?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

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


type MyHandler struct {

  DB *gorm.DB

}


func (m MyHandler) IndexHandler(w http.ResponseWriter, r *http.Request) {

  // Use m.DB here

}

主要内容:


handler:=mypkg.MyHandler{DB:gormDB}

r.Get("/", handler.IndexHandler)

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


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))


查看完整回答
反对 回复 2022-09-12
?
白衣染霜花

TA贡献1796条经验 获得超10个赞

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

这里很好地记录了组织数据库访问的多种方法。选择适合您需求的一个。


查看完整回答
反对 回复 2022-09-12
?
繁星coding

TA贡献1797条经验 获得超4个赞

在数据库/查询函数本身中。我个人为控制器制作了一个单独的包,为服务制作了一个单独的包。我在控制器(具有我的处理程序函数)中处理所有请求验证和HTTP内容。然后,如果一切都检查出来,我打电话给一个服务包。服务包是调用数据库以及任何其他服务或 API 集成的服务包。


然而,无论你在哪里调用数据库,通常你都会调用一个包,该包具有一堆具有友好名称的查询函数,例如或类似名称。好吧,该函数正是您传递或对象的位置。dbdb.GetAccountByIDdb*sql.DB*gorm.DB


一个例子是...


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

  }      

  //...

}

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


因此,此函数签名为您提供了可测试性,并且初始条件仍然使用单个中央数据库连接对象(如果为数据库值传入),除非您正在测试,否则该对象始终是。ifnilnil


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


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

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号