猿问

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

我按照本教程模拟数据库连接。但是当我尝试更进一步并为 Query 方法的返回类型实现一个接口时,我得到一个错误。


这是不适用于MockDB但适用于的工作版本main:


// The DB interface

type 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 interface

type 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

}



// #################################


// Usage


func GetStuff(db SQLDB) (*sql.Rows, error) {

    results := db.Query("query")

    // ...

    return results, nil

}


// #################################


// Main

var db SQLDB

func main() {

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

    results := GetResult(db)

}


// #################################


// Test

func 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 interface

type 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 interface

type 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)

我怎样才能使它适用于两者?还是根本做不到?


繁星淼淼
浏览 193回答 1
1回答

慕虎7371278

您可以做的是包装*sql.DB在一个瘦包装器中,该包装器实现SQLDB并且其实现只是将调用委托给 wrapped *sql.DB。type dbwrapper struct{ db *sql.DB }func (w *dbwrapper) Query(query string, args ...interface{}) (SQLRows, error) {&nbsp; &nbsp; return w.db.Query(query, args...) // delegate}现在不是*sql.DB直接使用,而是将其包装在dbwrapper其中,然后可以用作SQLDB接口。func GetStuff(db SQLDB) (SQLRows, error) {&nbsp; &nbsp; // ...}func main() {&nbsp; &nbsp; db, err := sql.Open("driver", "uri")&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; w := &dbwrapper{db}&nbsp; &nbsp; rows, err := GetStuff(w) // will compile&nbsp; &nbsp; // ...}
随时随地看视频慕课网APP

相关分类

Go
我要回答