Il giorno venerdì 5 gennaio 2018 16:57:04 UTC+1, Ayan George ha scritto: > > > > On 01/05/2018 10:16 AM, Manlio Perillo wrote: > > Recently I have developed a few web applications in Go, using a > > PostgreSQL database, but I have yet understand the best way to use > > the database/sql package. > > > > I don't know how you're serving web pages but I typically use net/http. > This also means that I typically build an http.Server. This requires > that I create a type that conforms to the http.Handler interface. >
Yes, I use the standard net/http interface, without frameworks (but I use a simple toolkit written by me). > > You can use this type to pass around all of the data you need, including > sql.DB instances, log.Logger, etc. > > So here's the skeleton of what I normally do. I haven't tested this -- > this is just to get the point across. Finally, this may be completely > off base. I'm open to any criticisms etc. anyone may have. > > package main > > import ( > "database/sql" > _ "github.com/lib/pq" > "log" > "net/http" > "time" > ) > > type app struct { > db *sql.DB > } > > func (a *app) ServeHTTP(w http.ResponseWriter, r *http.Request) { > // here we can use all of the fields of our app struct -- including > the db! > > row := db.QueryRow("select current_timestamp;") > > var time string > err := row.Scan(&time) > > if err != nil { > // handle the error. maybe log it? i typically > // create a log.Logger instance in my app and use it > // at times like these. > return > } > > w.Write([]byte("<h1>hello, world!</h1>")) > } > > func main() { > db, err := sql.Open("postgres", "...") > > if err != nil { > log.Fatal(err) > } > > if err := db.Ping(); err != nil { > log.Fatal(err) > } > > myapp := app{ > db: db, > } > > srv := http.Server{ > Addr: ":8080", > ReadTimeout: 1 * time.Second, > WriteTimeout: 1 * time.Second, > Handler: &myapp, > } > > log.Fatal(srv.ListenAndServe()) > } > Thanks, this is a very good solution. Currently I'm using something different, however. I have a package that exports the same API as database/sql, but as free functions using a global *DB configured when loading a configuration file. However the question is the same, and it is how and what to pass to functions that need a connection to the database. Passing *DB is no good; take as an example a "generic" package having type Table struct { A int B string } func SaveTable(t *Table, db *DB) ... or func SaveTable(t *Table, tx *Tx) ... The function does not need to know if it is inside a transaction; it is the responsibility of the caller. However consider a package with type Table struct { A int B string } type OtherTable struct { Table C float64 B bool } Now the function SaveOtherTable may want to use a transaction to save Table and OtherTable separately. You surely can not pass a *Tx, since it does not support nested transactions. Thanks Manlio Perillo -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.