Go进阶04 函数闭包和不定参数

2017-08-24 16:06:54
  • 匿名函数
    在了解闭包之前,我们先说下什么是匿名函数,匿名函数由一个不带函数名的函数声明和函数体组成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    func (a, b int, z float64) bool {
    return a*b < int(z)
    }

    //匿名函数可以赋值给一个变量
    f := func(x, y int) int {
    return x + y
    }

    func(ch chan int) {
    ch <-ACK
    }(reply_chan) //直接跟参数表示函数调用
  • 闭包
    Go的匿名函数就是一个闭包,闭包是可以包含自由变量的代码块,这些变量不在这个代码块内或者任何全局上下文中定义,而是在定义代码块的环境中定义.
    要执行的代码块(由于自由变量包含在代码块中,这些自由变量以及他们引用的对象没有被释放)为自由变量提供绑定的计算环境(作用域)

    Go语言中的闭包同样会引用到函数外的变量.闭包的实现确保只要闭包还被使用,那么被闭包引用的变量会一直存在

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package main

    import "fmt"

    func main() {
    var j int = 5

    a := func()(func()) {
    var i int = 10
    return func() {
    fmt.Printf("i, j: %d, %d\n", i, j)
    }
    }()
    a()
    j *= 2
    a()
    }

    [tiger@bogon tiger]$ go run closure.go
    i, j: 10, 5
    i, j: 10, 10

    变量a指向的闭包函数引用了局部变量i和j, i的值被隔离,在闭包外不能被修改,改变j的值以后,再次调用a, 发现结构是修改过的值
    在变量a指向的闭包函数中,只有内部的匿名函数才能访问变量i,而无法通过其他途径访问到,因此保证了i的安全性

  • 不定参数
    不定参数是指函数接受传入的参数为不定数量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    func myfunc(args ...int){
    for _, arg := range args{
    fmt.Println(arg)
    }
    }

    //原样传递
    myfunc(args...)
    //传递片段
    myfunc(args[1:]...)

    myfunc(2, 4, 6)
    myfunc(1, 3, 4, 6)

    如果传递的参数不是int,而是任意类型,可以指定类型为interface(),我们来看下Go语言标准库中fmt.Printf()的函数原型

    1
    2
    3
    func Printf(format string, args ...interface{}) {
    // ...
    }

    下面代码是展示如何处理传入interface{}类型的参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package main

    import "fmt"

    func MyPrintf(args ...interface{}) {
    for _, arg := range args {
    switch arg.(type) {
    case int:
    fmt.Println(arg, "is an int value.")
    case string:
    fmt.Println(arg, "is a string value.")
    case int64:
    fmt.Println(arg, "is an int64 value.")
    default:
    fmt.Println(arg, "is an unknow type.")
    }
    }
    }

    func main() {
    var v1 int = 1
    var v2 int64 = 234
    var v3 string = "hello"
    var v4 float32 = 1.456
    MyPrintf(v1, v2, v3, v4)

    }
  • 总结
    匿名函数
    闭包,Go的匿名函数就是一个闭包
    不定参数


您的鼓励是我写作最大的动力

俗话说,投资效率是最好的投资。 如果您感觉我的文章质量不错,读后收获很大,预计能为您提高 10% 的工作效率,不妨小额捐助我一下,让我有动力继续写出更多好文章。