一尘不染

将字符串切片传递给可变参数空接口参数

go

我正在使用的软件包gosqlite的方法带有 可变 参数,其类型为 空接口

func (s *Stmt) Exec(args ...interface{}) os.Error

如果显式传递各个参数,我可以称呼它为好:

statement := blah()
error := statement.Exec("hello", 3.0, true) // works fine

但是,由于可变参数与in我的SQL语句的运算符内的占位符相对应select,因此这些占位符的数目在编译时未知,但会在运行时根据用户的操作动态变化。例如,如果用户输入四个值,我最终会得到类似于以下的SQL:

SELECT * FROM sky WHERE name IN (?,?,?,?)

所以自然地我想Exec用一片字符串来调用该方法:

var values []string = getValuesFromUser()
statement := createStatementWithSufficientNumberOfPlaceholders(len(values))
_ := statement.Exec(values...) // compiler doesn't like this

这不会编译。我可以通过创建一个空的接口片并复制引用来解决此问题:

values2 := make([]interface{}, len(values))
for index, value := range values { values2[index] = value }
_ := statement.Exec(values2...) // compiler happy but I'm not

这工作正常,但感觉有点笨拙。我想知道是否有一些技巧可以values直接传递给此函数,或者失败了,将字符串切片转换为空接口的更整洁的方法了吗?

非常感谢。


阅读 187

收藏
2020-07-02

共1个答案

一尘不染

无法将a []string直接传递给...interface{}参数。这样做需要线性时间复制(具有n
+1个分配!)。如果语言对您隐藏了,那将是一笔巨大的隐性成本。通常,将切片传递给可变参数只是将切片传递给函数。

至于其他执行此操作的方法,可以通过编写一个接受a
[]string并返回相应的的函数来使其变得更整洁[]interface{}。当然,您必须为要执行的每个[]T->
[]interface{}转换再次编写它,但是它的功能很短,所有更改都是签名。您可以使用反射(带有固有的运行时成本)来使函数“通用”,例如:

valuesVal := reflect.ValueOf(values)
...
for i := range values2 { values2[i] = valuesVal.Index(i).Interface() }
2020-07-02