第14课:Go语言错误处理

和任何其他语言一样,Go语言也有自己的错误或异常处理
至于错误和异常的区别这里不再累述,主要是给大家详细讲下如何处理,怎么使用

有关错误处理,主要用到3个语句:defer panic recover
其中panic和recover是要谨慎使用的,可以想象,如果一段程序有很多的异常和不确定,那么这个程序肯定不是好程序
defer用的比较多,不过他的作用也并不是很大,可能大部分时候只是为了节省代码
举例:
func ReadWrite() bool {
    file.Open("godeye")
    //do something
    if failX {
        file.Close()
        return false
    }

    if failY {
        file.Close()
        return false
    }

    file.Close()
    return true
}
我们看到上面有很多重复的代码,Go的defer有效解决了这个问题。使用它后,代码量减少了很多,在defer后指定的函数会在函数退出前调用。
func ReadWrite() bool {
    file.Open("godeye")
    defer file.Close()
    if failX {
        return false
    }
    if failY {
        return false
    }
    return true
}
当然可以一次使用多个defer
defer 在声明时不会立即执行,而是在函数 return 后,再按照 FILO (先进后出)的原则依次执行每一个 defer


golang的错误处理流程:当一个函数在执行过程中出现了异常或遇到 panic(),正常语句就会立即终止,然后执行 defer 语句,再报告异常信息,最后退出 goroutine。如果在 defer 中使用了 recover() 函数,则会捕获错误信息,使该错误信息终止报告
流程实例:
package main

import (
	"log"
	"strconv"
)

//捕获因未知输入导致的程序异常
func catch(nums ...int) int {
	defer func() {
		if r := recover(); r != nil {
			log.Println("godeye:", r)
		}
	}()
	log.Println("godeye")
	return nums[1] * nums[2] * nums[3]
}

//主动抛出panic,不推荐使用,可能会导致性能问题
func toFloat64(num string) (float64, error) {
	defer func() {
		if r := recover(); r != nil {
			log.Println("godeye.org:", r)
		}
	}()
	log.Println("godeye.org")
	if num == "" {
		panic("param is null") //主动抛出panic
	}
	log.Println("www.godeye.org")
	return strconv.ParseFloat(num, 10)
}

func main() {
	catch(2, 8)
	toFloat64("")
}

运行结果:
2015/09/06 14:29:06 godeye
2015/09/06 14:29:06 godeye: runtime error: index out of range
2015/09/06 14:29:06 godeye.org
2015/09/06 14:29:06 godeye.org: param is null
跑一下上面的程序,仔细理解下执行的流程