我正在使用的软件包gosqlite的方法带有 可变 参数,其类型为 空接口 。
func (s *Stmt) Exec(args ...interface{}) os.Error
如果显式传递各个参数,我可以称呼它为好:
statement := blah() error := statement.Exec("hello", 3.0, true) // works fine
但是,由于可变参数与in我的SQL语句的运算符内的占位符相对应select,因此这些占位符的数目在编译时未知,但会在运行时根据用户的操作动态变化。例如,如果用户输入四个值,我最终会得到类似于以下的SQL:
in
select
SELECT * FROM sky WHERE name IN (?,?,?,?)
所以自然地我想Exec用一片字符串来调用该方法:
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直接传递给此函数,或者失败了,将字符串切片转换为空接口的更整洁的方法了吗?
values
非常感谢。
无法将a []string直接传递给...interface{}参数。这样做需要线性时间复制(具有n +1个分配!)。如果语言对您隐藏了,那将是一笔巨大的隐性成本。通常,将切片传递给可变参数只是将切片传递给函数。
[]string
...interface{}
至于其他执行此操作的方法,可以通过编写一个接受a []string并返回相应的的函数来使其变得更整洁[]interface{}。当然,您必须为要执行的每个[]T-> []interface{}转换再次编写它,但是它的功能很短,所有更改都是签名。您可以使用反射(带有固有的运行时成本)来使函数“通用”,例如:
[]interface{}
[]T
valuesVal := reflect.ValueOf(values) ... for i := range values2 { values2[i] = valuesVal.Index(i).Interface() }