func函数
- Go中的函数与其他高级语音一样被称为一等公民,就是支持高阶函数的函数。
高阶函数指函数可以被存储和作为参数传递 - 函数调用 采用栈结构的方式,main函数始终处于栈底
main函数需要等待内部函数调用完成 才能出栈 这就是先进后出FILO - 一个完整的函数,包括函数名,形参 和形参类型,返回值 和返回值类型,函数体
具名函数&匿名函数&形参&返回值
- 函数名可以省略,省略函数名的函数叫做匿名函数,具有函数名的函数叫做具名函数。只有匿名函数可以被嵌套
package main
import "fmt"
func main() {
//函数是一个数据,函数名就是存储数据的变量名
//数据就是函数本身
//这个数据类型称为函数类型,不同的形参 形参类型,返回值 返回值类型,分为不同的函数类型。
fmt.Printf("%T : %v\n", f1, f1)
fmt.Printf("%T : %v\n", f2, f2)
fmt.Printf("%T : %v\n", f3, f3)
fmt.Printf("%T : %v\n", f4, f4)
fmt.Println("----------------")
//有函数名的函数被称为具名函数,没有函数名的函数被称为匿名函数
//匿名函数因为没有名字,所以常被赋值给变量,否则无法使用将没有意义。通常用作临时使用
f5 := func() {}
fmt.Printf("%T : %v", f5, f5)
//立即调用使用
func(){fmt.Println("Hello,world")}() //在匿名函数后直接使用()括号 将会立即执行。
}
func f1() {}
func f2(i, j int) {}
func f3() int{return 0}
func f4(i int) int{return 0}
输出:
func() : 0xff74a0
func(int, int) : 0xff74c0
func() int : 0xff74e0
func(int) int : 0xff7500
----------------
func() : 0xff7520Hello,world
Process finished with exit code 0
栈逃逸和展开运算符...
package main
import "fmt"
func main() {
sum := func (i, j int)int{return i + j}(3,4)
//函数中,在括号内写的(i j)为形参,用作给该函数使用的变量,必须要指定类型。
//调用时(3,4)为实参,用作传递给函数的参数,必须为函数指定的类型。
fmt.Println(sum)
//...剩余和展开运算符
multiply := func(n... int)int{return n[0] * n[1]}([]int{2, 3}...)
//该函数中...是剩余运算符,会把接受到的所有值都给n,n会被go用作切片的方式存储数据。
//调用时...是展开运算符,会把一个切片的元素展开为数据。
fmt.Println(multiply)
//每调用执行一个函数的时候会创建一个栈,栈中存储着局部变量。当函数执行完毕,栈也将消失,但是如果在栈中的局部变量有被外部使用,会被重新分配到一个其他栈上。
//这种现象称为栈逃逸
/*
逃逸分析是一种确定指针动态范围的方法,简单来说就是分析在程序的哪些地方可以访问到该指针。
通俗地讲,逃逸分析就是确定一个变量要放堆上还是栈上,规则如下:
是否有在其他地方(非局部)被引用。只要有可能被引用了,那么它一定分配到堆上。否则分配到栈上
即使没有被外部引用,但对象过大,无法存放在栈区上。依然有可能分配到堆上
https://blog.csdn.net/u010853261/article/details/102846449
*/
}
defer延迟调用
package main
import "fmt"
//defer延迟调用:
//延迟调用defer后的语句,在此函数结束后。
func main() {
fmt.Println("1")
fmt.Println("2")
defer fmt.Println("3")
//此语句会在函数运行完毕后才执行
fmt.Println("4")
de()
}
func de(){
defer fmt.Println("a")
defer fmt.Println("b")
//如果存在多个defer 会使用栈结构执行最后入栈的defer
//每个函数会创建一个defer栈 每个defer语句都会入栈,使用源码中的代码顺序入栈
}
输出:
1
2
4
b
a
3
Process finished with exit code 0
闭包
我的理解是:闭包是一个为了访问到函数内的局部变量而使用了全局变量的匿名函数
package main
import "fmt"
//Closure 闭包
//为了能访问到函数内的局部变量的匿名函数,被称为闭包
var a1 = 123
func main() {
f1 := add()
fmt.Println(f1())
}
func add() func() int {
temp := 123
return func() int {
return temp + a1
//这里使用了全局变量a1,并返回
}
}
输出:246