[Go] 为 *sql.DB 和 *sql.Tx 提取公共的查询接口

陪她去流浪 桃子 2018年07月31日 编辑 阅读次数:2840

我博客的API接口部分有一个函数一开始是这样定义的:

1
func (o *OptionManager) Get(db *sql.DB, name string) (string, error)

后面发现这样定义不靠谱, 因为我很有可能需要在事务中调用这个函数。也就是说,还应该这样:

1
func (o *OptionManager) Get(tx *sql.Tx, name string) (string, error)

但是,同样的实现明显不能实现两遍。

考虑到 Get 方法只会调用 Tx/DB 的查询接口,所以我从 Tx/DB 中抽出了公共的查询接口:

1
2
3
4
5
type Querier interface {
	Exec(query string, args ...interface{}) (sql.Result, error)
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row
}

于是,我的接口方法现在改成这样了:

1
func (o *OptionManager) Get(db Querier, name string) (string, error)

这样的接口既支持传入*sql.DB,也支持传入*sql.Tx,可以说很优雅了。

其实我非常好奇,为什么官方没有抽象出这样的公共接口?sql.DB 和 sql.Tx 明明有很多完全相同的方法。

另外,GORM 中也有类似的实现(代码地址):

1
2
3
4
5
6
7
// SQLCommon is the minimal database connection functionality gorm requires.  Implemented by *sql.DB.
type SQLCommon interface {
	Exec(query string, args ...interface{}) (sql.Result, error)
	Prepare(query string) (*sql.Stmt, error)
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row
}

参考:

标签:Go · 数据库