Golang可变参数函数调用

来源:互联网 发布:ajax股票实时刷新数据 编辑:程序博客网 时间:2024/06/05 17:23

最近,在写代码的过程中,用到了某个任意类型的不定参数接口

package reflectimport (    "fmt")func InterfaceArg() {    interfaceArg := []string{"NetworkSettings","IPAddress"}    receiveAnyType(interfaceArg...)}func receiveAnyType(args ...interface{}) {    for _,arg := range args {        fmt.Println(arg)    }}

希望将传入参数列表元素一一打印出来,但在编译过程中,却出现如下错误

method/reflect/interface_arg.go:9: cannot use interfaceArg (type []string) as type []interface {} in argument to receiveAnyType

在我的认知中,认为interface{},标示函数可以接受任意的对象实例,所以数组切片打散之后,理论上是可行的,但允许却报错

类型查看

首先,我们查看 interfaceArg 及 args 参数类型

package reflectimport (    "fmt"    "reflect")func InterfaceArg() {    interfaceArg := []string{"NetworkSettings","IPAddress"}    fmt.Println(reflect.TypeOf(interfaceArg))    receiveAnyType()}func receiveAnyType(args ...interface{}) {    fmt.Println(reflect.TypeOf(args))    for _,arg := range args {        fmt.Println(arg)    }}

输出结果如下

[]string[]interface {}

从结果中,分析得到

interfaceArg 为一个 string 数组切片;arg 为一个 interface{} 数组切片;虽然 interface{}代表可以接受任意类型对象,但是interface{} 数组切片并不可以接受任意类型对象;此即为调用失败的原因。

解惑

既然 interface{} 数组切片不接受任意类型的对象,那为何将 string 数组切片一个个传入是可以的呢?

package reflectimport (    "fmt")func InterfaceArg() {    interfaceArg := []string{"NetworkSettings","IPAddress"}    fmt.Printf("interfaceArg parameter addres is %p\n",interfaceArg)    fmt.Printf("interfaceArg parameter 0 addres is %p\n",&interfaceArg[0])    receiveAnyType(interfaceArg[0])    fmt.Println()    interfaceArg2 := []interface{}{"NetworkSettings","IPAddress"}    fmt.Printf("interfaceArg2  addres is %p\n",interfaceArg2)    receiveAnyType(interfaceArg2...)}func receiveAnyType(args ...interface{}) {    fmt.Printf("receiveAnyType  arg addres is %p\n",args)}

上面的代码执行过程并不报错,且结果如下

interfaceArg parameter addres is 0xc42006c0c0interfaceArg parameter 0 addres is 0xc42006c0c0receiveAnyType arg addres is 0xc420072230interfaceArg2 addres is 0xc42006c120receiveAnyType arg addres is 0xc42006c120

从结果中,可以分析到

若将 string 数组切片,每项独自传入函数,则会执行[]T{arg1,arg2}等类似操作,从新进行初始化;若将 interface{} 数组切片打散后直接传入函数,则不再进行对象的创建,直接试用该对象;