I read that you should not close the *sql.DB variable.
http://go-database-sql.org/accessing.html
And it also says that I should: "Pass it around as needed, or make it available somehow globally, but keep it open."
But this article says I should not use global variables but should use closures: https://medium.com/@benbjohnson/structuring-applications-in-go-3b04be4ff091
I found an example of closure here: https://gist.github.com/tsenart/5fc18c659814c078378d
My question is: How should I pass around this variable to different packages?
For example if I have a package called User like this:
package user
import "errors"
var userNotFound = errors.New("User was not found.")
// Should I have a pointer to sql.DB as a property of the User type?
type User struct {
// db *sql.DB
Id int
Email string
Username string
}
// Should I pass in *sql.DB as parameter in the function?
func FindById(id int) (*User, error) {
// Access *sql.DB somehow
// Do query and look if user with id is found
// Should I return an error if the user is not found?
return &User{}, nil
}
Should I then have a pointer to sql.DB as property of the User type? Or should I pass a pointer to it in the findById method?
If I want to find a user by it's id, how should I do all this from a main function like below?
func getUserById(db *sql.DB) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprint(w, ps.ByName("id"))
// I will create a new(User) here, how should I use the *sql.DB in the user package?
}
}
func main() {
dsn := fmt.Sprintf("%s:%s@%s(%s:%s)/%s?charset=utf8",
cfg.DbUser, cfg.DbPass, cfg.DbProtocol, cfg.DbAddress, cfg.DbPort, cfg.DbName)
db, err := sql.Open("mysql", dsn)
err = db.Ping()
if err != nil {
log.Fatal(err)
}
router := httprouter.New()
router.GET("/api/user/:id", getUserById(db))
router.NotFound = &DefaultHandler{}
log.Fatal(http.ListenAndServe(":8080", router))
}
How should I this? What is a good preferred way, or kind of a best practice?