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 ofrows
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 withinrows.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.
CodePudding user response:
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.
-
- Regardless of the fact that the
rows
here has the same reference while being shared between 2 queries (so onerows.Close()
call would suffice, unless the library has some special implementation), defining two variables is cleaner, likeuserRows
andbookRows
.
- Regardless of the fact that the
-
- Although I already said that I have not worked with
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...)
- Although I already said that I have not worked with
-
- Regarding your second question, it depends on what you mean by "ok". Since your doing some synchronous iteration, I don't think it would result into bugs, but when it comes to coding style, personally, I wouldn't do this.
-
- I think that the best thing to do in your case is this:
I think this code is easier to read/maintain. You won't face the variable reassignment and other issues.// 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 }
You can take a look at the go-pg documentations for more details on how to improve your query.