将[] interface {}转换为非可变参数函数的参数

时间:2015-12-10 16:37:51

标签: go

我正在寻找一种在Go中解压缩参数列表的优雅方法。我不想为此目的使用可变参数函数,因为在我的用例中编写函数时我已经知道了参数的数量,我想保持这部分简单。但是在我的用例中,参数以[]interface{}的形式到达。 我找不到解决办法,但嘿,也许有人知道该怎么做?

package main

import (
    "fmt"
)

// NON-VARIADIC greater
func greet(n1, n2 string) {
    fmt.Printf("%s %s\n", n1, n2)
}


func main() {
    l := []interface{}{"hello", "world"}

    // works
    greet(l[0].(string), l[1].(string))

    // does not work: "./args.go:20: not enough arguments in call to greet"
    //greet(l...)

    // is there something more elegant to unzip the list?
}

2 个答案:

答案 0 :(得分:2)

你可以创建一个"泛型"调用者使用reflect包,虽然这会带来开销并且缺乏类型安全性。除非你遇到一些特殊的情况,并且不知道你想在代码中调用什么,否则使用你问题中的代码片段会更明智,但你认为不优雅。

反射的示例用法可能是您的起点:

package main

import (
    "fmt"
    "reflect"
)

func call(f interface{}, args []interface{}) {
    // Convert arguments to reflect.Value
    vs := make([]reflect.Value, len(args))
    for n := range args {
        vs[n] = reflect.ValueOf(args[n])
    }
    // Call it. Note it panics if f is not callable or arguments don't match
    reflect.ValueOf(f).Call(vs)
}

func greet(n1, n2 string) {
    fmt.Printf("%s %s\n", n1, n2)
}

func main() {
    l := []interface{}{"hello", "world"}
    call(greet, l)
}

// Output: hello world

https://play.golang.org/p/vbi3CChCdV

答案 1 :(得分:1)

我不太确定你要做什么。如果你想要一种方法轻松地将两个空接口的切片传递给一个接受两个字符串的函数,你可以创建一个小帮手:

func twoStrings(vs []interface{}) (string, string) {
    return vs[0].(string), vs[1].(string)
}

将其用作

greet(twoStrings(l))

游乐场:http://play.golang.org/p/R8KFwMUT_V

但老实说,似乎你做错了什么,试图让Go类型系统做一些它不能做的事情。