文章目录
- 1、包
- 2、本质
- 3、init函数
- 4、匿名函数
- 5、闭包
1、包
不同的包,不同的功能和业务,互相import
关于包:
package 包名
注意点:
- 建议包名和所在文件夹同名
- main函数一定要放在main包下,否则编译报错
go run:cannot run non-main package
- 导入包是:
//从$GOPATH/src/后开始计算
import "包的路径"//一次性导入多个
import("fmt""gocode/testproject01/unit5/demo09/crm/dbutils"
)
- 函数调用时定位到所在的包
- 一个目录下,不能有重复的函数
- 包名和文件夹的名字可以不一样。但同一个目录下的源文件,包名的声明必须一致。即你这个随便起了个aaa,那同文件夹下的其他go文件的包名也就是aaa了
- 给包取别名后,原来的包名不可再使用
2、本质
go里面,包的实质:
- 在程序层面,所有使用相同 package 包名 的源文件组成的代码模块
- 在源文件层面就是一个文件夹
3、init函数
- 包的初始化函数,做一些初始化操作
- 每个go的源文件都可以包含一个init函数
- init函数的执行,是在main函数被执行前,被Go自己的运行框架调用
- 执行时机:
全局变量的定义 > init函数 > main函数
- 多个源文件都有init函数的时候,从main包的import开始,依次执行导入的包的init函数。当然,如果被导入的包里也有在导入别的包,那就像函数调用一样A ⇒ B ⇒ C ⇒ D ,D函数执行完再退回去 ⇒ C ⇒ B ⇒ A
4、匿名函数
如果某个函数只希望调用一次,可用go的匿名函数:
如上,再定义匿名函数的时候直接调用,如此就能保证匿名函数只被调用一次。如果需要被多次调用,可将匿名函数赋值给一个变量(但不常用了,想多次调可直接去定义个普通函数)
最后,如果想要一个匿名函数可以在整个函数中被调用,那就赋值给一个全局变量:
package main
import "fmt"var Func01 = func (num1 int,num2 int) int{return num1 * num2
}func main(){ result := Func01(3,4)fmt.Println(result)
}
5、闭包
闭包即一个函数和起引用的环境组合的一个整体。
package main
import "fmt"
//函数功能:求和
//函数的名字:getSum 参数为空
//getSum函数返回值为一个函数,这个函数的参数是一个int类型的参数,返回值也是int类型
func getSum() func (int) int {var sum int = 0return func (num int) int{sum = sum + num return sum}
}
//闭包:返回的匿名函数+匿名函数以外的变量num
func main(){f := getSum()fmt.Println(f(1))//1 fmt.Println(f(2))//3fmt.Println(f(3))//6fmt.Println(f(4))//10
}
运行:
1
3
6
10
可以看到匿名函数中用到了函数以外的变量sum,它两形成闭包。且 匿名函数中引用的那个变量会一直保存在内存中,可以一直使用
闭包本质依旧是一个匿名函数,只是这个函数引入外界的变量/参数
匿名函数+引用的变量/参数 = 闭包
闭包的特点:
- 返回的是一个匿名函数,但是这个匿名函数引用到函数外的变量/参数 ,因此这个匿名函数就和变量/参数形成一个整体,构成闭包
- 闭包中使用的变量/参数会一直保存在内存中,所以会一直使用 ⇒ 意味着闭包不可滥用(对内存消耗大)
闭包应用场景:闭包可以保留上次引用的某个值
Demo:
package main
import "fmt"
//函数功能:求和
//函数的名字:getSum 参数为空
//getSum函数返回值为一个函数,这个函数的参数是一个int类型的参数,返回值也是int类型
func getSum() func (int) int {var sum int = 0return func (num int) int{sum = sum + num return sum}
}
//闭包:返回的匿名函数+匿名函数以外的变量num
func main(){f := getSum()fmt.Println(f(1))//1 fmt.Println(f(2))//3fmt.Println(f(3))//6fmt.Println(f(4))//10fmt.Println("----------------------")//不用闭包fmt.Println(getSum01(0,1))//1fmt.Println(getSum01(1,2))//3fmt.Println(getSum01(3,3))//6fmt.Println(getSum01(6,4))//10
}func getSum01(sum int,num int) int{sum = sum + numreturn sum
}
//不使用闭包的时候:我想保留的值,不可以反复使用
//闭包应用场景:闭包可以保留上次引用的某个值,我们传入一次就可以反复使用了
如上,不用闭包,想达到和上面闭包一样去共用某个值,就很麻烦。