Go语言学习-- No.10 函数 --- 匿名函数和闭包

匿名函数和闭包

  • 匿名函数
    • 1. 定义并同时调用匿名函数
    • 2. 将匿名函数赋值给变量。
  • 闭包

匿名函数即在需要函数时定义函数,匿名函数能以变量方式传递,它常常被用于实现闭包。

匿名函数

定义格式:

func (参数列表) (返回参数列表) {
   函数体
}

1. 定义并同时调用匿名函数

举例:
该例子相当于先定义了一个函数,这个函数后面直接对形参进行赋值操作,完成函数的使用。

  • 需要时候定义的函数。
  • 函数后面紧跟着实例化的形参变量。
package main

import "fmt"

func main() {
	func(data string) {
		fmt.Println("123" + data)
	}("456")
}

// 123456

2. 将匿名函数赋值给变量。

将函数赋值给变量,为 函数 的实例化操作,用一个变量来代替这个函数,后面只需要在函数中传入参数即可(即: 实例化形式参数 )

package main

import "fmt"

func main() {
	f1 := func(data string) {
		fmt.Println("123" + data)
	}
	f1("abc")
}

// 123abc

闭包

闭包就是包含了自由变量的匿名函数。自由变量即使已经脱离了原有的自由变量环境也不会被删除,在闭包的作用域内可继续使用这个自由变量,同一个匿名函数和不同的引用环境组成了不同的闭包。

可对作用域内的变量的引用进行修改。

举例说明上面的说明:

package main

import "fmt"

func main() {

	num := 1
	fmt.Printf("%p\n", &num) // 地址
	func() {
		num++
		fmt.Println(num)         // 数值打印
		fmt.Printf("%p\n", &num) // 地址
	}()
	func() {
		num++
		fmt.Println(num)
		fmt.Printf("%p\n", &num)
	}()

	fmt.Println(num)
	fmt.Printf("%p\n", &num)
}

// 0xc000014098
// 2
// 0xc000014098
// 3
// 0xc000014098
// 3
// 0xc000014098

以上程序中的匿名函数由于在函数体内部引用了外部的自由变量num而形成了闭包。闭包每次对num变量的加1操作都是对变量num引用的修改。
可以看出,物理地址没有发生变化,但是数值确发生变化,同时在第一个匿名函数中(闭包) 自变量n 发生变化,之后,n并没有重置,而是在基于保持该值,进入了第二个匿名函数中(闭包),n的数值继续发生变化,但是物理地址还是没有发生变化。
说明,在同一个作用域中(一个函数中,此处为 main(),当然可以为其他自定义的函数 ),闭包中的变量不会重置。

作用域不同的情况 — 举例:

package main

import "fmt"

func addone(i int) func() int {
	return func() int {
		i++
		return i
	}
}

func main() {
	a1 := addone(0)
	fmt.Println(a1())
	fmt.Print("a1闭包的地址为: ")
	fmt.Printf("%p\n", &a1)

	fmt.Println(a1())
	fmt.Print("a1闭包的地址为: ")
	fmt.Printf("%p\n", &a1)

	a2 := addone(10)
	fmt.Println(a2())
	fmt.Print("a2闭包的地址为: ")
	fmt.Printf("%p\n", &a2)

}

// 1
// a1闭包的地址为: 0xc000006028
// 2
// a1闭包的地址为: 0xc000006028
// 11
// a2闭包的地址为: 0xc000006038

作用域不同,闭包定义在了自定义的addone() 函数中,因此函数会重置闭包。
在同一个addone() 中的闭包,函数的物理地址没有发生变化,输出量:闭包中的值也在发生变化
在不同的addone() 中的闭包,函数的物理地址发生变化,同时,输出量是有新的参数产生,而不是在上一个的基础上进行的改动,因此 输出量也发生变化。
每次调用闭包实例,i的值都会在原有的基础上加1。从打印的结果可以看到,两个闭包实例的地址完全不同,两个闭包的调用结果互不影响。

你可能感兴趣的:(go语言学习,golang,开发语言,后端)