这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
(内容根据字节跳动青训营课程内容以及自己的理解编写)
近期将日更这几个主题的文章,欢迎关注!
- 全面理解go协程
- channel通信
- Kitex
- Hertx
- Gorm
- go的测试环节
函数初步认识
在go里面,函数也是一个类型,类似于js 函数式编程
我们打印一下函数的类型
func main() {
// 注意这里是打印类型,不能加括号,函数加括号就调用了
fmt.Printf("%T\n", add1)
fmt.Printf("%T\n", add2)
}
func add1() {
}
func add2(x, y int) int {
return x + y
}
发现可以打印出add函数的类型
既然函数是类型的话,是不是可以赋值?
答案是可以的
func main() {
// 注意这里是打印类型,不能加括号,函数加括号就调用了
fmt.Printf("%T\n", add1)
fmt.Printf("%T\n", add2)
// 赋值给函数
var f1 func(int, int) int
f1 = add2
fmt.Println(f1(1, 2))
// 也可以这么写
f2 := add2
fmt.Println(f2(1, 2))
}
func add1() {
}
func add2(x, y int) int {
return x + y
}
匿名函数
相当于在定义的时候给出函数实现
func main() {
// 匿名函数
f1 := func() {
fmt.Println("这是一个匿名函数")
}
f1()
}
也可以直接加一个括号执行! 后面的协程你会发现,每个协程定义完后面都会带个括号
func main() {
// 匿名函数
func() {
fmt.Println("这是一个匿名函数")
}()
}
匿名函数可以正常返回值
func main() {
// 匿名函数
ans := func(a, b int) int {
return a + b
}(1, 2)
fmt.Println(ans)
}
高阶函数和回调函数
高阶函数就是接收了一个函数作为参数的函数
回调函数就是作为另一个函数的参数
举个例子:
package main
import "fmt"
func main() {
fmt.Println(operation(1, 2, add))
}
// 高阶函数
func operation(a, b int, f func(a, b int) int) int {
return f(a, b)
}
// 回调函数
func add(a, b int) int {
return a + b
}
还可以这么把参数的方法写成匿名函数的样子:
func main() {
fmt.Println(operation(1, 2, func(a, b int) int { // 匿名实现add函数
return a + b
}))
}
// 高阶函数
func operation(a, b int, f func(a, b int) int) int {
return f(a, b)
}
闭包
闭包详解
闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)。
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
Go语言是支持闭包的,这里只是简单地讲一下在Go语言中闭包是如何实现的。
下面我来将之前的JavaScript的闭包例子用Go来实现。
package main
import (
"fmt"
)
func a() func() int {
i := 0
b := func() int {
i++
fmt.Println(i)
return i
}
return b
}
func main() {
c := a()
c()
c()
c()
a() //不会输出i
}
输出结果:
1
2
3
闭包复制的是原对象指针,这就很容易解释延迟引用现象。
package main
import "fmt"
func test() func() {
x := 100
fmt.Printf("x (%p) = %d\n", &x, x)
return func() {
fmt.Printf("x (%p) = %d\n", &x, x)
}
}
func main() {
f := test()
f()
}
输出:
x (0xc42007c008) = 100
x (0xc42007c008) = 100
外部引用函数参数局部变量
package main
import "fmt"
// 外部引用函数参数局部变量
func add(base int) func(int) int {
return func(i int) int {
base += i
return base
}
}
func main() {
tmp1 := add(10)
fmt.Println(tmp1(1), tmp1(2))
// 此时tmp1和tmp2不是一个实体了
tmp2 := add(100)
fmt.Println(tmp2(1), tmp2(2))
}
返回2个闭包
package main
import "fmt"
// 返回2个函数类型的返回值
func test01(base int) (func(int) int, func(int) int) {
// 定义2个函数,并返回
// 相加
add := func(i int) int {
base += i
return base
}
// 相减
sub := func(i int) int {
base -= i
return base
}
// 返回
return add, sub
}
func main() {
f1, f2 := test01(10)
// base一直是没有消
fmt.Println(f1(1), f2(2))
// 此时base是9
fmt.Println(f1(3), f2(4))
}