Indeed. The strength of Go's interfaces is precisely that a library 
provider does not need to create interfaces, unless they are critical to 
the implementation of the library. You should create these types of 
interfaces when you need them.

There's a subtle versioning problem here. If Go adds a method that applies 
to both the DB and Tx objects, the proposed interface could not add the 
method in question without breaking the compatibility promise. So that 
would mean an interface with a similar purpose but a new name, in order to 
maintain compatibility.

There are differences in meaning between performing operations on the DB 
object vs. performing them on the Tx. Only in your code own do you know if 
it is safe to hide these distinctions behind an interface.

In a transaction, it isn't necessary to close a statement after it is used, 
because it will be closed when the transaction ends 
<https://golang.org/pkg/database/sql/#Tx.Prepare>, whereas with the DB 
connection, explicit close is necessary 
<https://golang.org/pkg/database/sql/#DB.Prepare>.

The sql package has really good reasons for forcing the clients to think 
about what they really need, rather than providing the proposed interface.

Eric.

On Thursday, January 16, 2020 at 9:36:50 AM UTC-8, Marcin Romaszewicz wrote:
>
> I have that exact interface in all of my DB code, and I never use sql.Tx 
> or sql.DB directly. You don't need Go's libraries to adopt this at all, 
> just use your own.
>
> On Wed, Jan 15, 2020 at 11:20 PM Mhd Shulhan <m.sh...@gmail.com 
> <javascript:>> wrote:
>
>> ## Problem
>>
>> At some point we have a function that receive an instance of database 
>> connection to query rows in specific table.
>>
>> Let's say that function F() accept DB that query table T.
>>
>> If function F() called with DB instance, it will query only rows that has 
>> been committed into database.
>>
>> IF function F() called with Tx instance, it will query all rows including 
>> the one that has not been committed yet into database.
>>
>> Since DB and Tx are different types, we will have two functions that 
>> almost have identical code,
>>
>> func F(db *sql.DB) (output int) {
>>   q := `SELECT … FROM T WHERE …`
>>   err := db.QueryRow(q).Scan(&output)
>>   …
>>   return output
>> }
>>
>> func FWithTx(tx *sql.Tx)(output int) {
>>   q := `SELECT … FROM T WHERE …`
>>   err := tx.QueryRow(q).Scan(&output)
>>   …
>>   return output
>> }
>>
>>
>> ## Proposed solution
>>
>> Add an interface Session (the name is not fixed yet) to package sql with 
>> the following signature,
>>
>> type Session interface {
>>     func Exec(query string, args ...interface{}) (Result, error)
>>     func ExecContext(ctx context.Context, query string, args 
>> ...interface{}) (Result, error)
>>     func Prepare(query string) (*Stmt, error)
>>     func PrepareContext(ctx context.Context, query string) (*Stmt, error)
>>     func Query(query string, args ...interface{}) (*Rows, error)
>>     func QueryContext(ctx context.Context, query string, args 
>> ...interface{}) (*Rows, error)
>>     func QueryRow(query string, args ...interface{}) *Row
>>     func QueryRowContext(ctx context.Context, query string, args 
>> ...interface{}) *Row
>> }
>>
>> Session interface is combination of DB and Tx that contains all identical 
>> methods.
>>
>>
>> ## Rationale
>>
>> Without Session, user will have two functions that have the same code,
>>
>> By using Session, we can minimise duplicate code in the user level. for 
>> example using the previous problems definition the function F() become one,
>>
>> func F(session sql.Session)(output int) {
>>   q := `SELECT … FROM T WHERE …`
>>   err := session.QueryRow().Scan(&output)
>>   …
>>   return output
>> }
>>
>>
>> ## Discussion
>>
>> Any thought about this proposal?
>>
>> -- 
>> 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 golan...@googlegroups.com <javascript:>.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/C8AB29FF-7A85-445A-B09E-A0E7CB322A4C%40gmail.com
>> .
>>
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/9f4cab90-67e0-4f85-83d9-8e4f4e8c0ff7%40googlegroups.com.

Reply via email to