【go】闭包与defer

1.闭包就是一个函数和与其相关的引用环境组合的一个整体

package main
import (
	"fmt"
)

// 累加器
func addUpper() func (int) int {
	n := 10
	return func (x int) int {
		n += x
		return n
	}
}

func main() {
	f := addUpper()
	fmt.Println(f(1)) // 11
	fmt.Println(f(2)) // 13
	fmt.Println(f(3)) // 16
}

addUpper是一个函数,返回类型是func(int) int

返回的是一个匿名函数,但是这个匿名函数引用到函数外的n,因此这个匿名函数和n形成一个整体,构成闭包。

当我们反复调用f时,n只初始化一次,每调用一次,就产生累加。

要分析清楚,返回的函数使用哪些变量。

返回的匿名函数和这个匿名函数用到的函数外的变量构成闭包
反复调用这个函数时,它用到的变量只初始化一次。

2.闭包示例

package main
import (
	"fmt"
	"strings"
)

func makeSuffix(suffix string) func(string) string {
	return func(name string) string {
		// name 没有指定后缀 加上
		// 否则返回原来的名字
		if !strings.HasSuffix(name, suffix) {
			return name + suffix
		}
		return name
	}
}

func main() {
	f := makeSuffix(".jpg")
	var s string
	fmt.Println("input file name")
	fmt.Scanln(&s)
	fmt.Println("文件名处理后=", f(s))

}

如果用传统方法,需要反复传入suffix,用闭包的方法传入一次即可。

3.defer
函数中,常常需要创建资源(数据库连接,文件句柄,锁)
为了函数执行完毕后,及时释放资源,go提供defer延时机制

package main
import (
	"fmt"
)

func sum(n1 int, n2 int) int {
	defer fmt.Println("ok1 n1=", n1)
	defer fmt.Println("ok2 n2=", n2)
	res := n1 + n2
	fmt.Println("ok3 res=", res)
	return res
}


func main() {
	res := sum(10, 2)
	fmt.Println("res=", res)
}

执行到defer时,先不执行,将defer后面的语句压入到独立的栈(defer栈)
函数执行完毕后,再从defer栈,出栈执行

4.在defer将语句放入栈时,也会将相关的值拷贝,同时入栈

package main
import (
	"fmt"
)

func sum(n1 int, n2 int) int {
	defer fmt.Println("ok1 n1=", n1) // 10
	defer fmt.Println("ok2 n2=", n2) // 2
	n1++
	n2++
	res := n1 + n2
	fmt.Println("ok3 res=", res) // 14
	return res
}

func main() {
	res := sum(10, 2)
	fmt.Println("res=", res)
}

defer用于及时释放函数创建的资源

5.引用类型:指针、slice、map、管道chan、interface
引用类型默认是引用传递,变量存地址,内存一般在堆上分配
没有变量引用这个地址时,地址对应的数据空间就成为一个垃圾,由GC回收

如果希望函数内能改变函数外的变量,传入变量的地址&

6.函数外声明/定义的变量为 全局变量,作用域在整个包有效
首字母大写,作用域为整个程序

编译器采用就近原则,先用局部变量
Name := “tom”
等价于两句 定义和赋值
赋值不能在函数体外,报错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值