例子
函数变参的定义:
func Printf(format string, a ...interface{}) (n int, err error) { ... }
调用方式
Printf("%s-%d-%s", "AAA", 123, "BBB")
传递方式
在函数调用的时候,caller会把所有的变参转换成一个slice对象,然后传递给callee,
package main
import "fmt"
import "reflect"
func foo1(args ...string) {
fmt.Println("=====foo1()====")
fmt.Println("Type=", reflect.TypeOf(args))
fmt.Println("Value=", reflect.ValueOf(args))
fmt.Println(args)
}
func main() {
foo1("aaa", "bbb", "ccc")
}
运行结果为:
$ go build && ./main
=====foo1()====
Type= []string
Value= [aaa bbb ccc]
[aaa bbb ccc]
可以很清楚的看到在foo1函数内,args的类型是[]string是一个slice.
main函数内容可以这么写,能产生同样的结果:
func main() {
//foo1("aaa", "bbb", "ccc")
params := []string{"aaa", "bbb", "ccc"}
foo1(params...) // notice: not foo1(params)
}
如何变参传递给其他变参函数
这里我们讨论的是如何传递变参给另一个变参函数,如果对象不是一个变参函数,那么调用者可以分析slice得到每一个元素,这样就随便处理了。
把变参作为整体传给另一个变参函数也很容易,使用"args..."就行,例如上述代码再调用fmt.Printf
package main
import "fmt"
import _ "reflect"
func foo1(args ...interface{}) {
fmt.Printf("%s-%s-%s", args...)
}
func main() {
foo1("aaa", "bbb", "ccc")
}
运行结果
$ go build && ./main
aaa-bbb-ccc
如果没有使用args...,而是直接使用了args会出什么结果呢?
package main
import "fmt"
import _ "reflect"
func foo1(args ...interface{}) {
fmt.Printf("%s-%s-%s", args)
}
func main() {
foo1("aaa", "bbb", "ccc")
}
运行结果:
$ go build && ./main
[aaa bbb ccc]-%!s(MISSING)-%!s(MISSING)
这里因为"%s-%s-%s",需要三个string类型来匹配,而args作为整体只能算是提供了第一个参数。所以导致
第一个%s <- args, 即[]string {"aaa", "bbb", "ccc"}
第二个%s <- 没有值
第三个%s <- 没有值
常用场景
这个需求经常被用在自定义log输出的场合。比如
func myInfo(formating string, args ...interface{}) {
// fmt.Printf(fInfoormating+"\n", args...)
fmt.Printf("INFO: %s", fmt.Sprintf(formatting, args...))
}
func myDebug(formating string, args ...interface{}) {
// fmt.Printf(fInfoormating+"\n", args...)
fmt.Printf("DEBUG: %s", fmt.Sprintf(formatting, args...))
}
调用者
myInfo("Hello World");
myDebug("This is the %d bug", 12)
myDebug("This %s are %d", "AAA", 20)
网友评论