dongwuxie5112 2017-12-16 16:10
浏览 64
已采纳

切片的MySQL查询抽象接口

I am trying to abstract my uses of my MySQL database and I'm stuck on a error.

There is the object I will take as example:

package models

// Product : The Product's model
type Product struct {
    ID         int
    Name       string
    Price      int
    PictureURL string
}

I'm going to try to retrieve the Product id = 1 in my database. For that, let's say that I already have a connection to my database which is represented by the next variable:

var databaseMySQL *sql.DB

In order to query my database, I am using this function:

// 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}
    }
}

The 2 models used over here are SQLQuery & Status.

package models

type SQLQuery struct {
    Query string
    Args  []interface{}
    Dest  []*interface{}
}

Status just basically contains an error and an int.

So, since Scan() as the following prototype Scan func(dest ...interface{}) error, I can pass a []*interface{} as parameter.

If I'm right, then I should be able to get my Dest's elements filled by T type element, and then cast/transform them into the types I need?

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: this function is just a basic test to try my logic

However, I am getting an error:

cannot use &_product.Name (type *string) as type *interface {} in append: *interface {} is pointer to interface, not interface

To me, there is two errors:

  • cannot use &_product.Name (type *string) as type *interface {}
  • *interface {} is pointer to interface, not interface

First, why can't I use a interface to store my string?

Second, since I am passing a pointer on string, what's the matter with interface{}? it should be *interface{}, doesn't it?


The correct code, thanks to David Budworth for his answer

In addition to the given code, you can pass slice as varargs like I did by adding ... after your slice variable's name

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: ""}
}
  • 写回答

1条回答 默认 最新

  • doujing6053 2017-12-16 16:38
    关注

    Interfaces can hold pointers. There is rarely a reason to make a pointer to an interface.

    If you change your type to []interface{} it should work.

    If you really want pointers to interfaces, for some reason, you'd have to first store the field in an interface, then get a pointer to that.

    ie:

    var i interface{} = &_product.Name
    append(dest, &i)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料