我正在使用的包gosqlite有一个带有可变参数的方法,其中的类型是空接口.
func (s *Stmt) Exec(args ...interface{}) os.Error
Run Code Online (Sandbox Code Playgroud)
如果明确传递单个参数,我可以调用它:
statement := blah()
error := statement.Exec("hello", 3.0, true) // works fine
Run Code Online (Sandbox Code Playgroud)
但是,由于variadic参数对应于in我的SQL语句的运算符中的占位符select,因此这些占位符的数量在编译时是未知的,但在运行时会根据用户的操作而动态更改.例如,如果用户输入四个值,我最终会得到类似于以下内容的SQL:
SELECT * FROM sky WHERE name IN (?,?,?,?)
Run Code Online (Sandbox Code Playgroud)
所以我很自然地想Exec用一段字符串调用该方法:
var values []string = getValuesFromUser()
statement := createStatementWithSufficientNumberOfPlaceholders(len(values))
_ := statement.Exec(values...) // compiler doesn't like this
Run Code Online (Sandbox Code Playgroud)
这不编译.我可以通过创建一个空的接口切片并复制引用来解决这个问题:
values2 := make([]interface{}, len(values))
for index, value := range values { values2[index] = value }
_ := statement.Exec(values2...) // compiler happy but I'm not
Run Code Online (Sandbox Code Playgroud)
这工作正常,但感觉有点笨重.我想知道是否有一些技巧可以values直接传递给这个函数,或者,如果没有这个,一个更简单的方法将字符串切片转换为空接口一个?
非常感谢.
Ste*_*ark 10
无法[]string直接传递给...interface{}参数.这样做需要线性时间复制(n + 1分配!).如果语言隐藏了这个,那将是一个重要的隐藏成本.通常,将切片传递给可变参数只是将切片传递给函数.
至于其他方法,你可以通过编写一个带有a []string并返回相应的函数来使它更清晰[]interface{}.当然,你必须为每个[]T- []interface{}你想要做的转换再次写它,但它是一个相当短的函数,所有改变的都是签名.您可以使用带有固有运行时成本的反射来使函数"通用",例如:
valuesVal := reflect.ValueOf(values)
...
for i := range values2 { values2[i] = valuesVal.Index(i).Interface() }
Run Code Online (Sandbox Code Playgroud)