学习golang第十一天

函数定义和defer

defer语句
Go语言中的defer语句会将其后面跟随的语句进行延迟处理,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

package main
import "fmt"
func main(){
	fmt.Println("start")
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println("end")
}

defer执行的时机
在Go语言函数中return语句在底层并不是原子操作,它分为给返回值赋值和RET指令两步。而defer语句执行的时机就在返回值赋值操作后,RET指令执行前。

defer经典示例

package main
import "fmt"
func main(){

}
func f1(){
	x := 5
	defer func(){
		x++ //修改的是x不是返回值
	}()
	return x
}
func f2(x int){
	defer func(){
		x++
	}()
	return 5 //返回值=x
}

func f3()(y int){
	x := 5
	defer func(){
		x++ //修改的是x
	}()
	return x //返回值y = x = 5 
}

func f4()(x int){ //函数传参修改的是副本(值传递)
	defer func(x int){
		x++
	}(x)
	return 5
}

func f5()(x int){
	defer func(x *int){
		(*x)++
	}(&x)
	
	return 5
}
package main
import "fmt"
func calc(index string , a , b int) int{
	ret := a + b
	fmt.Println(index , a ,b , ret)
	return ret
}
func main(){
	a := 1
	b := 2
	defer calc("1" , a , calc("10" , a , b ))
	a = 0
	defer calc("2" , a , calc("20" , a , b))
	b = 1
}
/*


1. defer calc("1" , 1 , calc("10" , 1 , 2)) //"10" , 1 , 2 ,3
   defer calc("1" , 1 , 3)
2. defer calc("2" , 0 , calc("20" , 0 , 2)) // "20" , 0 , 2 , 2
   calc("2" , 0 , 2)
3. a = 0 b = 1
   calc("2" , 0 ,2) // "2" , 0 , 2  ,2
4. calc("1" , 1 ,3) // "1" , 1 , 3  ,4
*/

注:
1.defer 压栈的时候必须是一个确切的状态
2.defer 压栈的时候函数参数已经确定

变量的作用域

全局变量
全局变量是定义在函数外部的变量,它在程序整个运行周期内部有效。在函数中可以访问到全局变量。

package main
import "fmt"
var num int64 = 10
//函数中查找变量的顺序
//1.先在函数内部查找
//2.找不到就在函数外部查找,一直找到全局变量
func test(){
	fmt.Printf("num = %d\n" , num)
}

func main(){
	test()	
}

局部变量
局部变量又分两种:函数内部定义的变量无法在函数外部使用,例如下面的示例代码main函数中无法使用test函数中定义的变量x

package main
import "fmt"
func test(){
	var x int64 = 10
	fmt.Printf("x = %d" , x)
}
func main(){
	test()
	fmt.Println(x) //无法使用变量x
}

如果局部变量和全局变量重名优先使用局部变量

语句快作用域

package main
import "fmt"
for j:=0;j<5;j++{

}
fmt.Println(j) //不正确

if i:=10;i<18{
	
}
fmt.Println(i) //不正确

函数类型和变量
可以使用type关键字来定一个一个函数的类型

type calculation func(int , int) int

上面的语句定义了一个calculation类型,它是一种函数类型,这种函数接受两个int类型的参数并且返回一个int类型的返回值。
简单说,凡是满足这个条件的函数都是calculation类型的函数,例如如下add和sub都是calculation类型

package main
import "fmt"
func main(){
	add()
	sub()
}
func add(x,y int)int{
	return x + y
}
func sub(x,y int)int{
	return x - y
}

Go语言是静态类型的变量

函数作为参数的类型

package main
import "fmt"
func main(){
	f1(f2)
}

func f(x func()){
	
}
func f2()int{
	return 10
}
//有返回值的类型
func f1(x func()int){
	ret := x
	fmt.Println(ret)
}

函数还可以作为返回值

package main
import "fmt"
func f5(x func() int)func(int , int)int{
	ret := func (a ,b int) int{
		return a + b
	}
	return ret
}
func f2() int{
	return 10
}
func main(){
	f7 := f5(f2)
	fmt.Printf("%T\n" , f7)
}

匿名函数和闭包

匿名函数
函数当然还可以作为返回值,但是在Go语言中函数内部不能再像之前那样定义函数了,只能定义匿名函数。匿名函数就是没有函数名的函数,定义:

func(参数)(返回值){
	函数体
}

匿名函数因为没有函数名,所以没法像普通函数那样调用,所以匿名函数需要保存到某个变量或者作为立即执行函数。

package main
import "fmt"
func main(){
	//将匿名函数保存到变量
	add := func(x ,y int){
		fmt.Println(x + y)
	}
	add(2 ,3)//通过变量来调用匿名函数
	//自执行函数:匿名函数定义完加()直接执行
	func(x , y int){
		fmt.Println(x , y)
	}(100 , 200)
}

匿名函数一般都用在函数内部

闭包

闭包是一个函数,这个函数包含了它外部作用域的一个变量

package main
import "fmt"
func f1(f func()){
	fmt.Println(f1)
	f()
}
func f2 (x ,y int){
	fmt.Println("f2")
	fmt.Println(x + y)
}
func f3(f func(int , int) , x , y int)func(){
	tmp := func(){
		f(x , y)
	}
	return tmp 
}
func main(){
	f1(f3(f2 , 10 ,20))
}
package main
import "fmt"
func addr(x int)func(int)int{
	return func(y int)int{
		x+=y
		return x
	}
}

func main(){
	addr()
}
package main
import(
	"fmt"
	"strings"
)
func checksuffix(x string)func(string)string{
	return func(name string)string{
		if !strings.HasSuffix(name , x){
			return name + x
		}
		return name
	}
}

func main(){
	jpg := checksuffix(".jpg")
	txt := checksuffix(".txt")
	fmt.Println(jpg("1"))
	fmt.Println(txt("2"))
}
package main
import "fmt"
func calc(base int)(func(int)int,func(int)int){
	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 := calc(10)
	fmt.Println(f1(1) , f2(2)) //11 9
	fmt.Println(f1(3) , f2(4)) //12 8
	fmt.Println(f1(5) , f2(6)) //13 7
}

底层原理:
1.函数可以作为返回值
2.函数内部查找变量的顺序,先在自己内部找,找不到外层找

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值