如何将* interface {}的一部分作为参数传递?

时间:2018-12-07 07:46:53

标签: go

我想在软件包sql中使用Scan(),但是列数以及参数的数目将在运行时改变。这是Scan()的签名:

func (rs *Rows) Scan(dest ...interface{}) error

根据文档,*interface{}Scan()接受的类型之一。因此,我想创建一个[]*interface{}的切片,并将其作为参数扩展。

这是我认为可行的方法:

func query(database *sql.DB) {
    rows, _ := database.Query("select * from testTable")

    for rows.Next() {
        data := make([]*interface{}, 2)
        err := rows.Scan(data...) // Compilation error
        fmt.Printf("%v%v\n", *data[0], *data[1])
        if err != nil {
            fmt.Println(err.Error())
        }
    }
}

编译失败,cannot use data (type []*interface {}) as type []interface {} in argument to rows.Scan。我认为data...会扩展为&data[0], &data[1],但显然不会。我不明白该错误信息。 *interface{}interface{}兼容,所以为什么不能扩展指向接口类型的指针?

这有效:

func query(database *sql.DB) {
    rows, _ := database.Query("select * from testTable")

    for rows.Next() {
        data := make([]*interface{}, 2)
        err := rows.Scan(&data[0], &data[1]) // Only changed this line
        fmt.Printf("%v%v\n", *data[0], *data[1]) // Outputs "[48][116 101 120 116]"
        if err != nil {
            fmt.Println(err.Error())
        }
    }
}

但是我不能使用它,因为在编译时列数是未知的。如何编写此代码,以便可以将可变数量的*interface{}传递给rows.Scan()

1 个答案:

答案 0 :(得分:3)

首先,在接口是指针的情况下,切勿使用[]*interface{}指针的切片来接口,而不能使用[]interface{}[]*interface{}[]interface{}不同。只需创建一片接口,其中每个元素都是指向具体类型的指针。

以下是您如何执行此操作的摘要。

var x int
var s string

data := []interface{}{&x, &s}

rows.Scan(data...)

请注意使用...扩展运算符。

以下是一些相关的问题,这些问题将进一步解释:

golang: slice of struct != slice of interface it implements?

Cannot convert []string to []interface {}