【1】使用包的原因:
(1)我们不可能把所有的函数放在同一个源文件中,可以分门别类的把函数放在不同的原文件中
2)解决同名问题:两个人都想定义一个同名的函数,在同一个文件中是不可以定义相同名字的函数的。此时可以用包来区分
【2】案例展示包:
项目的结构:
代码展示:
//main.go
package main //1.package进行包的声明,建议:包的声明这个包和所在的文件夹同名
//2.main包是程序的入口包,一般main函数会放在这个包下
//import "fmt"
//3.包名是从$GOPATH/src/后开始计算的,使用/进行路劲分隔
//import "gocode/testproject01/unit5/demo9/crm/dbutils"
//如果有多个包需要导入,建议一次性导入
import (
"fmt"
"gocode/testproject01/unit5/demo9/crm/dbutils"
)
func main(){
fmt.Println("Hello ,这是main函数的执行")
dbutils.GetConn()//4.在函数调用的时候前面要定位到所在的包
}
//dbutils.go
package dbutils
import "fmt"
func GetConn(){//5.首字母大写,可以被其他包使用
fmt.Println("执行了dbutils包下的getConn函数")
}
1.package进行包的声明,建议:包的声明这个包和所在的文件夹同名
2.main包是程序的入口包,一般main函数会放在这个包下
main函数一定要放在main包下,否则不能编译执行
3.打包语法:
package 包名
4.引入包的语法:import “包的路径”
包名是从$GOPATH/src/后开始计算的,使用/进行路径分隔。
5.如果有多个包,建议一次性导入,格式如下:
import(
"fmt"
"gocode/testproject01/unit5/demo09/crm/dbutils"
)
6.在函数调用的时候前面要定位到所在的包
8.一个目录下不能有重复的函数
9.包名和文件夹的名字,可以不一样
10.一个目录下的同级文件归属一个包
同级别的源文件的包的声明必须一致
11.包到底是什么:
(1)在程序层面,所有使用相同 package 包名 的源文件组成的代码模块
(2)在源文件层面就是一个文件夹
【1】init函数:初始化函数,可以用来进行一些初始化的操作
每一个源文件都可以包含一个init函数,该函数会在main函数执行前,被Go运行框架调用。
package main
import "fmt"
func init(){
fmt.Println("main.go中的init函数被执行")
}
func main(){
fmt.Println("main函数被执行")
}
【2】全局变量定义,init函数,main函数的执行流程?
package main
import (
"fmt"
"gocode/testproject01/unit5/demo10/testutils"
)
var num int = test()
func test() int{
fmt.Println("test函数被执行")
return 10
}
func init(){
fmt.Println("main.go中的init函数被执行")
}
func main(){
fmt.Println("main函数被执行")
}
【3】多个源文件都有init函数的时候,如何执行:
package testutils
import "fmt"
var Age int
var Sex string
var Name string
//定义一个init函数对变量进行初始化赋值:
func init(){
fmt.Println("testutils中的init函数被执行了")
Age = 19
Sex = "女"
Name = "丽丽"
}
package main
import (
"fmt"
"gocode/testproject01/unit5/demo10/testutils"
)
var num int = test()
func test() int{
fmt.Println("test函数被执行")
return 10
}
func init(){
fmt.Println("main.go中的init函数被执行")
}
func main(){
fmt.Println("main函数被执行")
fmt.Println("Age= ",testutils.Age,"Sex=",testutils.Sex,"Name=",testutils.Name)
}
执行结果:
执行过程:
【1】Go支持匿名函数,如果我们某个函数只是希望使用一次,可以考虑使用匿名函数
【2】匿名函数使用方式:
(1)在定义匿名函数时就直接调用,这种方式匿名函数只能调用一次(用的多)
(2)将匿名函数赋给一个变量(该变量就是函数变量了),再通过该变量来调用匿名函数(用的少)
package main
import "fmt"
func main(){
//定义匿名函数:定义的同时调用
result := func (num1 int,num2 int) int{
return num1 + num2
}(10,20)
fmt.Println(result)
//将匿名函数赋给一个变量,这个变量实际就是函数类型的变量
//sub等价于匿名函数
sub := func (num1 int,num2 int) int{
return num1 - num2
}
//直接调用sub
result01 := sub(30,70)
fmt.Println(result01)
result02 := sub(30,70)
fmt.Println(result02)
}
【3】如何让一个匿名函数,可以在整个程序中有效呢?将匿名函数给一个全局变量就可以了
package main
import "fmt"
var Func01 = func (num1 int,num2 int) int{
return num1 * num2
}
func main(){
result03 := Func01(3,4)
fmt.Println(result03)
}
匿名函数实验的总代码
package main
import "fmt"
var Func01 = func (num1 int,num2 int) int{
return num1 * num2
}
func main(){
//定义匿名函数:定义的同时调用
result := func (num1 int,num2 int) int{
return num1 + num2
}(10,20)
fmt.Println(result)
//将匿名函数赋给一个变量,这个变量实际就是函数类型的变量
//sub等价于匿名函数
sub := func (num1 int,num2 int) int{
return num1 - num2
}
//直接调用sub
result01 := sub(30,70)
fmt.Println(result01)
result02 := sub(30,70)
fmt.Println(result02)
result03 := Func01(3,4)
fmt.Println(result03)
}
【1】什么是闭包:
闭包就是一个函数和与其相关的引用环境组合的一个整体
【2】案例展示:
package main
import "fmt"
//函数功能:求和
//函数的名字:getSum参数为空
//getSum函数返回值为一个函数,这个函数的参数是一个int类型的参数,返回值也是int类型
func getSum() func (int) int {
var sum int = 0
return func (num int) int{
sum = sum + num
return sum
}
}
//闭包,返回的匿名函数+匿名函数以外的变量num
func main(){
f := getSum()
fmt.Println(f(1)) //1
fmt.Println(f(2))
fmt.Println(f(3))
fmt.Println(f(4))
}
感受:匿名函数中引用的那个变量会一直保存在内存中,可以一直使用
【3】闭包的本质:
闭包本质依旧是一个匿名函数,只是这个函数引入外界的变量/参数
匿名函数+引用的变量/参数 = 闭包
【4】特点:
(1)返回的是一个匿名函数,但是这个匿名函数引用到函数外的变量/参数 ,因此这个匿名函数就和变量/参数形成一个整体,构成闭包。
(2)闭包中使用的变量/参数会一直保存在内存中,所以会一直使用—》意味着闭包不可滥用(对内存消耗大)
【5】不使用闭包可以吗?
package main
import "fmt"
//函数功能:求和
//函数的名字:getSum参数为空
//getSum函数返回值为一个函数,这个函数的参数是一个int类型的参数,返回值也是int类型
func getSum() func (int) int {
var sum int = 0
return func (num int) int{
sum = sum + num
return sum
}
}
//闭包,返回的匿名函数+匿名函数以外的变量num
func main(){
f := getSum()
fmt.Println(f(1)) //1
fmt.Println(f(2))
fmt.Println(f(3))
fmt.Println(f(4))
fmt.Println("---------------------")
fmt.Println(getSum01(0,1))//1
fmt.Println(getSum01(1,2))//3
fmt.Println(getSum01(3,3))//6
fmt.Println(getSum01(6,4))//10
}
func getSum01(sum int,num int) int{
sum = sum + num
return sum
//不使用闭包的时候:我想保留的值,不可以反复使用
//闭包应用场景:闭包可以保留上次引用的某个值,我们传入一次就可以反复使用了
}
【1】defer关键字的作用:
在函数中,程序员经常需要创建资源,为了在函数执行完毕后,及时的释放资源,Go的设计者提供defer关键字
【2】案例展示:
package main
import "fmt"
func main(){
fmt.Println(add(30,60))
}
func add(num1 int ,num2 int) int{
//在Golang中,程序遇到defer关键字,不会立即执行defer后的语句,而是将defer后的语句压入一个栈中,然后继续执行函数后面的语句
defer fmt.Println("num1=",num1)
defer fmt.Println("num2=",num2)
//栈的特点是:先进后出
//在函数执行完毕以后,从栈中取除语句开始执行,安照先进后出的规则执行语句
var sum int = num1 + num2
fmt.Println("sum=",sum)
return sum
}
发现:遇到defer关键字,会将后面的代码语句压入栈中,也会将相关的值同时拷贝入栈中,不会随着函数后面的变化而变化。
【4】defer应用场景:
比如你想关闭某个使用的资源,在使用的时候直接随手defer,因为defer有延迟执行机制(函数执行完毕再执行defer压入栈的语句),
所以你用完随手写了关闭,比较省心,省事