Go语言-defer语句
- 位置:仅能在函数和方法中
- 构成:关键字和一个表达式语句(表达式不能是内建函数和unsafe中的函数)
- 作用:最后执行;保护措施;节约资源
func readFile(path string) ([]byte, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
return ioutil.ReadAll(file)
}
func deferIt() {
defer func() {
fmt.Print(1)
}()
defer func() {
fmt.Print(2)
}()
defer func() {
fmt.Print(3)
}()
fmt.Print(4)
}
输出:4321
- 特别提示1:有参数传入,比如:fmt.Print(i + 1)。如果代表传入参数的是一个表达式,那么在defer语句被执行的时候该表达式就会被求值了
func deferIt3() {
f := func(i int) int {
fmt.Printf("%d ",i)
return i * 10
}
for i := 1; i < 5; i++ {
defer fmt.Printf("%d ", f(i))
}
}
打印出1 2 3 4 40 30 20 10
- 特别提示2:defer携带的表达式语句代表的是对匿名函数的调用(注意外部变量传递)
func deferIt4() {
for i := 1; i < 5; i++ {
defer func() {
fmt.Print(i)
}()
}
}
打印出5555
func deferIt4() {
for i := 1; i < 5; i++ {
defer func(n int) {
fmt.Print(n)
}(i)
}
}
打印出1234
Go语言异常处理——error
- 处理错误的惯用法之一:Go函数可以一次返回多个结果(怎样在传递错误)
func readFile(path string) ([]byte, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
return ioutil.ReadAll(file)
}
函数readFile有两个结果声明。第二个结果声明的类型是error。error是Go语言内置的一个接口类型
type error interface {
Error() string
}
- 怎样创造错误:调用标准库代码包errors的New函数即可
if path == "" {
return nil, errors.New("The parameter is invalid!")
}
Go语言异常处理——panic
- 可被意译为运行时恐慌,只有在程序运行的时候才会被“抛出来” == 程序崩溃
- 恐慌是会被扩散的,它会被迅速地向调用栈的上层传递。如果我们不显式地处理它的话,程序的运行瞬间就会被终止。
- 人为地产生一个运行时恐慌,可以被恢复的;内建函数recover
- 内建函数panic和recover是天生的一对。前者用于产生运行时恐慌,而后者用于“恢复”它
- recover函数必须要在defer语句中调用才有效,因为一旦有运行时恐慌发生,当前函数以及在调用栈上的所有代码都是失去对流程的控制权
- 只有defer语句携带的函数中的代码才可能在运行时恐慌迅速向调用栈上层蔓延时“拦截到”它
defer func() {
if p := recover(); p != nil {
fmt.Printf("Fatal error: %s\n", p)
}
}()
调用了recover函数。该函数会返回一个interface{}类型的值;interface{}代表空接口。Go语言中的任何类型都是它的实现类型。