Golang可变参数函数调用

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

package reflect

import (
    "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 reflect

import (
    "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 reflect

import (
    "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 0xc42006c0c0
interfaceArg parameter 0 addres is 0xc42006c0c0
receiveAnyType arg addres is 0xc420072230

interfaceArg2 addres is 0xc42006c120
receiveAnyType arg addres is 0xc42006c120

从结果中,可以分析到

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

没有更多推荐了,返回首页