Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Pass db to router functions #932

Closed
ghost opened this issue Jun 3, 2017 · 5 comments
Closed

How to Pass db to router functions #932

ghost opened this issue Jun 3, 2017 · 5 comments
Labels

Comments

@ghost
Copy link

ghost commented Jun 3, 2017

I'm opening the sqlite database in the main function

db, err := sql.Open("sqlite3", "./libreread.db")
CheckError(err)
defer db.Close()

And I have these router handlers

r.GET("/", GetHomePage)
r.GET("/signin", GetSignIn)
r.POST("/signin", PostSignIn)
...

How to pass that db value through the router handler func PostSignin(c *gin.Context) ?

So that I could avoid opening and closing the database each time in the functions.

Thanks!

@nazwa
Copy link

nazwa commented Jun 3, 2017

I usually create a middleware that sets a context value.

func Site(activeSite *sites.Site) gin.HandlerFunc {
	return func(c *gin.Context) {

		c.Set(constants.CONTEXT_SITE, activeSite)
		c.Next()
	}
}
	r.Use(middleware.Site(site))

And then inside your handler:

	site := c.MustGet(constants.CONTEXT_SITE).(*sites.Site)

Same concept applies to database objects :)

@easonlin404
Copy link
Contributor

@mysticmode you can put db into a custom Env type:

type Env struct {
	db *sql.DB
}

func (e *Env) GetHomePage(c *gin.Context) {
	//e.db.Query("SELECT * FROM USER")
	//omitted..
}
func (e *Env) GetSignIn(c *gin.Context) {
	//omitted...
}

func (e *Env) PostSignIn(c *gin.Context) {
	//omitted...
}

func main() {
	db, _ := sql.Open("sqlite3", "./libreread.db")

	r := gin.New()

	env := &Env{db: db}
	r.GET("/", env.GetHomePage)
	r.GET("/signin", env.GetSignIn)
	r.POST("/signin", env.PostSignIn)
}

@nazwa nazwa closed this as completed Jun 14, 2017
d5ve added a commit to d5ve/catch-up that referenced this issue Apr 26, 2018
+ Poke the db handle into an Env struct so all the routes can access it.
gin-gonic/gin#932
@McGiver-
Copy link

@mysticmode you can put db into a custom Env type:

type Env struct {
	db *sql.DB
}

func (e *Env) GetHomePage(c *gin.Context) {
	//e.db.Query("SELECT * FROM USER")
	//omitted..
}
func (e *Env) GetSignIn(c *gin.Context) {
	//omitted...
}

func (e *Env) PostSignIn(c *gin.Context) {
	//omitted...
}

func main() {
	db, _ := sql.Open("sqlite3", "./libreread.db")

	r := gin.New()

	env := &Env{db: db}
	r.GET("/", env.GetHomePage)
	r.GET("/signin", env.GetSignIn)
	r.POST("/signin", env.PostSignIn)
}

would this not effect performance since the environment receiver will be needed for every request which essentially makes it synchronous or at the very least is vulnerable to a data race?

@Demuzx
Copy link

Demuzx commented May 4, 2019

Just open db connection as global concurrency variable and get access to it from any function, goroutine etc.

// DB is safe to be accessed from multiple goroutines
// https://golang.org/pkg/database/sql/#DB
var DBPointer, _ = sql.Open("sqlite3", "./libreread.db")

func DBTestHandler(c *gin.Context) {
	rows, err := DBPointer.Query("select * from Products")
	if err != nil {
		panic(err)
	}
	defer rows.Close()
}

func main() {
	r := gin.New()
	r.GET("/test", DBTestHandler)
	srv := &http.Server{
		Handler:      r,
		Addr:         "127.0.0.1:5050",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}
	log.Fatal(srv.ListenAndServe())
}```

@nazwa
Copy link

nazwa commented May 7, 2019

@McGiver- No, this is totally fine. The database object is safe to use asynchronously. And also, you should treat the struct as a holder object only / something to group your endpoints in, and not as an active data source for operations within your handler functions if that makes any sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants