首页 > 编程语言 >学习go语言编程之错误处理

学习go语言编程之错误处理

时间:2023-08-13 23:44:52浏览次数:47  
标签:defer 函数 err 编程 go 错误处理 recover panic

error接口

Golang中有一个关于错误处理的标准模式,即:error接口。

type error interface {
	Error() string
}

对于大多数函数,如果要返回错误,大致上都可以定义为如下模式:

func Foo(param int)(n int,  err error)  {
	// ...
}

将error作为多种返回值中的一个,但是这并非强制要求。
调用代码时建议按如下方式处理错误情况:

n, err := Foo(0)
if err != nil {
    // 错误处理
} else {
    // 使用返回值n
}

defer关键字

关键字defer时Golang中一个非常有意思的特性,用于解决资源的释放问题。
示例代码如下:

func CopyFile(dst, src string)(w int64, err error)  {
	srcFile, err := os.Open(src)
	if err != nil {
		return
	}

	// 使用关键字defer标注确保这里的资源需要释放
	defer srcFile.Close()

	dstFile, err := os.Create(dst)
	if err != nil {
		return
	}

	// 使用关键字defer标注确保这里的资源需要释放
	defer dstFile.Close()

	return io.Copy(dstFile, srcFile)
}

使用defer关键字可以确保:即使其中的Copy()函数抛出异常,仍然会保证dstFilesrcFile会被正常关闭。

如果觉得一句话干不完清理的工作,也可以使用在defer后加一个匿名函数的做法:

defer func() { 
    // 多条语句执行清理工作
} ()

一个函数中可以存在多个defer语句,defer语句的调用是遵照先进后出的原则,即最后一个defer语句将最先被执行。

panic()和recover()

Golang中的两个内置函数panic()recover()用于报告和处理运行时错误和程序中的错误场景:

func panic(interface{}) 
func recover() interface{}

当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行panic流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用panic()函数时传入的参数,这个过程称为错误处理流程。
panic()的参数类型interface{}我们可以得知,该函数接收任意类型的数据,比如整型、字符串、对象等。
示例代码如下:

panic(404)
panic("network broken")
panic(errors.New("file not exists"))

recover()函数用于终止错误处理流程。
一般情况下,recover()应该在一个使用defer关键字的函数中执行以有效截取错误处理流程。
如果没有在发生异常的goroutine中明确调用恢复过程(使用recover关键字),会导致该goroutine所属的进程打印异常信息后直接退出。

如下描述一个使用recover()函数的场景:
对于foo()函数的执行要么心里没底感觉可能会触发错误处理,或者自己在其中明确加入了按特定条件触发错误处理的语句,那么可以用如下方式在调用代码中截取recover()。

defer func() { 
    if r := recover(); r != nil { 
        log.Printf("Runtime error caught: %v", r) 
    } 
}()
foo()

无论foo()中是否触发了错误处理流程,对应的匿名defer函数都将在函数退出时得到执行。
假如foo()中触发了错误处理流程,recover()函数执行将使得该错误处理过程终止。
如果错误处理流程被触发时,程序传给panic函数的参数不为nil,则该函数还会打印详细的错误信息。

标签:defer,函数,err,编程,go,错误处理,recover,panic
From: https://www.cnblogs.com/nuccch/p/17627537.html

相关文章

  • 学习go语言编程之面向对象
    类型系统类型系统是指一个语言的类型体系结构,一个典型的类型系统通常包含如下基本内容:基础类型,如:byte、int、bool、float等复合类型,如:数组、结构体、指针等可以指向任意对象的类型(Any类型)值语义和引用语义面向对象,即:所有具备面向对象特征(比如成员方法)的类型接口为类型添......
  • go语言环境要这样搭建才"省钱"
    go语言环境要这样搭建才省钱目录go语言环境要这样搭建才省钱本篇概要集成开发环境工具(ide)Goland或IntelliJIDEAVisualStudioCode其他集成开发环境VisualStudioCode的go语言开发环境搭建VisualStudioCode安装go编译环境安装配置go环境变量安装go语言插件使用golang编程本篇......
  • GUI编程
    GUI编程简介GUI的核心技术:SwingAWTAWT组件和容器Frameimportjava.awt.*;/***GUI的第一个界面*/publicclassDemo01{publicstaticvoidmain(String[]args){//FrameFrameframe=newFrame("我的第一个Java图像界面窗口");......
  • #region在多种编程语言及IDE中进行代码折叠,包括python msvc++ c#等
    vs/rider中折叠C#代码在写C#的时候,在visualstudio中可以使用#region和#endregion来进行代码折叠,那么在pycharm中是否可以呢?//这里有很多的代码......#region//这里的数百行的伪代码,可以直接折叠起来,方便阅读及归类[MenuItem("KEngine/KSFrameworkOptionsandHelp")]priva......
  • Shell编程规范与变量三
    目录1.正则表达式1.1元字符1.2表示次数1.3位置锚定1.4分组或其他1.5扩展正则表达式1.6grep2.AWK3.常用脚本1.正则表达式通配符功能是用来处理文件名,而正则表达式是处理文本内容中字符[localhost~]#man7regex#可以使用man手册帮助1.1元字符. 匹配任意单个......
  • java 8 函数式编程
    函数式编程1.Lambda表达式1.1概念对某些匿名内部类的写法优化,特点是可推导可省略。基本格式:(参数列表)->{代码}。例如:newThread(newRunnable(){@Overridepublicvoidrun(){System.out.println("运行进程");......
  • Django实现文件上传、文件列表查看、修改、限流和日志记录8
    Django实现文件上传、文件列表查看、修改、限流和日志记录8本章节,总结一些部署项目遇到的报错,希望会有所帮助NameError:name'datetime'isnotdefined报错“logging.info('用户{}在{}登录成功'.format(username,datetime.now()))NameError:name'datetime'isnotd......
  • Data structure and algorithm-One
    右边界左边界函数式编程传统的实现方式通常是将具体的功能代码直接写在方法内部。这样的实现方式对于固定的功能来说可能是足够的,但它的灵活性和复用性较低。每当需要不同的功能时,您需要编写新的方法或修改原有方法,这可能会导致代码的冗余和不易维护。而函数式编程的优点......
  • 并发编程 --- CAS原子操作
    介绍CAS(CompareAndSwap)是一种无锁算法的实现手段,中文名称为比较并交换。它由CPU的原子指令实现,可以在多线程环境下实现无锁的数据结构。原理CAS的原理是:它会先比较内存中的某个值是否和预期值相同,如果相同则更新这个值,否则不做任何操作。这整个过程是原子的,所以可以在......
  • 如何在C语言中进行图形界面编程
    在C语言中进行图形界面编程是一项非常有挑战性和有趣的任务。虽然C语言主要用于系统级编程和算法开发,但我们仍然可以使用一些库来实现简单的图形界面。在本文中,我将介绍一种在C语言中进行图形界面编程的方法。首先,让我们来了解一下几个常用的图形库,它们可以帮助我们在C语言中创建......