Go 语言的错误机制中与其他语言的主要差异如下:
type error interface { Error() string
}
errors.New(" num is not in range[0,100]")
如下测试代码演示基本的错误处理:
package error_testimport ("errors""testing"
)/* 斐波那契数列 */
func GetFibList(n int) ([]int,error){ // 两个返回值if n < 2 || n > 100 { // 返回错误return nil, errors.New("n should in range [2..100]")}fibList := []int{ 1,1}for i := 2; i < n; i++ { fibList = append(fibList, fibList[i-1] + fibList[i-2])}return fibList,nil
}func TestFibArray(t *testing.T) { if v,err := GetFibList(-10);err != nil { t.Error(err)} else { t.Log(v)}
}
输出如下:
=== RUN TestFibArrayerror_test.go:24: n should in range [2..100]
--- FAIL: TestFibArray (0.00s)
如果我们需要有多种错误类型的返回,那么就需要区分不同的错误,可以通过设置预置的错误类型来 快速简便得区分不同的错误
package error_testimport ("errors""testing"
)/*区分不同的错误类型*/
var LessThanTwo = errors.New("n should large than 2")
var BiggerThanHundred = errors.New("n should small than 100")/* 斐波那契数列 */
func GetFibList(n int) ([]int,error){ /* 两个返回值 */if n < 2 { return nil, LessThanTwo}if n > 100 { return nil, BiggerThanHundred}fibList := []int{ 1,1}for i := 2; i < n; i++ { fibList = append(fibList, fibList[i-1] + fibList[i-2])}return fibList,nil
}func TestFibArray(t *testing.T) { if v,err := GetFibList(-10);err != nil { t.Error(err)} else { t.Log(v)}
}
输出如下:
=== RUN TestFibArrayerror_test.go:32: n should large than 2
--- FAIL: TestFibArray (0.00s)
按照我们以上代码的处理逻辑,我们能够发现函数有多个返回值的时候 如果每个返回值都需要判断,并作出对应的错误处理,这回让代码非常冗余。
所以一般针对有多个错误 返回值的多个函数,会直接判断错误返回值不为空,直到调用到最终正常的结果才返回。
如下函数针对多个函数的多个错误返回值的正常处理:
func GetFibList2( str string) { var (i interr errorlist []int)if i, err = strconv.Atoi(str); err != nil { // 错误输出fmt.Println("Atoi error", err)return}if list,err = GetFibList(i); err != nil{ // 错误输出fmt.Println("GetFibList error",err)return}fmt.Println(list) // 直到所有函数都执行正常才最终输出
}
panic
关键字是Go语言中程序异常退出的关键字
这里先对比一下panic
和 os.Exit
两个异常退出函数的区别
os.Exit
退出时不会调用defer函数os.Exit
退出时不会打印函数调用栈信息如下测试代码:
package errorimport ("errors""fmt""testing"
)func TestPanicVsExit(t *testing.T){ defer func(){ fmt.Println("finally execute")}()fmt.Println("start")// os.Exit(-1)panic(errors.New("something wrong"))
}
输出如下,可以看到panic能够打印调用栈和执行defer函数
=== RUN TestPanicVsExit
start
finally execute
--- FAIL: TestPanicVsExit (0.00s)
panic: something wrong [recovered]panic: something wronggoroutine 18 [running]:
testing.tRunner.func1.1(0x11199c0, 0xc00008e4a0)/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:988 +0x30d
testing.tRunner.func1(0xc0000ce120)/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:991 +0x3f9
panic(0x11199c0, 0xc00008e4a0)/usr/local/Cellar/go/1.14.6/libexec/src/runtime/panic.go:969 +0x166
command-line-arguments.TestPanicVsExit(0xc0000ce120)/Users/zhanghuigui/go/src/test/ch10/error_test/panic_test.go:17 +0xd7
testing.tRunner(0xc0000ce120, 0x114b278)/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:1039 +0xdc
created by testing.(*T).Run/usr/local/Cellar/go/1.14.6/libexec/src/testing/testing.go:1090 +0x372
FAIL command-line-arguments 0.663s
而os.Exit(-1)
则直接退出程序。
recover
关键字类似于我们C++/Java中 的try..catch
关键字,能够防止程序异常后不会退出,而执行自己想要做的异常恢复或者对应的错误处理。
Go语言通过recover完成类似其他编译型语言的错误恢复处理。
如下简单测试代码:
package errorimport ("errors""fmt""testing"
)func TestPanicVsExit(t *testing.T){ defer func(){ if err := recover(); err != nil { // 并没有做异常恢复,仅仅是把异常打出来fmt.Println("recover : ", err)}}()fmt.Println("start")panic(errors.New("something wrong")) // 通过panic 传入异常
}
最后的输出比较有趣,可以看到panic并没有让程序异常退出和打程序调用栈,异常错误直接被recover捕获,程序执行状态是PASS
=== RUN TestPanicVsExit
start
recover from something wrong
--- PASS: TestPanicVsExit (0.00s)
最常见的“错误恢复” 如下, 是不被建议使用的
defer func(){ if err := recover(); err != nil { // 并没有做异常恢复,仅仅是把异常打出来log.Error("recovered panic",err)}}()
这样的处理错误仅仅是把异常结果打印到日志中或者直接忽略掉,这个时候可能一些错误是系统异常造成的,容易形成僵尸进程。
即如果一些异常是系统性异常(内存分配异常,磁盘异常。。。等),可以直接让进程崩溃,并将该异常告知开发者,由他决定如何处理。
能够在Linux系统下体验到原生界面的网易云音乐是件不错的事情,但是它总是经常性的出现网络异常,界面无响应的问题 为了听歌的体验,进行深入探究: 首先通过终端启用网易云音乐:sudo netease-cloud-music 会得到网易云音乐运行时的信息,比如一些出错的信息 其实我已经解决了首要的问题(QSslSocket错误),因...
【错误页面处理】 訪问一个错误的控制器 訪问一个错误的方法 有些控制器和方法禁止訪问 以上訪问会提示错误信息 404 403 以上错误信息是不方便给外边用户看到的。 1. 安全隐患 2. 用户体验不好 错误信息在site/error这个地方定义的。 如今我们要自己定义错误页面来显示我们的错误信息 转载于:...
噪声的来源: 1、noise in y 2、noise in x 在有noise的情况下,vc bound还会work么??? 之前,x ~ p(x) 现在 y ~ P( y | x ) 在hoeffding的部分,只要 (x, y) 联合分布满足某个分布, 结果是一致的。 error measure:打分衡量f和g的距离 1、...
在IIS7.5打开网页的时候,提示: HTTP 错误 500.0 - Internal Server Error 调用 LoadLibraryEx 失败,在 ISAPI 筛选器 C:WindowsMicrosoft.NETFrameworkv4.0.30319\aspnet_filter.dll,经过排除发现原来是两个斜杠导...
对ARM异常(Exceptions)的理解 1 .对 ARM 异常( Exceptions )的理解 所有的系统引导程序前面中会有一段类似的代码,如下: .globl _start ;系统复位位置 _start: b reset ;各...
org.apache.shiro.authc.pam.UnsupportedTokenException org.apache.shiro.authc.UnknownAccountExce...
什么是异常处理 异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下 语法错误: 这种错误根本就过不了python解释器的语法检测,必须在程序执行前就改正逻辑错误:#TypeError:int类型不可迭代 for i in...
Ø 前言 本文主要记录 Android 的常见异常及解决办法,以备以后遇到相同问题时可以快速解决。 1. java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.la...
Python之路【第五篇】:面向对象及相关 Python之路【第五篇】:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇面向对象进阶篇其他相关 一、isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 1 2 3 4 5 6 class Foo(o...
注意,前情提示: 本代码基于《Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)》 传送门Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)_你挚爱的强哥❤给你发来1条消息❤-CSDN博客 在/api/demo/文件夹下面创建CURD.base.j...
注意,前情提示: 本代码基于《Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)》 传送门Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)_你挚爱的强哥❤给你发来1条消息❤-CSDN博客 在/api/demo/文件夹下面创建copyFileOrF...