Go语言学习(七)闭包和错误处理
2017-12-29 18:20
274 查看
1.闭包
Go语言中的闭包同样也会引用到函数外的变量。闭包的实现确保只要闭包还被使用,那么被闭包引用的变量会一直存在,例如:package main import "fmt" func main(){ var j int=5 a:=func()(func()){//圆括号中的func()表示返回值是一个func()函数 var i int=10 return func(){//这里返回一个匿名函数 fmt.Printf("i,j: %v,%v\n",i,j) } }()//花括号后带参数列表表示调用匿名函数,执行到这里变量a就等于了一个函数了。 a()//调用函数a j*=2//修改函数外部的变量j a()//再次调用函数a }
运行结果:
i, j: 10,5
i, j: 10,10
在上面的例子中,变量a指向的闭包函数引用了局部变量i和j,i的值被隔离,在闭包外不能被修改,改变j的值以后,再次调用a,发现结果是修改过的值。
在变量a指向的闭包函数中,只有内部的匿名函数才能访问变量i,而无法通过其他途径访问到,因此保证了i的安全性。
2错误处理
2.1error接口
Go语言引入了一个关于错误处理的标准模式,即error接口,该接口的定义如下:type error interface {
Error() string
}
创建error通常如下:
var e error=errors.New(“…”)//需要使用errors包
对于大多数函数,如果要返回错误,大致上都可以定义为如下模式,将 error作为多种返回值中的最后一个,但这并非是强制要求:
func Foo(param int)(res int,err error){ //.... }
调用时的代码建议按如下方式处理错误情况:
n, err :=Foo(0)
if err !=nil{
4000
//错误处理
}else{
//使用返回值n
}
2.2defer关键字
Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作是,遇到错误需要提前返回,在返回前你需要关闭相关的资源,不然很容易造成资源泄露等问题。func ReadWrite() bool { file.Open("file") //做一些工作 if failureX { file.Close() return false } if failureY{ file.Close() return false } file.Close() return true } //我们看到上面有很多重复的代码,Go的defer有些解决了这个问题。使用它后。不但代码量减少了很多,而且程序变得更优雅。 func ReadWrite()bool{ file.Open("file") defer file.Close()//保证资源正常关闭 if failureX { return false } if failureY{ return false } return true } //如果有很多调用defer,那么defer是采用先进后出模式 for i:=0;i<5;i++{ defer fmt.Printf("%d",i)//输出结果:43210 }
defer有点类似java中的try{}finall{}
2.3panic和recover函数
Go语言有2个内置的函数panic()和recover(),用以报告和捕获运行时发生的错误程序,与error不同,panic和recover一般用在函数内部。一定要注意不要滥用panic和recover,可能会导致性能问题,
一般只在为之输入和不可靠请求时使用。
Go语言的错误处理流程:当一个函数在执行过程中出现了异常或遇到panic(),正常语句就会立刻终止,然后执行defer语句,再报告异常信息,最后退出goroutine.如果在defer中使用了recover()函数,则会捕获错误信息,使该错误信息终止报告。如下所示,例子来自网络
package main import( "log" //log包 "strconv" //字符转换包 ) //捕获因未知输入导致的程序异常 func catch(nums ...init) int { defer func() { //recover()可以捕获运行时发生的异常,避免异常时程序直接over,通常用在defer函数内 if r:=recover(): r !=nil{ log.Println("[E]",r)//将捕获的异常信息通过log打印,而不会导致挂掉 } }() return nums[1] *nums[2] *nums[3]//index out of range } //主动抛出panic,不推荐使用,可能会导致性能问题 func toFloat64(num string)(float64,error){ defer func(){ if r:=recover(): r !=nil{ log.Println("[W]",r) } }() if num == "" { panic("param is null")//主动抛出panic } return strconv.ParseFloat(num,10) } func main(){ catch(2,8) toFloat64("") }
运行结果:
2016/03/26 20:16:03 [E] runtime error: index out of range
2016/03/26 20:16:03 [W] param is null
最后补充下nil的介绍:
golang的nil在概念上和其他语言的null,None,Null一样,都指代零值或空值。nil是预先说明的标示符,也即通常意义上的关键字。在golang中,nil只能赋值给指针,channel,func,interface,map或slice类型的变量。如果未遵循这个规则,则会引发panic
相关文章推荐
- Go语言学习(七)闭包和错误处理
- 错误处理,匿名函数,闭包
- “OCIEnvNlsCreate 失败,返回代码为 -1,但错误消息文本不可用”的处理方法
- Sys.WebForms.PageRequestManagerServerErrorException: 在服务器上处理请求时出现未知错误解决办法
- Retrofit中 RestAdapter.LogLevel.FULL 含义,自己写错误处理方法+请求拦截器
- Oracle错误ORA-03113: end-of-file on communication channel处理办法
- openssl的错误处理
- .NET中错误中异常处理的表达方式
- Linux下的C语言编程——错误处理函数
- 如何处理错误信息 Pricing procedure could not be determined
- 关于 yum 错误 TypeError: rpmdb open failed 的处理
- 错误:仅当显式请求注释处理时才接受类名称
- DB2存储过程的事务控制以及错误处理。
- GOLANG错误处理最佳方案
- Error js内置错误 js处理错误流程 Throw语句
- php一些错误处理的方法与技巧总结
- 【windows核心编程】第一章 错误处理
- 调试的艺术学习笔记--程序崩溃处理(段错误)
- PHP学习系列之错误处理和异常捕获
- JavaScript异常错误处理