Go语言没有提供像Java、C#、Python语言中的try...catch异常处理方式,而是通过函数返回值逐层往上抛。好处就是避免漏掉本应处理的错误。坏处是代码啰嗦。

错误与异常区别

错误指的是可能出现问题的地方出了问题,比如打开文件失败。
异常是不应该出现问题的地方出了问题,比如空指针。
Go中的错误是一种类型,错误用内置的error类型(接口)来表示。错误可以存储在变量中,从函数中返回。

type error interface {
Error() string
}

创建自定义错误

创建自定义错误可用errors包下的New()函数以及fmt包下的Errorf()函数。

//创建一个error的数据
err1 := errors.New("自己创建...")
fmt.Println(err1)
fmt.Printf("%T\n", err1) //*errors.fundamental
//创建一个error方法
err2 := fmt.Errorf("错误码:%d", 10000)
fmt.Println(err2) //错误码:10000
fmt.Printf("%T\n", err2) //*errors.errorString

自定义错误示例

//求矩形面积
type areaError struct {
msg string //错误描述
length float64 //矩形长度
wigth float64 //矩形宽度
} func (e *areaError) Error() string {
return e.msg
}
func (e *areaError) lengthNegative() bool {
return e.length < 0 //如果比0小,返回false
}
func (e *areaError) wigthNegative() bool {
return e.wigth < 0 //如果比0小,返回false
}
func revArea(length, wigth float64) (float64, error) {
msg := ""
if length < 0 {
msg = "长度小于0"
}
if wigth < 0 {
if msg == "" {
msg = "宽度小于0"
} else {
msg += ",宽度小于0"
}
}
if msg != "" {
return 0, &areaError{msg, length, wigth}
}
return length * wigth, nil
}
func main() {
length, wigth := -4.3, -6.7
area, err := revArea(length, wigth)
if err != nil {
fmt.Println(err)
//断言判断具体error
if err, ok := err.(*areaError); ok {
if err.lengthNegative() {
fmt.Printf("error:长度,%.2f小于0\n", err.length)
}
if err.wigthNegative() {
fmt.Printf("error:宽度,%.2f小于0\n", err.wigth)
}
}
return
}
fmt.Println("矩形面积是:", area)
}
输入:
长度小于0,宽度小于0
error:长度,-4.30小于0
error:宽度,-6.70小于0

panic/recover

GO可以使用panic/recover模式来处理错误。 panic可以在任何地方引发,但recover只有在defer调用的函数中有效。
等到包含defer语句的函数执行完毕时,延迟函数(defer后的函数)才会被执行,而不管包含defer语句的函数是通过return的正常结束,还是由于panic导致的异常结束,你可以在一个函数中执行多条 defer语句,它们的执 行顺序与声明顺序相反。

panic:

  1. 内建函数
  2. 假如函数F中书写了panic语句,会终止其后要执行的代码,在panic所在函数F内如果存在要执行的defer函数列表,按照defer的逆序执行
  3. 返回函数F的调用者G,在G中,调用函数F语句之后的代码不会执行,假如函数G中存在要执行的defer函数列表,按照defert的逆序执行,这里的 defer有点类似 try-catch-finally中的finally
  4. 直到 goroutine整个退出,并报告错误

recover

  1. 内建函数
  2. 用来控制一个goroutine的panicking行为,捕获panic,从而影响应用的行为
  3. 一般的调用建议:在defer函数中,通过recever来终止一个goroutine的 panicking过程,从而恢复正常代码的执行;可以获取通过panic传递的 error
    简单来讲go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理.

实例

func a()  {
fmt.Println("func a")
}
func b() {
panic("func b")
}
func c() {
fmt.Println("func c")
}
func main() {
a()
b()
c()
}

执行到func b的时候会抛出异常,程序崩溃,可以使用recover将程序恢复

func a()  {
fmt.Println("func a")
}
func b() {
defer func() {
err := recover()
if err != nil{
fmt.Println("recover fun b")
}
}()
panic("func b")
}
func c() {
fmt.Println("func c")
}
func main() {
a() //func a
b() //recover fun b
c() //func c
}
  • recover()必须搭配defer使用。
  • defer一定要在可能引发panic的语句之前定义。

GO语言Error处理的更多相关文章

  1. 不一样的go语言-error

    前言   go语言的error处理方式,在目前流行的编程语言中属于刺头.似乎天生就是用来有别于他人标记.TIOBE排行榜全十除了C语言,无一例外是try catch的阵营.而排在go之前的语言除了C与 ...

  2. c语言 error C4996: 'strupr': The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name

    问题: 在使用visual studio 2013,进行调试执行代码时,出现如下错误: error C4996: 'strupr': The POSIX name for this item is d ...

  3. c语言-error C2440: “static_cast”: 无法从“UINT (__thiscall CHyperLink::* )(CPoint)”转换为“LRESULT (__thiscall CWnd::* )(CPoint)”

    出现这个错误的原因可是“人力不可抗拒”之原因造成的,因为旧版本的 ON_WM_NCHITTEST 宏使用了 UINT (__thiscall CWzButton::* )(CPoint); 类型的类成 ...

  4. 07. Go 语言接口

    Go 语言接口 接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程. Go 语言中使用组合实现对象特性的描述.对象的内部使用结构体内嵌组合对象应该具 ...

  5. golang error错误处理

    error定义 数据结构 go语言error是一普通的值,实现方式为简单一个接口. // The error built-in interface type is the conventional i ...

  6. flask框架(二):简单的登录demo

    一:main.py # -*- coding: utf-8 -*- # @Author : Felix Wang # @time : 2018/7/3 22:58 from flask import ...

  7. 3_JSP

    一. 引言 1.1 现有问题 在之前学习Servlet时, 服务器通过Servlet响应客户端页面, 有什么不足之处? 开发方式麻烦: 继承父类, 覆盖方法, 配置web.xml或注解 代码修改麻烦: ...

  8. [转载]VS2012编译C语言scanf函数error的解决方法

    在VS 2012 中编译 C 语言项目,如果使用了 scanf 函数,编译时便会提示如下错误: error C4996: 'scanf': This function or variable may ...

  9. 与非java语言使用RSA加解密遇到的问题:algid parse error, not a sequence

    遇到的问题 在一个与Ruby语言对接的项目中,决定使用RSA算法来作为数据传输的加密与签名算法.但是,在使用Ruby生成后给我的私钥时,却发生了异常:IOException: algid parse ...

随机推荐

  1. Ruby开发小记

    基础点 1.log打印 puts "Hello!" 2.拼接字符 value1 = "today" value2 = "#{value1} is Th ...

  2. SQL SERVER-3种连接

    Nested Loops Join Merge Join Hash Join

  3. 资源管理与调度系统-资源管理系统Mesos

    资源管理与调度系统-资源管理系统Mesos 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Mesos是诞生于UC Berkeley的一个研究项目,它的设计动机是解决编程模型和计算框 ...

  4. SpringCloud学习心得—1.3—Eureka与REST API

      SpringCloud学习心得—1.3—Eureka与REST API Eureka的REST API接口 API的基本访问 Eureka REST APIEureka 作为注册中心,其本质是存储 ...

  5. virtual box 6.0 扩容原有磁盘空间 ubuntu18.04

    virtual box 6.0 扩容原有磁盘空间 ubuntu18.04 1虚拟介质管理 1.1点击菜单 1.2 修改磁罗容量大小(需要关闭虚拟机),点击应用 2使用ubuntu安装镜像将新加容量添加 ...

  6. PAT1016 × PAT1017

    本次题解是综合1016和1017两道题来讲解,原因无他,因为这两道都是模拟题,综合字符串处理.排序等考点 接手一道模拟题,一定要快速且准确地了解模拟的过程,清晰题目涉及的关键信息.比如1016要计算电 ...

  7. Centos7安装nginx后提示“Welcome to nginx on Fedora!”,conf.d目录下无default.conf文件

    问题描述 在腾讯云centos7上安装nginx sudo yum install nginx 打开默认网页显示 Welcome to nginx on Fedora! 且 /etc/nginx/co ...

  8. Two Year's Harvest

    转眼间来到这里已经两年,在懵懵懂懂中渐渐在成长,一步一步走过脚下的路.这两年你说长,时间也是不短,但说长吧,时间又匆匆在指间匆匆流走.还记得大一时老师为我们讲专业课,那时候还不知道TGB,只是在五月的 ...

  9. Fiddler——如何抓取PHP的curl请求

    前言 本文主要介绍如何使用fiddler工具,来进行抓取PHP的curl请求,如果你会使用fiddler,那就是一行代码的事, 不会也没事,本文会教你如何简单的使用. 步骤 代码 设置桥接网络为127 ...

  10. yum 安装 出错 Error: Protected multilib versions:

    例如:安装zlib出错 yum install zlib-1.2.3-29.el6.i686 Error: Protected multilib versions: zlib-1.2.3-29.el6 ...