This is a creation in Article, where the information may have evolved or changed.
1. Closures
Go语言中的闭包同样也会引用到函数外的变量。闭包的实现确保只要闭包还被使用,那么被闭包引用的变量会一直存在,例如:
PackageMainImport "FMT"funcMain () {varJint=5A: =func()(func()) {the func () in parentheses indicates that the return value is a func () function varIint=Ten return func() {//Returns an anonymous function hereFmt. Printf ("I, J:%v,%v\n", I, J)}} ()The //curly brace followed by a parameter list means that the anonymous function is called, and the variable a here is equal to a function.A ()//Call function aJ *=2 //Modify variables outside the function JA ()//Call function A again}
运行结果:i, j: 10, 5i, j: 10, 10
在上面的例子中,变量 a 指向的闭包函数引用了局部变量 i 和 j , i 的值被隔离,在闭包外不能被修改,改变 j 的值以后,再次调用 a ,发现结果是修改过的值。在变量 a 指向的闭包函数中,只有内部的匿名函数才能访问变量 i ,而无法通过其他途径访问到,因此保证了 i 的安全性。
2. Error handling
2.1 Error interface
Go语言引入了一个关于错误处理的标准模式,即 error 接口,该接口的定义如下:type error interface { Error() string}对于大多数函数,如果要返回错误,大致上都可以定义为如下模式,将 error 作为多种返回值中的最后一个,但这并非是强制要求:
funcintint,err error){ //....}
调用时的代码建议按如下方式处理错误情况:
n, err := Foo(0)ifnil { // 错误处理else { // 使用返回值n}
2.2 Defer keywords
Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题。
funcbool { file.Open("file") // 做一些工作 if failureX { file.Close() returnfalse } if failureY { file.Close() returnfalse } file.Close() returntrue}
我们看到上面有很多重复的代码,Go的defer有效解决了这个问题。使用它后,不但代码量减少了很多,而且程序变得更优雅。
funcbool { file.Open("file") defer//保证资源正常关闭 if failureX { returnfalse } if failureY { returnfalse } returntrue}
如果有很多调用defer,那么defer是采用后进先出模式
for i := 0; i < 5; i++ { defer fmt.Printf("%d "//输出结果:4 3 2 1 0}
defer有点类似java中的try{}finall{}
2.3 Panic and recover functions
Go语言有2个内置的函数panic()和recover(),用以报告和捕获运行时发生的程序错误,与error 不同,panic和recover一般用在函数内部。一定要注意不要滥用panic和recover,可能会导致性能问题,一般只在未知输入和不可靠请求时使用。Go语言的错误处理流程:当一个函数在执行过程中出现了异常或遇到 panic(),正常语句就会立即终止,然后执行 defer 语句,再报告异常信息,最后退出 goroutine。如果在defer中使用了recover() 函数,则会捕获错误信息,使该错误信息终止报告。如下示例,例子来自网络
PackageMainImport("Log" //log Bag "StrConv" //Character conversion package)//Capture program exceptions due to unknown inputfunccatch (Nums ...int)int{defer func() {//recover () captures exceptions that occur at run time, avoids exceptions when the program is directly over, and is typically used within the defer function ifr: =Recover(); r! =Nil{log. Println ("[E]", R)//Print the captured exception information through log without causing the program to hang} }()returnNums[1] * Nums[2] * Nums[3]//index out of range}//Active throw panic, deprecated, may cause performance issuesfuncToFloat64 (numstring) (float64, error) {defer func() {ifr: =Recover(); r! =Nil{log. Println ("[W]", R)}} ()ifnum = =""{Panic("param is null")//Active Throw Panic}returnStrConv. parsefloat (NUM,Ten) }funcMain () {catch(2,8) ToFloat64 ("")}
运行结果:2016/03/26 20:16:03 [E] runtime error: index out of range2016/03/26 20:16:03 [W] param is null