go语言函数变参

作者: CodingCode | 来源:发表于2017-09-22 16:54 被阅读8次

    例子

    函数变参的定义:
    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)
    

    相关文章

      网友评论

        本文标题:go语言函数变参

        本文链接:https://www.haomeiwen.com/subject/qbotextx.html