Reputation: 1569
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
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
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