GO语言中的Defer与Error异常报错详细教程
目录标题
- 一、Defer
- 1. Example
- 2. Deferred methods 延迟方法
- 3. Arguments evaluation 延迟参数
- 4. Stack of defers 延迟程序堆栈
- 5. Practical use of defer 实际使用
- 二、Error
- 1. Example
- 2. PathError
- 3. DNSError
- 4. Direct Comparison 直接比较
- 5. Do not ignore errors 不要忽略错误
- 三、Custom Errors
- 1. Creating custom errors using the New function 创建自定义错误
- 2. Adding more information to the error using Errorf 添加更多信息
- 3. Providing more information about the error using struct type and fields 使用结构类型与字段展示错误
- 4. Providing more information about the error using methods on struct types 使用结构类型与方法展示错误
一、Defer
在Go语言中,defer 关键字用于延迟(defer)函数或方法的执行,即在函数执行完毕后再执行被延迟的代码块。defer 语句通常用于资源释放、
清理操作或确保某些代码在函数执行的最后一刻被执行。下面是对 defer 的几个关键点进行解释:
1.延迟执行: 使用 defer 可以将函数或方法的执行推迟到包含它的函数返回之前。当函数中的 defer 语句被执行时,相应的函数调用被推迟,并被压入一个栈中,直到包含函数返回时才会按照后进先出(LIFO)的顺序执行这些被推迟的函数调用。2.资源释放: defer 经常用于释放资源,比如打开的文件、数据库连接或网络连接等。通过在打开资源后使用 defer 来确保在函数返回之前关闭资源,可以避免资源泄漏,即使函数中途发生错误或提前返回,资源也会被正确释放。3.清理操作:defer 还可以用于执行一些清理操作,例如解锁互斥锁、关闭通道或恢复(recover)错误处理等。通过在函数开始时使用 defer,可以确保在函数执行结束时进行必要的清理。4.顺序执行: 多个 defer 语句按照它们的出现顺序进行执行。第一个 defer 语句的函数调用会在最后一个 defer 语句之前执行,即最后一个被推迟的函数调用会最先执行。
1. Example
package mainimport "fmt"func finished() {fmt.Println("Finished finding largest")}func largest(nums []int) {defer finished() // 延迟执行fmt.Println("Started finding largest")max := nums[0]for _, v := range nums {if v > max {max = v}}fmt.Println("Largest number in", nums, "is", max)}func main() {nums := []int{78, 111, 222, 333}largest(nums)}// Started finding largest// Largest number in [78 111 222 333] is 333// Finished finding largest
2. Deferred methods 延迟方法
type Person struct {firstName stringlastName string}func (p Person) fullName() {fmt.Printf("%s %s", p.firstName, p.lastName)}func main() {p := Person{firstName: "Mei",lastName: "Jin",}defer p.fullName()fmt.Printf("Welcome ")}// Welcome Mei Jin
3. Arguments evaluation 延迟参数
func printA(a int) {fmt.Println("Value of a in deferred function", a)}func main() {a := 5defer printA(a)a = 10fmt.Println("Values of before deferred function call", a)}// Values of before deferred function call 10// Value of a in deferred function 5
4. Stack of defers 延迟程序堆栈
func main() {name := "Like"fmt.Printf("Original String: %s\n", string(name))fmt.Printf("Reversed String: ")for _, v := range name {defer fmt.Printf("%c", v) // defer表示延迟调用 但是堆栈的数据时后进先出 所以导致字符串反转}}// Original String: Like// Reversed String: ekiL
5. Practical use of defer 实际使用
package mainimport ( "fmt""sync")type rect struct { length intwidth int}func (r rect) area(wg *sync.WaitGroup) { defer wg.Done()if r.length < 0 {fmt.Printf("rect %v's length should be greater than zero\n", r)return}if r.width < 0 {fmt.Printf("rect %v's width should be greater than zero\n", r)return}area := r.length * r.widthfmt.Printf("rect %v's area %d\n", r, area)}func main() { var wg sync.WaitGroupr1 := rect{-67, 89}r2 := rect{5, -67}r3 := rect{8, 9}rects := []rect{r1, r2, r3}for _, v := range rects {wg.Add(1)go v.area(&wg)}wg.Wait()fmt.Println("All go routines finished executing")}// rect {8 9}'s area 72 // rect {-67 89}'s length should be greater than zero // rect {5 -67}'s width should be greater than zero // All go routines finished executing
二、Error
1. Example
package mainimport ("fmt""os")func main() {f, err := os.Open("/test.txt") // 没有该文件if err != nil {fmt.Println(err)return}fmt.Println(f.Name(), "Opened successfully")}// open test.txt: The system cannot find the file specified.
2. PathError
package mainimport ("errors""fmt""os")func main() {f, err := os.Open("/test.txt")if err != nil {var pErr *os.PathErrorif errors.As(err, &pErr) {fmt.Println("Failed to open file at path", pErr.Path)return}fmt.Println("Generic error", err)return}fmt.Println(f.Name(), "Opened successfully")}// Failed to open file at path /test.txt
3. DNSError
package mainimport ("errors""fmt""net")func main() {addr, err := net.LookupHost("www.baidu.com")//addr, err := net.LookupHost("golangbot123.com")if err != nil {var dnsErr *net.DNSErrorif errors.As(err, &dnsErr) {if dnsErr.Timeout() { // 超时错误fmt.Println("operation time out")return}if dnsErr.Temporary() { // 临时错误fmt.Println("Temporary error")return}fmt.Println("Generic DNS error", err) // 没有这个站点return}fmt.Println("Generic error", err)return}fmt.Println(addr) // [180.101.50.242 180.101.50.188]}// 没有站点报错 Generic DNS error lookup golangbot123.com: no such host// 有站点 [180.101.50.242 180.101.50.188]
4. Direct Comparison 直接比较
package mainimport ("errors""fmt""path/filepath")func main() {files, err := filepath.Glob("go.mod")if err != nil {if errors.Is(err, filepath.ErrBadPattern) {fmt.Println("Bad pattern error:", err) // syntax error in patternreturn}fmt.Println("Generic error:", err) // 类型错误return}fmt.Println("matched files", files) // 正确打印列表 matched files [go.mod]}
5. Do not ignore errors 不要忽略错误
package mainimport ( "fmt""path/filepath")func main() { files, _ := filepath.Glob("[") // 匹配错误 如果不展示则找起错误就麻烦了fmt.Println("matched files", files)}// matched files []
三、Custom Errors
1. Creating custom errors using the New function 创建自定义错误
package mainimport ("errors""fmt""math")func circleArea(radius float64) (float64, error) {if radius < 0 { // 如果小于0则运行以下return 0, errors.New("Area calculation failed, radius is less than zero")}return math.Pi * radius * radius, nil}func main() {radius := -10.00area, err := circleArea(radius)if err != nil { // 如果为空fmt.Println(err)return}fmt.Printf("Area of circle %0.2f", area)}// Area calculation failed, radius is less than zero
2. Adding more information to the error using Errorf 添加更多信息
package mainimport ("fmt""math")func circleArea(radius float64) (float64, error) {if radius < 0 { // 如果小于0则运行以下return 0, fmt.Errorf("Area calculation failed, radius %0.2f is less than zero", radius)}return math.Pi * radius * radius, nil}func main() {radius := -10.00area, err := circleArea(radius)if err != nil { // 如果为空fmt.Println(err)return}fmt.Printf("Area of circle %0.2f", area)}// Area calculation failed, radius -10.00 is less than zero
3. Providing more information about the error using struct type and fields 使用结构类型与字段展示错误
package mainimport ("errors""fmt""math")type areaError struct {err stringradius float64}func (e *areaError) Error() string {return fmt.Sprintf("radius %0.2f:%s", e.radius, e.err)}func circleArea(radius float64) (float64, error) {if radius < 0 { // 如果小于0则运行以下return 0, &areaError{err: "radius is negative",radius: radius,}}return math.Pi * radius * radius, nil}func main() {radius := -20.0area, err := circleArea(radius)if err != nil {var areaError *areaErrorif errors.As(err, &areaError) {fmt.Printf("Area calculation failed, radius %0.2f is less than zero", areaError.radius)return}fmt.Println(err)return}fmt.Printf("Area of rectangle %0.2f", area)}// Area calculation failed, radius -20.00 is less than zero
4. Providing more information about the error using methods on struct types 使用结构类型与方法展示错误
package mainimport ( "errors""fmt")type areaError struct { err string //error descriptionlength float64 //length which caused the errorwidth float64 //width which caused the error}func (e *areaError) Error() string { return e.err}func (e *areaError) lengthNegative() bool { return e.length < 0}func (e *areaError) widthNegative() bool { return e.width < 0}func rectArea(length, width float64) (float64, error) { err := ""if length < 0 {err += "length is less than zero"}if width < 0 {if err == "" {err = "width is less than zero"} else {err += ", width is less than zero"}}if err != "" {return 0, &areaError{err: err,length: length,width: width,}}return length * width, nil}func main() { length, width := -5.0, -9.0area, err := rectArea(length, width)if err != nil {var areaError *areaErrorif errors.As(err, &areaError) {if areaError.lengthNegative() {fmt.Printf("error: length %0.2f is less than zero\n", areaError.length)}if areaError.widthNegative() {fmt.Printf("error: width %0.2f is less than zero\n", areaError.width)}return}fmt.Println(err)return}fmt.Println("area of rect", area)}// error: length -5.00 is less than zero// error: width -9.00 is less than zero
技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请点点赞收藏+关注谢谢支持 !!!
相关文章:
GO语言中的Defer与Error异常报错详细教程
目录标题 一、Defer1. Example2. Deferred methods 延迟方法3. Arguments evaluation 延迟参数4. Stack of defers 延迟程序堆栈5. Practical use of defer 实际使用 二、Error1. Example2. PathError3. DNSError4. Direct Comparison 直接比较5. Do not ignore errors 不要忽略…...

AP6315 DC单节锂电池充电IC 同步2A锂电芯片
概述 是一款面向5V交流适配器的2A锂离子电池充电器。它是采用1.5MHz固定频率的同步降压型转换器,因此具有高达90%以上的充电效率,自身发热量极小。包括完整的充电终止电路、自动再充电和一个达1%的4.2V预设充电电压,内部集成了防反灌保护、输…...

PDF校对工具正式上线,为用户提供卓越的文档校对解决方案
为满足当下对数字化文档校对的精准需求,我们今日正式发布全新的PDF校对工具。经过深入的技术研发与细致的测试,该工具旨在为企业和个人用户带来一个高效且准确的PDF文档校对平台。 PDF校对工具的主要特性: 1.全面性校对:工具支持…...
WSL 配置 Oracle 19c 客户端
Windows WSL 登陆后显示如下: Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 4.4.0-19041-Microsoft x86_64)* Documentation: https://help.ubuntu.com* Management: https://landscape.canonical.com* Support: https://ubuntu.com/advantageSystem information as…...

ChatGPT⼊门到精通(1):ChatGPT 是什么
⼀、直观感受 1、公司 OpenAI(美国) 2、官⽅⽹站 3、登录ChatGPT  at com.alibaba.druid.pool…...
软考高级系统架构设计师系列论文八十九:论软件需求分析方法和工具的选用
软考高级系统架构设计师系列论文八十九:论软件需求分析方法和工具的选用 一、软件需求相关知识点二、摘要三、正文四、总结一、软件需求相关知识点 软考高级系统架构设计师:论软件需求管理...

java八股文面试[JVM]——类加载器
一、类加载器的概念 类加载器是Java虚拟机用于加载类文件的一种机制。在Java中,每个类都由类加载器加载,并在运行时被创建为一个Class对象。类加载器负责从文件系统、网络或其他来源中加载类的字节码,并将其转换为可执行的Java对象。类加载器…...

CSS中如何实现元素之间的间距(Margin)合并效果?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 外边距合并的示例:⭐ 如何控制外边距合并:⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅ÿ…...

【实操干货】如何开始用Qt Widgets编程?(三)
Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。 在本文中࿰…...

基于深度学习的图像风格迁移发展总结
前言 本文总结深度学习领域的图像风格迁移发展脉络。重点关注随着GAN、CUT、StyleGAN、CLIP、Diffusion Model 这些网络出现以来,图像风格迁移在其上的发展。本文注重这些网络对图像风格迁移任务的影响,以及背后的关键技术和研究,并总结出一…...
小程序页面间有哪些传递数据的方法?
使用全局变量实现数据传递 在 app.js 文件中定义全局变量 globalData, 将需要存储的信息存放在里面使用的时候,直接使用 getApp() 拿到存储的信息 App({// 全局变量globalData: {userInfo: null} }) 使用 wx.navigateTo 与 wx.redirectTo 的时候&…...

bh002- Blazor hybrid / Maui 保存设置快速教程
1. 建立工程 bh002_ORM 源码 2. 添加 nuget 包 <PackageReference Include"BootstrapBlazor.WebAPI" Version"7.*" /> <PackageReference Include"FreeSql" Version"*" /> <PackageReference Include"FreeSql.…...

同源政策与CORS
CORS意为跨源资源共享(Cross origin resource sharing),它是一个W3C标准,由一系列HTTP Header组成,这些 HTTP Header决定了浏览器是否允许JavaScript 代码成功获得跨源请求的服务器响应。 在说CORS之前,先…...

科技资讯|三星再申请智能戒指商标,智能穿戴进入更小型化发展
三星正在积极扩展可穿戴设备生态,近日向英国知识产权局提交了名为“Samsung Curio”的新商标,其分类为“Class 9”,可能会用于未来的智能戒指。 智能戒指: 可穿戴计算机本质上的智能手环、智能项链、智能眼镜和智能戒指࿱…...

HarmonyOS开发第一步,熟知开发工具DevEco Studio
俗话说的好,工欲善其事,必先利其器,走进HarmonyOS第一步,开发工具必须先行,当然了,关于开发工具的使用,官网和其他的博客也有很多的讲解,但是并没有按照常用的功能进行概述ÿ…...
【应急响应】Linux常用基础命令
文章目录 文件和目录操作文件内容查看和编辑系统信息查询权限管理进程管理网络管理 文件和目录操作 ls:列出目录内容(例如 ls -l 显示详细信息) cd:切换工作目录 pwd:显示当前工作目录 touch:创建空文件&a…...

什么是Pytorch?
当谈及深度学习框架时,PyTorch 是当今备受欢迎的选择之一。作为一个开源的机器学习库,PyTorch 为研究人员和开发者们提供了一个强大的工具来构建、训练以及部署各种深度学习模型。你可能会问,PyTorch 是什么,它有什么特点…...
Baidu World 2023,定了!
1. 定了,Baidu World 2023 终于定了,今年的 Baidu World 将会于 2023-10-17 日在北京首钢园正式召开,主题为『生成未来 / PROMPT THE WORLD』,这也是近4年来 Baidu World 再次恢复线下举行。 有些小伙伴们如果还不知道什么是 Baid…...
ProxySQL+MGR高可用搭建
服务器点位 NODEIPmgr_node0192.165.26.200mgr_node1192.165.25.201mgr_node2192.165.26.202proxysql192.165.26.199 修改主机名 # 登录192.165.26.200 hostnamectl set-hostname mgr_node0 # 登录192.165.26.201 hostnamectl set-hostname mgr_node1 # 登录192.165.26.202 …...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...

工厂方法模式和抽象工厂方法模式的battle
1.案例直接上手 在这个案例里面,我们会实现这个普通的工厂方法,并且对比这个普通工厂方法和我们直接创建对象的差别在哪里,为什么需要一个工厂: 下面的这个是我们的这个案例里面涉及到的接口和对应的实现类: 两个发…...
uniapp获取当前位置和经纬度信息
1.1. 获取当前位置和经纬度信息(需要配置高的SDK) 调用uni-app官方API中的uni.chooseLocation(),即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...