I am trying to build a REST API with go-chi and Gorm.
I am not sure how I should pass the Gorm DB instance to the route handlers.
Or if I should create one instance per handler, which does not sound right to me.
Should I use middleware, dependency injection or other? What would be recommended pattern here?
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)
}
}
Use methods instead of functions. This allows you to pass any information needed by the handlers using the receiver of those methods:
type MyHandler struct {
DB *gorm.DB
}
func (m MyHandler) IndexHandler(w http.ResponseWriter, r *http.Request) {
// Use m.DB here
}
In main:
handler:=mypkg.MyHandler{DB:gormDB}
r.Get("/", handler.IndexHandler)
In some cases, a closure makes more sense.
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))