1、系统自己抛异常

  1. //go语言抛异常
  2.  
  3. func test3_1() {
  4. l := [5] int {0,1,2,3,4}
  5.  
  6. var index int = 6
  7.  
  8. fmt.Println(l)
  9. l[index] = 6
  10.  
  11. }

测试结果

  1. //test3_1()
  2. //panic这个关键字,这是系统自己抛的异常
  3. //panic: runtime error: index out of range

 

2、用户抛异常,使用panic关键字

  1. func test3_2(s float64) (m float64) {
  2. if s < 0 {
  3. panic("该参数为半径,不能小于0")
  4.  
  5. }else {
  6. return 3.14 * s * s
  7. }
  8. }

测试结果

  1. //正常的参数,不会抛异常
  2. //res := test3_2(3.6)
  3. //fmt.Println(res)
  4. //40.6944
  5.  
  6. //res := test3_2(-3.6)
  7. //fmt.Println(res)
  8. //panic: 该参数为半径,不能小于0

3、使用defer+recover捕获函数执行过程中的异常并打印

  1. func test3_3() {
  2. defer func() {
  3. //这个recover会捕获函数执行的异常的错误信息,我们这里的例子是执行test3_2这个函数报错,使用panic抛出了异常,这里recover就会接受到这个异常,然后打印出来
  4. err := recover()
  5. if err != nil {
  6. fmt.Println(err,"1111")
  7. }
  8. }()
  9. test3_2(-2.34)
  10. fmt.Println("这里是函数3")
  11. }

测试结果

  1. //test3_3()
  2. //该参数为半径,不能小于0 1111

我们看到“这里是函数3”这句话没有打印,因为上面的函数执行出错了,就直接执行defer语句了

4、defer+recover用法2

  1. func test3_3() {
  2. defer func() {
  3. //这个recover会捕获函数执行的异常的错误信息,我们这里的例子是执行test3_2这个函数报错,使用panic抛出了异常,这里recover就会接受到这个异常,然后打印出来
  4. err := recover()
  5. if err != nil {
  6. fmt.Println(err,"1111")
  7. }
  8. }()
  9. test3_2(-2.34)
  10. fmt.Println("这里是函数3")
  11. }
  12.  
  13. func test3_4() {
  14. test3_3()
  15. fmt.Println("这里是函数4")
  16. }

测试结果

  1. //test3_4()
  2. //该参数为半径,不能小于0 1111
  3. //这里是函数4

这里打印了“这里是函数4”,主要是因为test3_3这个函数执行本身没有报错

5、使用errors.NEW返回异常,并捕获打印

  1. //接受异常
  2. func test3_5(b float64) (m float64,e error) {
  3. if b < 0 {
  4. e = errors.New("傻屌,半径不能为负数")
  5. return
  6. }else {
  7. m = b * b *3.14
  8. return
  9. }
  10. }

测试结果

  1. m,e := test3_5(3.21)
  2. fmt.Println(m,e)
  3. //32.354874 <nil>
  4.  
  5. m1,e1 := test3_5(-3.21)
  6. fmt.Println(m1,e1)
  7. //0 傻屌,半径不能为负数

Go 错误处理

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

error类型是一个接口类型,这是它的定义:

  1. type error interface {
  2. Error() string
  3. }

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。使用errors.New 可返回一个错误信息:

  1. func Sqrt(f float64) (float64, error) {
  2. if f < 0 {
  3. return 0, errors.New("math: square root of negative number")
  4. }
  5. // 实现
  6. }

在下面的例子中,我们在调用Sqrt的时候传递的一个负数,然后就得到了non-nil的error对象,将此对象与nil比较,结果为true,所以fmt.Println(fmt包在处理error时会调用Error方法)被调用,以输出错误,请看下面调用的示例代码:

  1. result, err:= Sqrt(-1)
  2.  
  3. if err != nil {
  4. fmt.Println(err)
  5. }
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. )
  6.  
  7. // 定义一个 DivideError 结构
  8. type DivideError struct {
  9. dividee int
  10. divider int
  11. }
  12.  
  13. // 实现 `error` 接口
  14. func (de *DivideError) Error() string {
  15. strFormat := `
  16. Cannot proceed, the divider is zero.
  17. dividee: %d
  18. divider: 0
  19. `
  20. return fmt.Sprintf(strFormat, de.dividee)
  21. }
  22.  
  23. // 定义 `int` 类型除法运算的函数
  24. func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
  25. if varDivider == 0 {
  26. dData := DivideError{
  27. dividee: varDividee,
  28. divider: varDivider,
  29. }
  30. errorMsg = dData.Error()
  31. return
  32. } else {
  33. return varDividee / varDivider, ""
  34. }
  35.  
  36. }
  37.  
  38. func main() {
  39.  
  40. // 正常情况
  41. if result, errorMsg := Divide(100, 10); errorMsg == "" {
  42. fmt.Println("100/10 = ", result)
  43. }
  44. // 当被除数为零的时候会返回错误信息
  45. if _, errorMsg := Divide(100, 0); errorMsg != "" {
  46. fmt.Println("errorMsg is: ", errorMsg)
  47. }
  48.  
  49. }

执行以上程序,输出结果为:

  1. 100/10 = 10
  2. errorMsg is:
  3. Cannot proceed, the divider is zero.
  4. dividee: 100
  5. divider: 0

这里应该介绍一下 panic 与 recover,一个用于主动抛出错误,一个用于捕获panic抛出的错误。

概念

panic 与 recover 是 Go 的两个内置函数,这两个内置函数用于处理 Go 运行时的错误,panic 用于主动抛出错误,recover 用来捕获 panic 抛出的错误。

  • 引发panic有两种情况,一是程序主动调用,二是程序产生运行时错误,由运行时检测并退出。
  • 发生panic后,程序会从调用panic的函数位置或发生panic的地方立即返回,逐层向上执行函数的defer语句,然后逐层打印函数调用堆栈,直到被recover捕获或运行到最外层函数。
  • panic不但可以在函数正常流程中抛出,在defer逻辑里也可以再次调用panic或抛出panicdefer里面的panic能够被后续执行的defer捕获。
  • recover用来捕获panic,阻止panic继续向上传递。recover()defer一起使用,但是defer只有在后面的函数体内直接被掉用才能捕获panic来终止异常,否则返回nil,异常继续向外传递。

例子1

  1. //以下捕获失败
  2. defer recover()
  3. defer fmt.Prinntln(recover)
  4. defer func(){
  5. func(){
  6. recover() //无效,嵌套两层
  7. }()
  8. }()
  9.  
  10. //以下捕获有效
  11. defer func(){
  12. recover()
  13. }()
  14.  
  15. func except(){
  16. recover()
  17. }
  18. func test(){
  19. defer except()
  20. panic("runtime error")
  21. }

例子2

多个panic只会捕捉最后一个:

  1. package main
  2. import "fmt"
  3. func main(){
  4. defer func(){
  5. if err := recover() ; err != nil {
  6. fmt.Println(err)
  7. }
  8. }()
  9. defer func(){
  10. panic("three")
  11. }()
  12. defer func(){
  13. panic("two")
  14. }()
  15. panic("one")
  16. }

使用场景

一般情况下有两种情况用到:

  • 程序遇到无法执行下去的错误时,抛出错误,主动结束运行。
  • 在调试程序时,通过 panic 来打印堆栈,方便定位错误。

在看一个事例

  1. if result, errorMsg := Divide(100, 10); errorMsg == "" {
  2. fmt.Println("100/10 = ", result)
  3. }
  4.  
  5. if _, errorMsg := Divide(100, 0); errorMsg != "" {
  6. fmt.Println("errorMsg is: ", errorMsg)
  7. }

上面的事例等价于下面的事例

  1. result, errorMsg := Divide(100,10)
  2. if errorMsg == ""{
  3. fmt.Println("100/10 = ", result)
  4. }
  5.  
  6. result, errorMsg = Divide(100,0)
  7. if errorMsg != ""{
  8. fmt.Println("errorMsg is: ", errorMsg)
  9. }

fmt.Println 打印结构体的时候,会把其中的 error 的返回的信息打印出来

  1. type User struct {
  2. username string
  3. password string
  4. }
  5.  
  6. func (p *User) init(username string ,password string) (*User,string) {
  7. if ""==username || ""==password {
  8. return p,p.Error()
  9. }
  10. p.username = username
  11. p.password = password
  12. return p,""}
  13.  
  14. func (p *User) Error() string {
  15. return "Usernam or password shouldn't be empty!"}
  16. }
  17.  
  18. func main() {
  19. var user User
  20. user1, _ :=user.init("","");
  21. fmt.Println(user1)
  22. }

结果如下

  1. Usernam or password shouldn't be empty!

 

字符串操作

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "strconv"
  6. )
  7.  
  8. //字符串转换
  9. //Append系列函数,把整数等转换为字符串,添加到现有的字节数组中
  10. //Format系列函数,把其他类型的转换为字符串
  11. //Parse系列函数,把字符串转换为其他类型
  12. func main() {
  13. str := make([]byte,0,100)
  14.  
  15. //10是十进制的意思
  16. str = strconv.AppendInt(str,456,16)
  17. str = strconv.AppendBool(str,false)
  18. str = strconv.AppendQuote(str,"abc")
  19. fmt.Println(string(str))
  20. }

  

go语言的错误处理的更多相关文章

  1. C语言常见错误中英文对照表

    C语言常见错误中英文对照表(网络搜索及经验积累不断更新中) 常见错误中英文对照表 fatal error C1003:  error count exceeds number; stopping co ...

  2. [日常] Go语言圣经-错误,函数值习题

    Go语言圣经-错误 1.panic异常.panic是来自被调函数的信号,表示发生了某个已知的bug 2.任何进行I/O操作的函数都会面临出现错误的可能 3.错误是软件包API和应用程序用户界面的一个重 ...

  3. 如何处理C++构造函数中的错误——兼谈不同语言的错误处理

    用C++写代码的时候总是避免不了处理错误,一般来说有两种方式,通过函数的返回值或者抛出异常.C语言的错误处理一律是通过函数的返回值来判断的,一般是返回0.NULL或者-1表示错误,或者直接返回错误代码 ...

  4. 常见C语言编译错误解析【转】

    C语言编译错误信息及说明1. 在函数 ‘transform’ 中:7: 错误:expected ‘;’ before ‘{’ token    解释:‘{’之前的某个语句缺少分号‘;’: 2. 在函数 ...

  5. 【Go语言】错误与异常处理机制

    ①error接口 Go语言中的error类型实际上是抽象了Error()方法的error接口 type error interface { Error() string } Go语言使用该接口进行标准 ...

  6. 常见C语言内存错误

    前言 C语言强大的原因之一在于几乎能掌控所有的细节,包括对内存的处理,什么时候使用内存,使用了多少内存,什么时候该释放内存,这都在程序员的掌控之中.而不像Java中,程序员是不需要花太多精力去处理垃圾 ...

  7. 多语言业务错误日志收集监控工具Sentry 安装与使用

    Sentry 是一个实时事件日志记录和汇集的平台.其专注于错误监控以及提取一切事后处理所需信息而不依赖于麻烦的用户反馈. Sentry是一个日志平台, 它分为客户端和服务端,客户端(目前客户端有Pyt ...

  8. Go 语言基础——错误处理

    #### 学习目标 掌握错误处理 掌握自定义错误处理 掌握defer关键字的使用 ------ #### 错误处理 GO没有异常处理机制 Go语言引入了一个关于错误处理的标准模式,即error接口,该 ...

  9. vs2017- C语言- winsocket- 链接错误 LNK2019

    错误介绍 操作系统:windows10 IDE:vs2017 语言:C语言 项目内容简介:编写一个双人网络海战棋对战游戏 错误类型:链接错误 LNK2019 解决方案:程序需要用到ws2_32.lib ...

随机推荐

  1. docker进阶之路-基础篇 | 二:portainer安装与基本使用

    转载请注明作者及出处: 作者:银河架构师 原文链接:https://www.cnblogs.com/luas/p/12061755.html ​简介 Portainer 是轻量级,跨平台,开源的管理D ...

  2. 11条MySQL规范,你知道的有几个?

    一.数据库命令规范 · 所有数据库对象名称必须使用小写字母并用下划线分割 · 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) · 数据库对象的命名 ...

  3. Real World CTF一日游

    今天去感受了长亭举办的RWCTF现场,参加了技术论坛,也学到了很多的知识 比较有印象的就是 智能安全在Web防护中的探索和实践 阿里云安全防护构建的AI架构体系: 基线检测 基础过滤 异常检测 攻击识 ...

  4. 吃透Python上下文管理器

    什么是上下文管理器? 我们常见的with open操作文件,就是一个上下文管理器.如: with open(file, 'rb') as f: text = f.read() 那上下文管理器具体的定义 ...

  5. MySQL数据库Group by分组之后再统计数目Count(*)与不分组直接统计数目的区别

    简述问题“统计最新时刻处于某一状态的设备的数量” 1. 首先子查询结果,可以看到每个设备最新的状态信息 2.1 在子查询的基础上,对设备状态进行分组,进行统计每个状态的设备数量 2.1.1 可以看到处 ...

  6. linux部署.net Core项目

    首篇笔记,多多关照.方便回忆和给新手指导,大神绕道 首先在Linux系统部署.net Core项目首先准备一个Linux系统的服务器,百度云,阿里云都行. 1.net core 部署在Linux系统上 ...

  7. Leetcode327: Count of Range Sum 范围和个数问题

    ###问题描述 给定一个整数数组,返回range sum 落在给定区间[lower, upper] (包含lower和upper)的个数.range sum S(i, j) 表示数组中第i 个元素到j ...

  8. Python 中国象棋源码 V1

    Pygame 做的中国象棋,一直以来喜欢下象棋,写了 python 就拿来做一个试试,水平有限,电脑走法水平低,需要在下次版本中更新电脑走法,希望源码能帮助大家更好的学习 python.总共分为四个文 ...

  9. Mysql 主从复制搭建-极简版

    前言 自己在百度.Google一番踩坑搭建成功后,记录一下,也希望后来人不再被这些坑到. 这里为了方便使用 docker,不会的同学请移步相关 Docker 教程. 正文 1. 启动 mysql #启 ...

  10. WebRTC分支提交记录

    截至2019.8.6日,webrtc官网release了M76,具体可参考:release notes WebRTC分支提交记录可以查看git commit记录. 方法:git checkout 到特 ...