如何使用接口为 Golang 中的数据库实现依赖注入



我有以下代码,它尝试通过数据库实现依赖注入,以便我稍后可以在测试中模拟它。

问题是编译器无法将 db 识别为实现接口:cannot use db (type *sqlx.DB) as type storage in field value: *sqlx.DB does not implement storage.

package main
func main() {
db, _ := database.NewDB()
api, _ := controllers.NewAPI(db)
api.Register(data)
}

控制器/main.go

package controllers
type storage interface {
AccountExists(id int64)
}
type API struct {
storage
}
func NewAPI(db *sqlx.DB) (*API, error) {
return &API{db}, nil
}
func (api *API) Register(userdata) {
// register user here
}

storage/database.go

package database
func NewDB() (*sqlx.DB, error) {
// connect to db ere
return database, nil
}
type DB struct {
*sqlx.DB
}
func (db *DB) Account(id int64) (bool, error) {
// query db here
}

我尝试在controllers中实现类型DB,但如果我不在database中声明它,我就无法在那里定义它的方法,如果我在两者中声明它,编译器不会将其识别为实现接口。我想我已经接近实现这一点了,但我真的已经尝试了我能想到的一切。

你走在正确的轨道上,但与接口相关的代码中存在一些错误。

为了使结构实现您的storage接口,它需要一个带有签名AccountExists(id int64)的方法。根据规范 (https://godoc.org/github.com/jmoiron/sqlx#DB(,sqlx.Db没有具有此签名的方法。

你需要做的是这样的:

package database
func NewMyDB() (*MyDB, error) {
dbConnection := // get an *sqlx.DB instance
return &MyDB{db: dbConnection}, nil
}
type MyDB struct {
db *sqlx.DB
}
func (db *MyDB) AccountExists(id int64) {
// query db here
}

控制器:

type storage interface {
AccountExists(id int64)
}
type API struct {
db storage
}
func NewAPI(db storage) (*API, error) {
return &API{db}, nil
}

请注意几件事。1. 以前,您的NewMyDB构造函数返回的是sqlx.DB的实例,而不是结构的实例(我将其重命名为MyDB以避免与sqlx.DB类混淆(。2.以前,您的MyDB结构没有带有签名AccountExists(id int64)的方法。因此,它没有实现storage因为storage需要这种方法。

我建议阅读一些关于 Golang 中接口如何工作的信息。我认为这将对解决您在这里的问题有很大帮助。这里有一个链接,你可以检查快速阅读(其中包括另一个指向更长但有用的博客文章的链接(:https://gobyexample.com/interfaces