golang闭包学习笔记
在开发中,经常会将一个方法的参数设置为可选,并设置一些默认值,使代码更通用简洁。在很多语言中这很容易,比如在C类语言中,可以使用相同方法名不同参数的多个版本(重写), 而在像python这样的语言中, 可以给参数一个默认值,并在调用方法时忽略它们。但是在 Go中, 这两种方式都用不了
通过闭包的方式来解决这个问题
package main
import "fmt"
//用于初始化参数不定的情况,可以传入任意个参数
//可以给每个参数一个初始默认值,
//如果传入了ServerOption函数,就可以自定义这个字段的值,没传入这个字段的ServerOption则使用默认值
type options struct {
a int
b string
}
//定义了ServerOption为一个函数,参数是*options
type ServerOption func(*options)
func NewOption(opt ...ServerOption) *options {
r := new(options)
for _, o := range opt {
o(r)
}
return r
}
func InitA(a int) ServerOption {
return func(o *options) {
o.a = a
}
}
func InitB(b string) ServerOption {
return func(o *options) {
o.b = b
}
}
func main() {
initFuncs := []ServerOption{
InitA(100),
InitB("hello"),
}
//将需要初始化的字段对应的函数传入即可
opts := NewOption(initFuncs...)
fmt.Printf("opts = %+v\n", opts)
}
对闭包的深入分析
在过去近十年时间里,面向对象编程大行其道,以至于在大学的教育里,老师也只会教给我们两种编程模型,面向过程和面向对象。孰不知,在面向对象思想产生之前,函数式编程已经有了数十年的历史。就让我们回顾这个古老又现代的编程模型,看看究竟是什么魔力将这个概念在21世纪的今天再次拉入我们的视野
闭包是函数式编程语言中的概念,没有研究过函数式语言的人可能很难理解闭包的强大
闭包=函数+引用环境
package main
import "fmt"
func main() {
f := add()
fmt.Printf("f(1) = %+v\n", f(1)) //1
fmt.Printf("f(1) = %+v\n", f(1)) //1
p := pp(0)
fmt.Printf("p() = %+v\n", p()) //1
fmt.Printf("p() = %+v\n", p()) //2
fmt.Printf("p() = %+v\n", p()) //3
fmt.Printf("p() = %+v\n", p()) //4
fmt.Printf("p() = %+v\n", p()) //5
lv := localVar()
fmt.Printf("lv(0) = %+v\n", lv(0)) //0
fmt.Printf("lv(1) = %+v\n", lv(1)) //1
fmt.Printf("lv(2) = %+v\n", lv(2)) //3
fmt.Printf("lv(3) = %+v\n", lv(3)) //6
fmt.Printf("lv(4) = %+v\n", lv(4)) //10
}
func add() func(i int) int {
num := 0
return func(i int) int {
return num + i
}
}
//每次调用后,局部变量i的值会被保存
func pp(i int) func() int {
return func() int {
i++
return i
}
}
//每次调用后,局部变量sum会被保存
func localVar() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
闭包是匿名函数与匿名函数所引用环境的组合
匿名函数和它引用的变量以及环境,类似常规函数引用全局变量处于一个包的环境。
sum := 0
return func(x int) int {
sum += x
return sum
}
sum类比于全局变量,因此每次被赋值后,都会改变。
闭包被返回赋予一个同类型的变量时,同时赋值的是整个闭包的状态,该状态会一直存在外部被赋值的变量lv
中,直到lv
被销毁,整个闭包也被销毁。
参考资料:
https://blog.csdn.net/qq_3597...
https://www.cnblogs.com/landv...
https://blog.keyboardman.me/2...
https://www.jianshu.com/p/034...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。