defer
-
应用defer注册的匿名函数(提早调用)还能够给它传参,不过是值拷贝
package main import "fmt" func work() int { num := 10 defer func(i int) { i += 20 println("defer内的后果:", i) }(num) return num } func main() { ret := work() fmt.Println(ret) }
输入:
defer内的后果: 30 10
解析:在work函数内,变量num传递给了通过defer注册了的匿名函数,在匿名函数内做了加20,但它的后果并未影响到里面的num变量,这就是值拷贝。
-
当被动调用os.Exit退出程序后,defer会不会执行?试试再说
package main import ( "fmt" "os" ) func main() { defer func() { fmt.Println("开释锁...") }() fmt.Println("hello") os.Exit(1) }
输入:
hello
答案很显著了,竟然不会。
-
注册自定义的函数为提早调用,模仿个小栗子:关上文件,解决,解决完后敞开该文件
package main import ( "fmt" ) func closeFile() { println("敞开文件") } func work() bool { defer closeFile() fmt.Println("关上文件") fmt.Println("正在解决...") fmt.Println("解决实现!") return true } func main() { status := work() fmt.Println(status) }
输入:
关上文件 正在解决... 解决实现! true 敞开文件
所以说,defer的利用场景能够是开释资源或者敞开连贯、敞开文件、开释锁等等,说白了就是:它就是做收尾工作的家伙。
闭包
-
闭包初体验
闭包的实质其实返回的是一个函数,但这个函数有点非凡,为啥说非凡呢?因为在这个函数外面,还有一个函数,这个函数是匿名函数,且在这个匿名函数外面还能够援用内部变量,当被重复调用时,这里援用的内部变量只会初始化一次。因而:闭包=函数+函数外面的匿名函数+匿名函数援用的内部变量
接下来一步一步进行解剖
方才说到闭包的实质其实返回的是一个函数,之前提到过,匿名函数是能够作为函数的返回值的,看上面代码:
func bibao() func() {
}
下面的栗子中,定义了一个函数Bibao,这个函数没有入参,返回值的类型是函数类型,也就是定义成func(),所以它要返回一个函数才行呢,当初函数体是空的,别急,一步一步解剖。
方才说到在这个函数外面,还有一个函数,这个函数是匿名函数,且还要返回这个匿名函数,看上面的代码:
func bibao() func() {
return func() {
fmt.Println("hello")
}
}
func main() {
b := bibao()
b()
}
输入:
hello
在bibao函数体里,返回了一个匿名函数,这个匿名函数的性能是输入了字符串“hello”,调用bibao()把它赋值给变量b,此刻,变量b就是一个函数(它接管的就是返回的匿名函数),变量b既然是函数,那就能够进行调用了b(),所以执行后,输入的是“hello”。
方才说到且在这个匿名函数外面还能够援用内部变量,当被重复调用时,这里援用的内部变量只会初始化一次,看上面代码:
package main
import "fmt"
func bibao(name string) func() string {
base := "hello"
return func() string {
base = base + " " + name
return base
}
}
func main() {
b := bibao("ttr")
fmt.Println(b()) // 第1次调用
fmt.Println(b()) // 第2次调用
fmt.Println(b()) // 第3次调用
fmt.Println(b()) // 第4次调用
}
输入:
hello ttr //第1次调用的后果输入
hello ttr ttr //第2次调用的后果输入
hello ttr ttr ttr //第3次调用的后果输入
hello ttr ttr ttr ttr //第4次调用的后果输入
这次对bibao函数做了点小革新,它须要接管一个参数name。在bibao函数中,对于匿名函数外部来说,它的内部变量就是bibao函数里的base变量。调用函数bibao并传入”ttr”,在匿名函数中进行了字符串拼接,bibao(“ttr”)初始化了一次,b()重复调用了4次,在匿名函数中援用的内部变量base,每次调用时返回的是内部变量base的多个正本,因为在每次调用时都会为局部变量分配内存(对于整个程序来说,在函数里的base变量是局部变量,而对于在bibao函数里的匿名函数来说,base变量是内部变量。)
还能够再这样革新,成果也是一样的:
package main
import "fmt"
func bibao() func(name string) string {
base := "hello"
return func(name string) string {
base = base + " " + name
return base
}
}
func main() {
b := bibao()
fmt.Println(b("ttr"))
fmt.Println(b("ttr1"))
fmt.Println(b("ttr2"))
}
输入:
hello ttr
hello ttr ttr1
hello ttr ttr1 ttr2
好了,到此为止,闭包到底在哪呢?上面这块就是闭包,bibao函数返回了这个闭包:
base := "hello"
return func(name string) string {
base = base + " " + name
return base
}
闭包是由函数和与其相干的援用环境组合而成的实体,这里所说的函数就是匿名函数,所说的援用环境就是内部变量base,他们一起组合成了一个实体并返回,这就是闭包。
忽然想到如果把base变量放到匿名函数外面,它还是不是一个闭包?看看成果:
package main
import "fmt"
func bibao() func(name string) string {
return func(name string) string {
base := "hello "
base = base + " " + a + " " + name
return base
}
}
func main() {
b := bibao()
fmt.Println(b("ttr"))
fmt.Println(b("ttr1"))
fmt.Println(b("ttr2"))
}
输入:
hello ttr
hello ttr1
hello ttr2
-
来一个小栗子
闭包的益处在于,能够缩小全局变量,在函数调用的过程中隐式的传递共享变量,这更具备封装性,更平安了,使其不能随便拜访到共享变量。
package main import ( "fmt" ) func bankcard(name string) func() (string, float32) { amount := 10000.0 return func() (string, float32) { return name, float32(amount) } } func main() { b := bankcard("xiaoming") fmt.Println(b()) }
本文装载于(喜爱的盆友关注咱们): https://mp.weixin.qq.com/s/O7…
发表回复