I'm new to Go, so sorry for the silly question in advance!
I'm using Gin framework and want to make multiple queries to the database within the same handler (database/sql
+ lib/pq
)
userIds := []int{}
bookIds := []int{}
var id int
/* Handling first query here */
rows, err := pgClient.Query(getUserIdsQuery)
defer rows.Close()
if err != nil {
return
}
for rows.Next() {
err := rows.Scan(&id)
if err != nil {
return
}
userIds = append(userIds, id)
}
/* Handling second query here */
rows, err = pgClient.Query(getBookIdsQuery)
defer rows.Close()
if err != nil {
return
}
for rows.Next() {
err := rows.Scan(&id)
if err != nil {
return
}
bookIds = append(bookIds, id)
}
I have a couple of questions regarding this code (any improvements and best practices would be appreciated)
Does Go properly handle defer rows.Close()
in such a case? I mean I have reassignment of rows
variable later down the code, so will compiler track both and properly close at the end of a function?
Is it ok to reuse id
shared var or should I redeclare it while iterating within rows.Next()
loop?
What's the better approach of having even more queries within one handler? Should I have some kind of Writer
that accepts query and slice and populate it with ids retrieved?
Thanks.
I've never worked with go-pg
library, and my answer is mostly focused on the other stuff, which are generic, and are not specific to golang or go-pg.
rows
here has the same reference while being shared between 2 queries (so one rows.Close()
call would suffice, unless the library has some special implementation), defining two variables is cleaner, like userRows
and bookRows
.go-pg
, I believe that you wont need to iterate through rows and scan the id for all the rows manually, I believe that the lib has provided some API like this (based on the quick look on the documentations):userIds := []int{}
err := pgClient.Query(&userIds, "select id from users where ...", args...)
// repo layer
func getUserIds(args whatever) ([]int, err) {...}
// these can be exposed, based on your packaging logic
func getBookIds(args whatever) ([]int, err) {...}
// service layer, or wherever you want to aggregate both queries
func getUserAndBookIds() ([]int, []int, err) {
userIds, err := getUserIds(...)
// potential error handling
bookIds, err := getBookIds(...)
// potential error handling
return userIds, bookIds, nil // you have done err handling earlier
}
I think this code is easier to read/maintain. You won't face the variable reassignment and other issues.You can take a look at the go-pg documentations for more details on how to improve your query.