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

Mak*_*toE 3 go

我想Scan()在 package 中使用sql,但列数以及参数数将在运行时发生变化。这是签名Scan()

func (rs *Rows) Scan(dest ...interface{}) error
Run Code Online (Sandbox Code Playgroud)

根据文档,*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())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编译失败,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())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

sse*_*lla 6

首先,您不能使用[]*interface{}指向接口的指针切片,而不是[]interface{}接口是指针的位置。[]*interface{}不同于[]interface{}. 只需创建一个接口片段,其中每个元素都是一个指向具体类型的指针。

这是您将如何执行此操作的片段。

var x int
var s string

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

rows.Scan(data...)
Run Code Online (Sandbox Code Playgroud)

关于使用...扩展运算符的注意事项。

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

golang:结构切片!=它实现的接口切片?

无法将 []string 转换为 []interface {}