• Golang中的匿名函数、闭包、defer、panic、recover


    匿名函数

    package main
    
    import "fmt"
    
    func main() {
    	f := func() {
    		fmt.Println("test")
    	}
    	f()
    }
    

    闭包

    下面代码中,输出的三个x的地址一定是一样的,它们引用同一个变量。

    package main
    
    import "fmt"
    
    func main() {
    	f := closure(10)
    	fmt.Println(f(1))
    	fmt.Println(f(2))
    }
    
    func closure(x int) func(int) int {
    	fmt.Println(&x)
    	return func(y int) int {
    		fmt.Println(&x)
    		return x + y
    	}
    }
    
    /* possible output:
    0xc000060068
    0xc000060068
    11
    0xc000060068
    12
    */
    
    

    defer

    • 执行方式类似其它语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行
    • 即使函数发生严重错误也会执行
    • 支持匿名函数的调用
    • 常用于资源清理、文件关闭、解锁以及记录时间等操作
    • 通过与匿名函数配合可在return之后修改函数计算结果
    • 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址

    下面这个代码中,defer时i就传值进去了。所以输出210

    package main
    
    import "fmt"
    
    func main() {
    	for i := 0; i < 3; i++ {
    		defer fmt.Print(i)
    	}
    }
    

    下面这个代码中,由于闭包中的i是对main函数中局部变量i的引用。defermain函数结束后执行,而main函数结束时i的值已经为3。所以输出3次3

    package main
    
    import "fmt"
    
    func main() {
    	for i := 0; i < 3; i++ {
    		defer func() {
    			fmt.Println(i)
    		}()
    	}
    }
    

    下面这个代码中,闭包里每一次传递的string事实上都不是同一个。所以输出的是ans2 ans1 ans0

    package main
    
    import (
    	"fmt"
    	"strconv"
    )
    
    func main() {
    	for i := 0; i < 3; i++ {
    		var t string = "ans" + strconv.Itoa(i)
    		defer func() {
    			fmt.Print(t + " ")
    		}()
    	}
    }
    

    defer配合panic与recover

    package main
    
    import "fmt"
    
    func main() {
    	f1()
    	f2()
    	f3()
    }
    
    func f1() {
    	fmt.Println("func f1")
    }
    
    func f2() {
    	// defer 一定要在 panic 之前, 因为 panic 触发时
    	// panic 所在函数就会立刻终止并倒序调用所有已经存在的defer
    	// 若 defer 在 panic 之后, 程序根本不会知道后面有 defer
    	defer func() {
    		if err := recover(); err != nil {
    			fmt.Println("err =", err)
    			fmt.Println("recover in f2 (first)")
    		}
    	}()
    	defer func() {
    		if err := recover(); err != nil {
    			fmt.Println("err =", err)
    			fmt.Println("recover in f2 (second)")
    		}
    	}()
    	panic("panic in f2")
    }
    
    func f3() {
    	fmt.Println("func f3")
    }
    /* output:
    func f1
    err = panic in f2
    recover in f2 (second)
    func f3
    */
    
  • 相关阅读:
    Flink安装排坑指南
    Java对类进行XSS过滤
    java.sql.SQLException: 无法转换为内部表示
    Flutter环境搭建
    运行npm命令 TypeError: Cannot read property 'get' of undefined
    利用Xilinx的cordic ip做开方运算
    modelsim脚本化仿真出现的两个错误
    opencv中使用imread()读入的图像,始终为显示为8位深度
    PS端时钟供给PL使用的问题
    Xilinx 使用shift_RAM消耗分布式RAM(LUTRAM)还是BRAM (Block RAM)?
  • 原文地址:https://www.cnblogs.com/sandychn/p/12421988.html
Copyright © 2020-2023  润新知