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 golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to