Go 分布式学习利器(14)-- Go语言的错误处理
1. Go 的错误机制
Go 语言的错误机制中与其他语言的主要差异如下:
- 没有异常机制
- error 类型实现了 error接口
type error interface {Error() string }
- 可以通过errors.New来快速创建错误实例
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)
2. 错误处理的最佳实践
按照我们以上代码的处理逻辑,我们能够发现函数有多个返回值的时候 如果每个返回值都需要判断,并作出对应的错误处理,这回让代码非常冗余。
所以一般针对有多个错误 返回值的多个函数,会直接判断错误返回值不为空,直到调用到最终正常的结果才返回。
如下函数针对多个函数的多个错误返回值的正常处理:
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) // 直到所有函数都执行正常才最终输出
}
3. panic和recover
panic
关键字是Go语言中程序异常退出的关键字
- 用于不可以恢复的错误
- panic 程序退出前 会执行 defer指定的函数,并打印函数调用栈
这里先对比一下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)}}()
这样的处理错误仅仅是把异常结果打印到日志中或者直接忽略掉,这个时候可能一些错误是系统异常造成的,容易形成僵尸进程。
即如果一些异常是系统性异常(内存分配异常,磁盘异常。。。等),可以直接让进程崩溃,并将该异常告知开发者,由他决定如何处理。
相关文章:

30 个 php 操作 redis 常用方法代码例子
这篇文章主要介绍了 30 个 php 操作 redis 常用方法代码例子 , 本文其实不止 30 个方法 , 可以操作 string 类型、 list 类型和 set 类型的数据 , 需要的朋友可以参考下redis 的操作很多的,以前看到一个比较全的博客,但是现在找不到了。查个东西搜半天,下面整理一下php 处理 re…

电脑机时,电脑死机时,为啥会忍不住扇它一巴掌?
我们为什么会把自己的愤怒发泄在机器人呢?对于人们为何会打机器这个问题,国外媒体Hopes&Fears请教了很多专家,包括精神治疗医师、机械工程师、愤怒管理专家以及流行文化专家。有一场非常重要的会议就要召开了,你必须在五分钟时…

Android所有系统版本USB调试模式打开方法
参考 Android所有系统版本USB调试模式打开方法

docker(4)docker的网络,自定义网桥
Docker 的网络 运行 ifconfig 找到 docker0 : 虚拟网卡默认网卡名称为docker0 查看docker 的网桥: 我这里默认们没有进行安装 网桥管理设备:进行安装一下; yum install bridge-utils 命令:查看网桥crctl show: 注意上图中的i…

Go 分布式学习利器(15) -- Go 实现 深搜和广搜
强化语法,回顾算法。 通过Go语言实现 深度优先搜索 和 广度优先搜索,来查找社交网络中的三度好友关系(三度指的是一个节点到 其相邻节点 到 其相邻节点的节点 ,图递增三层好友关系)。 涉及到的Go语言语法:…

css背景属性
CSS背景: 属性 描述 background 简写属性,作用是将背景属性设置在一个声明中。 background-attachment 背景图像是否固定或者随着页面的其余部分滚动。 background-color 设置元素的背景颜色。 background-image 把图像设置为背景。 backgroun…

scp服务器复制命令跳过已有的文件夹,Linux scp命令复制文件到其它服务器上
例如:我想将59.64.30.101中的文件复制到59.64.28.78服务器。步骤如下:1.59.64.30.101终端执行如下命令#ssh-keygen -t rsa2.密钥生成后会在/root/.ssh/文件夹下产生两个文件id_rsa id_rsa.pub将id_rsa.pub文件复制到59.64.28.78执行如下命令scp id_rsa.p…

Win2008学习(二),群集的仲裁配置
当群集中的节点发生故障时,会有其它节点继续提供服务。不过,当节点之间的通信有问题或太多故障节点时,群集服务就会停止,可是群集可以容纳多少个节点故障呢?这要由仲裁配置(Quorum Configuration࿰…

前端token刷新并发处理
添加中间件,处理多个前端来的请求时,如果token需要刷新,先查看缓存,如果没有就在redis中做个标志位进行短期缓存,其他的请求发现缓存中的token,就不再刷新token了。这样就避免了重复刷新token的问题。 中间…

Rocksdb 的一些参数调优策略
文章目录写性能优化CF write buffer sizeDB write buffer size读性能优化block cachebloom filterCompression 压缩Compaction优化通用workload的配置本文在rocksdb 整个读写链路基础上给出一些简单的调优策略,主要是通过调整一些 参数来满足我们大多数workload的性…

Java项目:酒店管理系统(java+SSM+jsp+mysql+maven)
源码获取:博客首页 "资源" 里下载! 主要技术:java springmvc mybatis mysql tomcat js jauery jsp log4j等一些常见基本技术适用于Java毕设和学习使用 主要实现: 前台:登录、注册、酒店信息浏览、搜索酒店信息…

设计模式之装饰模式(Java实现)
“怎么了,鱼哥?” “唉,别提了,网购了一件衣服,结果发现和商家描述的差太多了,有色差就算了,质量还不好,质量不好就算了,竟然大小也不行,说好的3个Xÿ…

ueditor与七牛云存储结合
2019独角兽企业重金招聘Python工程师标准>>> 摘要: ueditor与七牛云存储结合,主要是表单api. ueditor上传图片到七牛云存储 ueditor结合七牛传图片 传统上,图片是存在自己的服务器上(图片->自己服务器),如果使用…

微服务网关从零搭建——(七)更改存储方式为oracle
资源准备: 下载开源项目 新建oracle表: -- ---------------------------- -- Table structure for OcelotGlobalConfiguration -- ----------------------------CREATE TABLE OcelotGlobalConfiguration (Id NUMBER(11) NOT NULL ,GatewayName NVARCHAR2…

Rocksdb 的优秀代码(一) -- 工业级分桶算法实现分位数p50,p99,p9999
文章目录基本概念普通的分位数计算Rocksdb中的应用rocksdb中的分桶算法结果展示rocksdb 分桶算法实现一些总结 和 相关论文我们知道一个完整的监控系统必须存在p99/p999等分位数指标,作为系统可用性的评判标准之一。而像开源监控系统中做的很不错的grafana和prometh…

Java项目:前后端分离疫情防疫平台设计和实现(java+springmvc+VUE+node.js+mybatis+mysql+springboot+redis+jsp)
源码获取:博客首页 "资源" 里下载! 主要技术:Java、springmvc、VUE、node.js、mybatis、mysql、tomcat、jquery、layui、bootstarp、JavaScript、html、css、jsp、log4j等一些常见的基本技术。 主要模块功能有: 管理员…

js里的匿名函数 数组排序
// 匿名函数:其实就是函数的简写形式 var method function(){ alert("123"); } method(); // 匿名函数可以用于事件的处理 function func(){ alert("456"); } window.οnlοadfunc; window.οnlοadfunction(){ alert("加载完成࿰…

oracle监听器动态注册于静态注册的区别
2019独角兽企业重金招聘Python工程师标准>>> 1, oracle 10g 用netca方式建立的都默认为动态注册方式 2,如果想改为静态注册的方式则在listener.ora 中加入如下内容即可 SID_LIST_LISTENER (SID_LIST (SID_DESC (SID_NAME PLSExtProc) (ORACLE_HOME …

什么是Singleton?
Singleton:在Java中即指单例设计模式,它是软件开发中最常用的设计模式之一。 单:指唯一 例:指实例 单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。 要点: 一、单例类只能…

磁盘I:O 性能指标 以及 如何通过 fio 对nvme ssd,optane ssd, pmem 性能摸底
文章目录1. 磁盘I/O性能指标1.1 性能指标1.2 I/O 观测1.2.1 磁盘I/O 观测1.2.2 进程I/O观测2. Fio 性能测试2.1 环境准备2.2 测试维度选择2.3 测试2.3.1 optane ssd和nvme ssd性能测试2.3.2 aep性能测试(intel persistent memory)真正测试之前 我们需要清楚 评判磁盘I/O性能 是…

Java项目:旅游网站管理系统设计和实现(java+springboot+jsp+mysql+spring)
源码获取:博客首页 "资源" 里下载! 运行环境: java jdk 1.8 IDE环境: IDEA tomcat环境: Tomcat 7.x,8.x,9.x版本均可 主要功能说明: 管理员角色包含以下功能:管理员登录,用户管理,旅游路线管理,…

稀疏矩阵十字链表表示
类型定义 #include<stdio.h> #include<malloc.h> #include<stdlib.h> #define MAX 100 /*稀疏矩阵的十字链表表示:非零元素节点与表头节点公用一种类型 */ typedef struct matrixnode {int row,col;struct matrixnode *right,*down;union{int val…

thrift框架使用C++
2019独角兽企业重金招聘Python工程师标准>>> 1. 编写thrift接口文件student.thrift struct Student{1: i32 sno,2: string sname,3: bool ssex,4: i16 sage, } service Serv{i32 put(1: Student s), } 2. 用“thrift -r --gen cpp student.thrift”在gen-cpp文件夹中…

shell编程:实现shell字符串连接功能
功能:实现shell字符串连接功能 a0 s1test. s2.wav s3.mp3 s40 s500str"sox ./${s1}${a}${s2} ./${a}${s3}"./tts -c bcgirl.0.0.4.bin -b 1 -i input.txt -s 1.0 -speed 1.0 $str rm ./*.wav转载于:https://www.cnblogs.com/kay2018/p/10673110.html

一文运维zookeeper
文章目录1. zookeeper生产环境的安装配置1.1 软件配置1.2 硬件配置1.3 日志配置文件1.4 配置三节点的zookeeper集群2. zookeeper的监控方法2.1 four letters命令2.2 JMX 监控方式3. 通过zookeeper observer实现跨地域部署3.1 什么是observer3.2 observer 提升 写性能3.3 observ…

Java项目:电商书城平台系统设计和实现(java+springboot+mysql+spring+jsp)
源码获取:博客首页 "资源" 里下载! JAVA springboot 电商书城平台系统(已调试) 主要实现了书城网站的浏览、加入购物车操作、订单操作、支付操作、分类查看、搜索、以及后台上传图书信息以及订单管理和一些基本操作功能 主要功能截图如下&…

(周三赛)FATE
//题意 打怪的经验值 ,消耗忍耐度 看升级后还能保留的最大忍耐度 用 背包去做,不是很会啊 T T Description 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感&#…

ASP.NET MVC 3中ViewBag, ViewData和 TempData
ViewBag, ViewData十分类似,都可用于把数据从controller传递到view。 ViewBag是WebViewPage中的一个属性,它的类型是dynamic。dynamic类型可以理解为,编译器在编译到这种类型时,会跳过类型检查,而在运行时做这些事情。…

如何在指定文件夹下进入jupyter notebook
第一步: 打开 Anaconda Prompt 第二步: 查看文件夹所在路径 例如:你有个jupyterwork文件夹在 D:\ 路径下 第三步: 在Anaconda Prompt依次输入一下命令: d:cd jupyterworkjupyter notebook完成。转载于:https://www.cnb…

Go 分布式学习利器(16) -- go中可复用的package构建
通过本文,你将了解go 语言中如何将自己的package构建到项目中 以及如何将远程(github)的package构建到项目中。 1. 构建本地的package package 是可复用模块的基本单元,以首字母大写的函数实现来表明可被包外代码访问代码的pack…