函数 : Go 语言 用 func 关键字来定义
1 go 程序中 至少有一个 函数 main函数
2 Go语言 函数不能重载
语法格式
func FuncName( 参数.... ) (返回值...){
//ToDo.....
return a,b...
}
package main
import "fmt"
//函数可以定义不使用
func A(){
fmt.Println("haha")
}
//函数名不能冲突: 即 Go语言 函数不能重载
func A(a int8){
fmt.Println(a)
}
func main(){
fmt.Println("once")
//A(5)
}
参数类型简写: 参数类型一致时, 可以把类型写在后边 ,只写一个
参数类型不匹配时 不会进行隐式类型转换。
参数类型不匹配时 不会进行隐式类型转换。
参数类型不匹配时 不会进行隐式类型转换。
可变参数 函数(原理: slice)
可变參函数的使用切片的原理, 将传入的数据存放在 slice 中,
类似的可变參函数有 printf 、append 等 ,可以 摁住ctrl键查看源码
一个函数中,只能有一个可变參函数, 并且可变参必须放在 函数参数的最后
一个函数中,只能有一个可变參函数, 并且可变参必须放在 函数参数的最后
一个函数中,只能有一个可变參函数, 并且可变参必须放在 函数参数的最后
参数传递
参数传递 分为 值传递 和 引用传递
切片: 应用传递
数组: 值传递(copy了一份)
另外 : func 函数的参数类型必须匹配才能接收,函数调用时不会进行类型转换。
引用传递: 引用类型数据都是引用传递: 例如 slice,map chan等
函数的返回值
Go 语言 函数的返回值 可以是多个值
语法格式:
func funcName(args)(return values){
//todo
return values
}
defer 语句: 延迟函数执行
延迟语句 : 延迟语句用来延迟一个函数/方法的执行,等到 主函数要返回时, 再去执行被延迟的语句
意义:
比如文件指针 我们打开了 ,后来我们忘了关闭,临时文件忘了删除, 我们就可以在定义临时文件/ 打开文件指针时 进行定义 defer语句: 到时候关闭/删除临时文件,避免内存泄漏
Panic 函数 : 错误信息的处理
recover 函数: 恢复数据, 必须放在 defer 语句中
defer 语句 案例:
一: 一个 defer 自己最后执行
二: 多个defer 执行为定义defer 的逆序,类似于 栈
package main
import "fmt"
func func1(){
fmt.Println("张三")
}
func func2(){
fmt.Println("李四")
}
func func3(){
fmt.Println("王五")
}
func main(){
//多个defer 语句则 按照定义的逆序执行defer
//一个defer 语句 自己最后执行
fmt.Println("hello")
defer func1()//
defer func2()//延迟语句 : 外围函数都执行完才执行 他
defer func3()
fmt.Println("world")
}
defer 语句的 函数 ,调用时 ,参数已经传递过去了 ,只是函数执行延迟了
函数的 数据类型
函数 也有 函数的类型 : func()
带有参数的还有 参数func(int)
带有返回值 的 还有返回值类型 func(int)(int)
func func1(){
}
c: = func1
那么这是一个 值拷贝
c() 等价于 func1()
匿名函数 :没有名字的函数,
可以赋值给函数变量 ,这样可以多次调用,
也可以 当作lambda表达式那么用
匿名函数 可以通过赋值给某一个函数变量的方式使用多次
Go 语言支持函数式编程:
1 将匿名函数 作为另一个函数的参数,即 回调函数
2 将匿名函数作为另外一个函数的返回值,可以形成闭包结构(内层函数 和 外层函数的 局部变量 统一称为闭包结构)
回调函数
包含回调函数的函数 称为 高阶函数
func fun1(){
}
func fun2(a int, fun1){
}
此时 fun2称为 高阶函数
func Add(a, b int) int {
return a + b
}
// oper 函数是一个高阶函数:
//参数 a,b均为 int 类型
//fun 是一个 func(int,int) int 类型的函数
//代码执行时 ,按照正常流程来就行了
func oper(a, b int, fun func(int, int) int) {
fmt.Println(a, b, fun) //fun将来时 Add的地址
ret := fun(a, b)
fmt.Println(ret) //调用回调函数
}
func main() {
Add(10, 20)
oper(10, 20, Add)
}
闭包结构分析
//闭包结构: 函数内部嵌套这匿名函数, 而匿名函数又是该函数的返回值,
//那么当 匿名函数使用到了外层函数的局部变量时,外层数的该局部变量将不能释放
// 因为被人家用到了
func closedPackage() func()int{
i:=0
fun1 := func ()int{
i++
return i
}
return fun1
}
func main() {
//Add(10, 20)
//oper(10, 20, Add)
ret := closedPackage()// 检验闭包结构
println(ret)//func()int
v1 := ret()
println(v1)
v1 = ret()
println(v1)// 局部变量 i未被销毁
v1 = ret()
println(v1)// 局部变量 i未被销毁
}
此时 这个 基部变量 i 就潜逃了