为了账号安全,请及时绑定邮箱和手机立即绑定

为sql.DB的Query方法的返回类型实现一个接口

为sql.DB的Query方法的返回类型实现一个接口

Go
繁星淼淼 2022-06-21 10:32:09
我按照本教程模拟数据库连接。但是当我尝试更进一步并为 Query 方法的返回类型实现一个接口时,我得到一个错误。这是不适用于MockDB但适用于的工作版本main:// The DB interfacetype SQLDB interface {    Query(query string, args ...interface{}) (*sql.Rows, error)}type MockDB struct {    // ...}func (m *MockDB) Query(query string, args ...interface{}) (SQLRows, error) {    // var row MockRows    // ...    return rows, nil}// #################################// The Rows interfacetype SQLRows interface {    Next() bool    Scan(dest ...interface{}) error}type MockRows struct {    // ...}func (m *MockRows) Next() bool {    // ...    return true}func (m *MockRows) Scan(dest ...interface{}) error {    // ...    return nil}// #################################// Usagefunc GetStuff(db SQLDB) (*sql.Rows, error) {    results := db.Query("query")    // ...    return results, nil}// #################################// Mainvar db SQLDBfunc main() {    db = sql.Open("driver", "uri")    results := GetResult(db)}// #################################// Testfunc TestGetStuff(t *testing.T) {    mockDB = new(MockDB)    results := GetResult(mockDB)    // ...}这适用于 main,但不适用于测试,并且在运行测试时出现以下错误:*MockDB does not implement SQLDB (wrong type for Query method)    have Query(string, ...interface {}) (SQLRows, error)    want Query(string, ...interface {}) (*sql.Rows, error)这是适用于MockDB但不适用的版本main:// The DB interfacetype SQLDB interface {    Query(query string, args ...interface{}) (SQLRows, error)}type MockDB struct {    // ...}func (m *MockDB) Query(query string, args ...interface{}) (SQLRows, error) { // <<<<<< Changed    // var row MockRows    // ...    return rows, nil}// #################################// The Rows interfacetype SQLRows interface {    Next() bool    Scan(dest ...interface{}) error}type MockRows struct {    // ...}这是错误: *sql.DB does not implement SQLDB (wrong type for Query method)        have Query(string, ...interface {}) (*sql.Rows, error)        want Query(string, ...interface {}) (SQLRows, error)我怎样才能使它适用于两者?还是根本做不到?
查看完整描述

1 回答

?
慕虎7371278

TA贡献1802条经验 获得超4个赞

您可以做的是包装*sql.DB在一个瘦包装器中,该包装器实现SQLDB并且其实现只是将调用委托给 wrapped *sql.DB。


type dbwrapper struct{ db *sql.DB }


func (w *dbwrapper) Query(query string, args ...interface{}) (SQLRows, error) {

    return w.db.Query(query, args...) // delegate

}

现在不是*sql.DB直接使用,而是将其包装在dbwrapper其中,然后可以用作SQLDB接口。


func GetStuff(db SQLDB) (SQLRows, error) {

    // ...

}


func main() {

    db, err := sql.Open("driver", "uri")

    if err != nil {

        panic(err)

    }


    w := &dbwrapper{db}

    rows, err := GetStuff(w) // will compile

    // ...

}


查看完整回答
反对 回复 2022-06-21
  • 1 回答
  • 0 关注
  • 192 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信