dimiguel
dimiguel

Reputation: 1569

Calling the same function on two different structs

I've got two functions that accept different pointers pointing to different structs, but the structs have the same underlying function.

func Save(db *sql.DB) error {
  db.Prepare(query)
}

func TxSave(tx *sql.Tx) error {
  tx.Prepare(query)
}

I don't want to have to make changes in both functions when I need to extend this function in the future. How do I adhere to DRYness in golang with this scenario?

Upvotes: 0

Views: 1016

Answers (2)

Francois
Francois

Reputation: 3080

Create an interface such as:

type SQLRunner interface{
    Prepare(query string) (*sql.Stmt, error)
    PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
    Query(query string, args ...interface{}) (*Rows, error)
    QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
    // add as many method shared by both sql.Tx qnd sql.DB
    // ...
} 

And then create a single method taking that interface:

func Save(s SQLRunner) error {
    s.Prepare()
}

In go interface implementation is implicit, so you just have to pass *sql.Tx or *sql.DB to the save function:

Save(tx)
Save(db)

Here a good blog post about interfaces in go:http://jordanorelli.com/post/32665860244/how-to-use-interfaces-in-go

Upvotes: 2

dimiguel
dimiguel

Reputation: 1569

Wow, I think I'm in love with Go. I can actually just do this by creating my own interface.

type Saver interface {
  Prepare(query string) (*sql.Stmt, error)
}

func Save(db *sql.DB) error {
  return GenericSave(db)
}

func TxSave(tx *sql.Tx) error {
  return GenericSave(tx)
}

func GenericSave(saver Saver) error {
  stmt := saver.Prepare(query)
  // Do rest with saver
}

Upvotes: 0

Related Questions