问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

golang异常处理(golang异常处理最佳实践)

发布网友 发布时间:2024-10-01 08:25

我来回答

1个回答

热心网友 时间:2024-12-13 06:05

golang之context详解

为什么需要context

在go服务器中,对于每个请求的request都是在单独的goroutine中进行的,处理一个request也可能设计多个goroutine之间的交互,使用context可以使开发者方便的在这些goroutine里传递request相关的数据、取消goroutine的signal或截止日期

在并发程序中,由于超时、取消操作或者一些异常情况,往往需要进行抢占操作或者中断后续操作。熟悉channel的朋友应该都见过使用donechannel来处理此类问题。比如以下这个例子:

上述例子中定义了一个buffer为0的channeldone,子协程运行着定时任务。如果主协程需要在某个时刻发送消息通知子协程中断任务退出,那么就可以让子协程监听这个donechannel,一旦主协程关闭donechannel,那么子协程就可以推出了,这样就实现了主协程通知子协程的需求。这很好,但是这也是有限的。

如果我们可以在简单的通知上附加传递额外的信息来控制取消:为什么取消,或者有一个它必须要完成的最终期限,更或者有多个取消选项,我们需要根据额外的信息来判断选择执行哪个取消选项。

考虑下面这种情况:假如主协程中有多个任务1,2,…m,主协程对这些任务有超时控制;而其中任务1又有多个子任务1,2,…n,任务1对这些子任务也有自己的超时控制,那么这些子任务既要感知主协程的取消信号,也需要感知任务1的取消信号。

如果还是使用donechannel的用法,我们需要定义两个donechannel,子任务们需要同时监听这两个donechannel。嗯,这样其实好像也还行哈。但是如果层级更深,如果这些子任务还有子任务,那么使用donechannel的方式将会变得非常繁琐且混乱。

我们需要一种优雅的方案来实现这样一种机制:

上层任务取消后,所有的下层任务都会被取消;中间某一层的任务取消后,只会将当前任务的下层任务取消,而不会影响上层的任务以及同级任务。

这个时候context就派上用场了。我们首先看看context的结构设计和实现原理。

context接口

先看Context接口结构,看起来非常简单。

}

Context接口包含四个方法:

Deadline返回绑定当前context的任务被取消的截止时间;如果没有设定期限,将返回ok==false。

Done当绑定当前context的任务被取消时,将返回一个关闭的channel;如果当前context不会被取消,将返回nil。

Err如果Done返回的channel没有关闭,将返回nil;如果Done返回的channel已经关闭,将返回非空的值表示任务结束的原因。如果是context被取消,Err将返回Canceled;如果是context超时,Err将返回DeadlineExceeded。

Value返回context存储的键值对中当前key对应的值,如果没有对应的key,则返回nil。

可以看到Done方法返回的channel正是用来传递结束信号以抢占并中断当前任务;Deadline方法指示一段时间后当前goroutine是否会被取消;以及一个Err方法,来解释goroutine被取消的原因;而Value则用于获取特定于当前任务树的额外信息。而context所包含的额外信息键值对是如何存储的呢?其实可以想象一颗树,树的每个节点可能携带一组键值对,如果当前节点上无法找到key所对应的值,就会向上去父节点里找,直到根节点。

emptyCtx

emptyCtx是一个int类型的变量,但实现了context的接口。emptyCtx没有超时时间,不能取消,也不能存储任何额外信息,所以emptyCtx用来作为context树的根节点。

Background和TODO只是用于不同场景下:Background通常被用于主函数、初始化以及测试中,作为一个顶层的context,也就是说一般我们创建的context都是基于Background;而TODO是在不确定使用什么context的时候才会使用。

用法:

golang空指针卡死问题

golang空指针卡死解决方法如下:

1、出错的位置在执行Excute函数处,debug还是搜索百度都找不到解决方案。解决方案就是不用Goland编译文件。

2、直接使用gobuild编译文件后,再执行,访问网页就不报错了。

golang编程中,不属于异常处理的关键词是

error。Go语言又称Golang是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言,在该语言种类中error不属于异常处理的关键词,因为error仅仅是用来提示错误的词,和异常处理功能无关。

Go数据库操作异常处理

第一种写法

第二种写法

上述两种写法说明:

两种写法都没啥问题,第一种写法,如果只插入一条数据,可以使用第一种写法简单;第二种写法可以拿到执行的*DB,方便后续的DB操作

说明:

update方法将返回执行完之后的*DB,需要通过指针对象才能获取正确的RowAffected。

事务的提交也可能会有error,要判断是否正确commit

需要判断tx.Error,因为事务的提交可能会有error

其实要注意的是,没查询到结果,也会返回一个Error

gorm的ErrRecordNotFound也好理解,假设根据身份证号查询公民信息,如果是一个无效的身份证ID,那必然无法查询到结果,其实就是查询不到结果,会返回一个错误。

当然GORM提供了一个处理RecordNotFound错误的快捷方式,如果发生了多个错误,它将检查每个错误,如果它们中的任何一个是RecordNotFound错误。

当一个程序中使用两个不同的数据库时,重写方法DefaultTableNameHandler()会影响到两个数据库中的表名。其中一个数据库需要设置表前缀时,访问另一个数据库的表也可能会被加上前缀。因为是包级别的方法,整个代码里只能设置一次值。

怎么学习golang

已经有好多程序员都把Go语言描述为是一种所见即所得(WYSIWYG)的编程语言。这是说,代码要做的事和它在字面上表达的意思是完全一致的。在这些新语言中,包含D,Go,Rust和Vala语言,Go曾一度出现在TIOBE的排行榜上面。与其他新语言相比,Go的魅力明显要大很多。Go的成熟特征会得到许多开发者的欣赏,而不仅仅是因为其夸大其词的曝光度。下面我们来一起探讨一下谷歌开发的Go语言以及谈谈Go为什么会吸引众多开发者:快速简单的编译Go编译速度很快,如此快速的编译使它很容易作为脚本语言使用。关于编译速度快主要有以下几个原因:首先,Go不使用头文件;其次如果一个模块是依赖A的,这反过来又取决于B,在A里面的需求改变只需重新编译原始模块和与A相依赖的地方;最后,对象模块里面包含了足够的依赖关系信息,所以编译器不需要重新创建文件。你只需要简单地编译主模块,项目中需要的其他部分就会自动编译,很酷,是不是?通过返回数值列表来处理错误信息目前,在本地语言里面处理错误的方式主要有两种:直接返回代码或者抛异常。这两种都不是最理想的处理方式。其中返回代码是非常令人沮丧的,因为返回的错误代码经常与从函数中返回的数据相冲突。Go允许函数返回多个值来解决这个问题。这个从函数里面返回的值,可以用来检查定义的类型是否正确并且可以随时随地对函数的返回值进行检查。如果你对错误值不关心,你可以不必检查。在这两种情况下,常规的返回值都是可用的。简化的成分(优先于继承)通过使用接口,类型是有资格成为对象中一员的,就像Java指定行为一样。例如在标准库里面的IO包,定义一个Writer来指定一个方法,一个Writer函数,其中输入参数是字节数组并且返回整数类型值或者错误类型。任何类型实现一个带有相同签名的Writer方法是对IO的完全实现,Writer接口。这种是解耦代码而不是优雅。它还简化了模拟对象来进行单元测试。例如你想在数据库对象中测试一个方法,在标准语言中,你通常需要创建一个数据库对象,并且需要进行大量的初始化和协议来模拟对象。在Go里面,如果该方法需要实现一个接口,你可以创建任何对该接口有用的对象,所以,你创建了MockDatabase,这是很小的对象,只实现了几个需要运行和模拟的接口——没有构造函数,没有附件功能,只是一些方法。简化的并发性相对于其他语言,并发性在Go里面显得更加容易。把‘go’关键字放在任意函数前面然后那个函数就会在其go-routine自动运行(一个很轻的线程)。go-routines是通过通道进行交流并且基本上封锁了所有的队列消息。普通工具对相互排斥是有用,但是Go通过使用通道来踢掉并发性任务和坐标更加容易。优秀的错误消息所有与Go相似的语言,自身作出的诊断都是无法与Go相媲美的。例如,一个死锁程序,在Go运行时会通知你目前哪个线程导致了这种死锁。编译的错误信息是非常详细全面和有用的。其他这里还有许多其他吸引人的地方,下面就一概而过的介绍一下,比如高阶函数、垃圾回收、哈希映射和可扩展的数组内置语言(部分语言语法,而不是作为一个库)等等。当然,Go并不是完美无瑕。在工具方面还有些不成熟的地方和用户社区较小等,但是随着谷歌语言的不断发展,肯定会有整治措施出来。尽管许多语言,尤其是D、Rust和Vala旨在简化C++并且对其进行简化,但它们给人的感觉仍是“C++看上去要更好”。

【Go语言的优势】

可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,部署就是扔一个文件上去就完成了。

静态类型语言,但是有动态语言的感觉,静态类型的语言就是可以在编译的时候检查出来隐藏的大多数问题,动态语言的感觉就是有很多的包可以使用,写起来的效率很高。

语言层面支持并发,这个就是Go最大的特色,天生的支持并发,我曾经说过一句话,天生的基因和整容是有区别的,大家一样美丽,但是你喜欢整容的还是天生基因的美丽呢?Go就是基因里面支持的并发,可以充分的利用多核,很容易的使用并发。

内置runtime,支持垃圾回收,这属于动态语言的特性之一吧,虽然目前来说GC不算完美,但是足以应付我们所能遇到的大多数情况,特别是Go1.1之后的GC。

简单易学,Go语言的作者都有C的基因,那么Go自然而然就有了C的基因,那么Go关键字是25个,但是表达能力很强大,几乎支持大多数你在其他语言见过的特性:继承、重载、对象等。

丰富的标准库,Go目前已经内置了大量的库,特别是网络库非常强大,我最爱的也是这部分。

内置强大的工具,Go语言里面内置了很多工具链,最好的应该是gofmt工具,自动化格式化代码,能够让团队review变得如此的简单,代码格式一模一样,想不一样都很困难。

跨编译,如果你写的Go代码不包含cgo,那么就可以做到window系统编译linux的应用,如何做到的呢?Go引用了plan9的代码,这就是不依赖系统的信息。

内嵌C支持,前面说了作者是C的作者,所以Go里面也可以直接包含c代码,利用现有的丰富的C库。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
你见过最古老的东西是什么,有多少年历史 WORD中怎么输出稿纸模式word中怎么输出稿纸模式 女性尿检阴性是什么意思 阴性尿检是什么意思 尿检阴性是什么 win10如何查看电脑配置参数 win10怎样查看电脑配置参数 多地对公职人员提接种要求 亚马逊订单可以退回任何Kohl's商店,7月份生效 亚马逊提供免费退货,珠宝退货卖家要承担运费吗 新的亚马逊退货政策惹争议!官方解答来了 苏州大学好还是上海大学好 【大学PK】上海大学 VS 苏州大学 想考传播学研究生,上海大学,南京师范,苏州大学,学术气氛,就业情况哪所... 学习golang(9) 初探:go path与go mod 使用dlv排查Golang程序线上问题的过程及使用记录 绿茶有哪些品种?中国十大绿茶 周公解梦银环蛇仇人把它搞死了蛇毒搞到我和儿子眼睛里 在正常微信聊天中!被对方的老公误解!老公在微信语音中出口成脏的乱骂... 怎么样用硬盘去别人的电脑上装个游戏 怎么拿硬盘到别的电脑上拷游戏,又怎样装? 从硬盘拷贝游戏怎么弄 oppo中文叫什么 企业买断工龄以后是不是就没有干部和工人身份的区别了 OPPO的官方正式中文名是什么? 镉污染的主要来源 土壤重金属镉超标的原因是什么 我是改制企业买断工龄的职工,原企业把我的档案搞丢了,导致我退休算不到... 镉污染污染来源 四川结婚的哪些具体风俗代表了吉祥寓意? 福建结婚风俗中男方下聘礼的寓意是什么? java和go哪个简单(java和go哪个有前景) 怎么写区块链程序? 楼上是木地板如何做隔音 从咸西莲花村到广州火车总站怎么走 木地板隔音吗 五年级上册语文寒假作业第二篇习作:小发明和新发现 木地板如何隔音 如何向上司汇报工作进展情况? 请问怎么才能催领导帮忙办事? windows7家庭普通版的系统中自带的IE8看不了视频 windows7 用不了ie8 泰国办理单身证明材料_泰国旅游男人必玩项目 地面隔音材料哪些 Windows 7下IE8内核设置如何影响迅雷看看视频流畅度? 换了台电脑,装的windows7默认网页浏览器是IE8后,上某网站上传视频,但是... 隔音效果好的材料有哪些 涉外婚姻的单身证明和无犯罪记录证明在市级公证处公证有用吗? ...出身证明,单生证明,无犯罪记录证明,我应该去哪里开呢? 孙浩柯世兰是什么电视剧 孙浩柯世兰出自什么电视剧 谜砂孙浩大巴车第几集