亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

從 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 關注
  • 108 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號