Why not use an interface?
type TableSaver func (db *DB)
or
type TableSaver func (tx *Tx) // depending on your needs
Allowing you to:
func (t *Table) SaveTable (...) {}
Which in your example if you wanted use a different SaveTable
implementation for OtherTable you could. Otherwise it would just inherit it
from Table.
Or am I missing something here?
Chris
On Friday, 5 January 2018 16:11:53 UTC, Manlio Perillo wrote:
>
> 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 [email protected].
For more options, visit https://groups.google.com/d/optout.