【发布时间】:2015-09-30 14:11:32
【问题描述】:
在测试数据库方法时,我在 database/sql 包上创建了一个最小的包装器,以允许我针对接口进行测试,而不是设置具体的类(如果不是不可能的话)。但是,当我尝试模拟 sql.Stmt 时出现以下错误:
cannot use *sql.Stmt as type IStmt in return argument:
*sql.Stmt does not implement IStmt (wrong type for Query method)
have Query(...interface {}) (*sql.Rows, error)
want Query(...interface {}) (IRows, error)
这是我的界面:
type IStmt interface {
Query(args ...interface{}) (IRows, error)
QueryRow(args ...interface{}) IRow
}
type IRows interface {
Columns() ([]string, error)
Next() bool
Close() error
Scan(dest ...interface{}) error
Err() error
}
这是问题的方法:
func (c *DbConnection) Prepare(query string) (IStmt, error) {
return c.conn.Prepare(query)
}
我知道 Go 的一大优点是您可以创建自己的接口,并且实现它的任何结构都会自动“实现”它,而无需在 java 中使用 implements 关键字或使用分号,如C# 到子类。为什么它不适用于此返回类型?我是不是做错了什么?
【问题讨论】:
-
*sql.Rows没有实现IStmt,所以不能退货。更改接口以返回具体类型(最快修复)。我还建议阅读Effective Go 并查看您的界面命名(即Queryer或Queryable)和/或阅读robots.thoughtbot.com/interface-with-your-database-in-go -
但是 *sql.Stmt 实现了 Query 方法和 QueryRow 方法,就像我的一样。
Query(args ...interface{}) (*Rows, error)和QueryRow(args ...interface{}) *Row。当然,我使用一个接口来表示*sql.Rows和*sql.Row,但是我使用的方法签名完全一样。如果我将这些方法更改为分别返回*sql.Rows和*sql.Row,它就可以工作。如果 Go 不能处理来自返回类型的嵌套接口,那真是太可惜了!
标签: database unit-testing go