【发布时间】:2018-05-30 13:30:40
【问题描述】:
我试图抽象出我对 MySQL 数据库的使用,但我遇到了一个错误。
有一个对象我会举个例子:
package models
// Product : The Product's model
type Product struct {
ID int
Name string
Price int
PictureURL string
}
我将尝试在我的数据库中检索产品id = 1。为此,假设我已经与我的数据库建立了连接,该连接由下一个变量表示:
var databaseMySQL *sql.DB
为了查询我的数据库,我使用了这个函数:
// QueryMySQL query our MySQL database
func QueryMySQL(sqlquery model.SQLQuery) model.Status {
// prepare the query
stmtOut, err := databaseMySQL.Prepare(sqlquery.Query)
if err != nil {
return model.Status{Code: http.StatusInternalServerError, Error: err}
}
defer stmtOut.Close()
// Run the query
err = stmtOut.QueryRow(sqlquery.Args).Scan(sqlquery.Dest)
if err != nil {
return model.Status{Code: http.StatusInternalServerError, Error: err}
} else {
return model.Status{Code: http.StatusOK, Error: nil}
}
}
这里使用的 2 个模型是 SQLQuery 和 Status。
package models
type SQLQuery struct {
Query string
Args []interface{}
Dest []*interface{}
}
Status 基本上只包含一个error 和一个int。
所以,既然Scan()作为下面的原型Scan func(dest ...interface{}) error,我可以传递一个[]*interface{}作为参数。
如果我是对的,那么我应该能够让我的 Dest 的元素由T 类型元素填充,然后将它们转换/转换为我需要的类型?
func GetProductByID(ID int) (model.Product, model.Status) {
// "SELECT ID, Name, Price, PictureURL FROM Products WHERE ID = ?"
var _product model.Product
// HERE IS THE PROBLEM
var dest []*interface{}
append(dest, &_product.Name)
append(dest, &_product.Price)
append(dest, &_product.PictureURL)
// HERE IS THE PROBLEM
status := QueryMySQL(model.SQLQuery{
Query: "SELECT Name, Price, PictureURL FROM Products WHERE ID = ?",
Args: []interface{}{ID},
Dest: dest})
return _product, model.Status{Code: http.StatusOK, Error: nil}
}
PS:这个功能只是一个基本的测试,试试我的逻辑
但是,我收到一个错误:
不能在追加中使用 &_product.Name (type *string) 作为 type *interface {}: *interface {} 是指向接口的指针,而不是接口
对我来说,有两个错误:
cannot use &_product.Name (type *string) as type *interface {}*interface {} is pointer to interface, not interface
首先,为什么我不能使用接口来存储我的字符串?
其次,既然我在字符串上传递一个指针,那么interface{} 是怎么回事?它应该是 *interface{},不是吗?
正确的代码,感谢 David Budworth 的回答
除了给定的代码之外,您还可以像我一样通过在切片变量名称后添加... 将切片作为可变参数传递
mysqlproduct.go
// GetProductByID returns a Product based on a given ID
func GetProductByID(ID int) (model.Product, model.Status) {
_product := model.Product{
ID: ID}
status := QueryMySQL(&model.SQLQuery{
Query: "SELECT Name, Price, PictureURL FROM Products WHERE ID = ?",
Args: []interface{}{_product.ID},
Dest: []interface{}{&_product.Name, &_product.Price, &_product.PictureURL}})
if status.Code != http.StatusOK {
return _product, status
}
return _product, model.Status{Code: http.StatusOK, Error: ""}
}
mysql.go
// QueryMySQL query our MySQL database
func QueryMySQL(sqlquery *model.SQLQuery) model.Status {
stmtOut, err := databaseMySQL.Prepare(sqlquery.Query)
if err != nil {
return model.Status{Code: http.StatusInternalServerError, Error: err.Error()}
}
defer stmtOut.Close()
// Run the query
err = stmtOut.QueryRow(sqlquery.Args...).Scan(sqlquery.Dest...)
if err != nil {
return model.Status{Code: http.StatusInternalServerError, Error: err.Error()}
}
defer stmtOut.Close()
return model.Status{Code: http.StatusOK, Error: ""}
}
【问题讨论】:
-
节省自己的时间,请查看github.com/volatiletech/sqlboiler
标签: mysql pointers go interface slice