Golang(5)-函数和错误处理

golang error处理 golang error处理error 是什么?存在的问题舍弃的try提案社区对于error堆栈解决方案go 1.13 的Error 升级 本文主要讲解golang中error的使用以及原理。主要包括以下话题。 error是什么 error 面临的问题 舍弃的try提案 社区对于error堆栈解决方案 go 1.13 对于error的提升 error 是什么? 在 golang 中我们使用 e... 阅读详情


更多关于Golang核心编程知识的文章请看:Golang核心编程(0)-目录页


可能很多习惯用C或Java的朋友发现,Add方法是以大写开头的,这并不符合驼峰式方法命名的规范,但在Go语言中,**以名字以大写开头的函数表示可被包之外的代码去调用,而以小写开头的函数则表明只能被本包调用,相当于Java中的private关键字的作用。**错误处理是学习任何编程语言都需要考虑的一个重要话题。在早期的语言中,错误处理不是语言规范的一部分,通常只作为一种编程范式存在,比如C语言中的 errno 。但自C++语言以来,语言层面上会增加错误处理的支持,比如异常(exception)的概念和 try-catch 关键字的引入。`Go语言在此功能上考虑得更为深远。漂亮的错误处理规范是Go语言最大的亮点之一。

一、函数

1.1、函数定义

前面我们已经大概介绍过函数,这里我们用一个最简单的加法函数来进行详细说明:

package mymath
import "errors"
func Add(a int, b int) (ret int, err error) {
	if a < 0 || b < 0 { // 假设这个函数只支持两个非负数字的加法
	err= errors.New("Should be non-negative numbers!")
	return
}
	return a + b, nil  // 支持多重返回值
}

如果参数列表中若干个相邻的参数类型的相同,比如上面例子中的 a 和 b ,则可以在参数列表中省略前面变量的类型声明,如下所示:

func Add(a, b int)(ret int, err error) {
	// ...
}

如果返回值列表中多个返回值的类型相同,也可以用同样的方式合并。
如果函数只有一个返回值,也可以这么写:

func Add(a, b int) int {
	// ...
}
1.2、函数调用

函数调用非常方便,只要事先导入了该函数所在的包,就可以直接按照如下所示的方式调用函数:

import "mymath"// 假设Add被放在一个叫mymath的包中
	// ...
c := mymath.Add(1, 2)

可能很多习惯用C或Java的朋友发现,Add方法是以大写开头的,这并不符合驼峰式方法命名的规范,但在Go语言中,以名字以大写开头的函数表示可被包之外的代码去调用,而以小写开头的函数则表明只能被本包调用,相当于Java中的private关键字的作用。

1.3、不定参数

接触过Java的朋友应该知道Java中有的方法可以使用不定参数,而在Go语言中,也同样提供了这项机制。

public static void fun1(int ...numbers){
        for (int number : numbers) {
            System.out.println(number);
        }
    }

 public static void main(String[] args) {
        fun1(1,2,3,4,5,6,7);
    }
1.3.1、不定参数类型

不定参数是指函数传入的参数个数为不定数量,为了做到这点,首先需要将函数定义为接受不定参数类型:

func myfunc(args ...int) {
	for _, arg := range args {
	fmt.Println(arg)
}
}

这段代码的意思是,函数 myfunc() 接受不定数量的参数,这些参数的类型全部是 int ,所以它可以用如下方式调用:

myfunc(2, 3, 4)
myfunc(1, 3, 7, 13)

形如 …type 格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数。它是一个语法糖(syntactic sugar),即这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说,使用语法糖能够增加程序的可读性,从而减少程序出错的机会。
从内部实现机理上来说,类型...type本质上是一个数组切片,也就是 []type ,这也是为什么上面的参数args可以用for循环来获得每个传入的参数。

假如没有 ...type 这样的语法糖,开发者将不得不这么写:

func myfunc2(args []int) {
	for _, arg := range args {
	fmt.Println(arg)
}
}
1.3.2、任意类型的不定参数

之前的例子中将不定参数类型约束为 int ,如果你希望传任意类型,可以指定类型为
interface{} 。

func function(args ...interface{}){
	// ...
}

在Java中,这相当于:

public static void function(int ...Object){
       //...
    }
1.4、多返回值

与C、C++和Java等开发语言的一个极大不同在于,Go语言的函数或者成员的方法可以有多个返回值,这个特性能够使我们写出比其他语言更优雅、更简洁的代码,比如 File.Read() 函数就可以同时返回读取的字节数和错误信息。如果读取文件成功,则返回值中的 n 为读取的字节数, err 为 nil ,否则 err 为具体的出错信息:
func (file *File) Read(b []byte) (n int, err Error)

同样,从上面的方法原型可以看到,我们还可以给返回值命名,就像函数的输入参数一样。返回值被命名之后,它们的值在函数开始的时候被自动初始化为空。在函数中执行不带任何参数的 return 语句时,会返回对应的返回值变量的值。

如果调用方调用了一个具有多返回值的方法,但是却不想关心其中的某个返回值,可以简单地用一个下划线“ _ ”来跳过这个返回值,比如下面的代码表示调用者在读文件的时候不想关心Read() 函数返回的错误码:
n, _ := f.Read(buf)

二、错误处理

错误处理是学习任何编程语言都需要考虑的一个重要话题。在早期的语言中,错误处理不是语言规范的一部分,通常只作为一种编程范式存在,比如C语言中的 errno 。但自C++语言以来,语言层面上会增加错误处理的支持,比如异常(exception)的概念和 try-catch 关键字的引入。`Go语言在此功能上考虑得更为深远。漂亮的错误处理规范是Go语言最大的亮点之一。

2.1、error 接口

Go语言引入了一个关于错误处理的标准模式,即error 接口,该接口的定义如下:

type error interface {
	Error() string
}

对于大多数函数,如果要返回错误,大致上都可以定义为如下模式,将 error 作为多种返回值中的最后一个,但这并非是强制要求:

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

//调用时的代码建议按如下方式处理错误情况:
n, err := Foo(0)
if err != nil {
// 错误处理
} else {
// 使用返回值n
}

一个简单的错误处理:

func main() {
	if res, err := compute(1, 2, "x"); err != nil {
		panic(err)
	} else {
		fmt.Println(res)
	}
}

func compute(a, b int, c string)(res int, err error) {
	switch c {
	case "+" :
		return a + b, nil
	case "-":
		return a - b, nil
	case "*":
		return a * b, nil
	case "/":
		return a / b, nil
	default:
		return -1, fmt.Errorf("操作符不合法")
	}
}
2.2、自定义的错误类型

首先,定义一个用于承载错误信息的类型。因为Go语言中接口的灵活性,你根本不需要从error 接口继承或者像Java一样需要使用 implements 来明确指定类型和接口之间的关系,具体代码如下:

type PathError struct {
	Op string
	Path string
	Err error
}

如果这样的话,编译器又怎能知道 PathError 可以当一个 error 来传递呢?关键在于下面的代码实现了 Error() 方法:

func (e *PathError) Error() string {
	return e.Op + " " + e.Path + ": " + e.Err.Error()
}

当syscall.Stat()失败返回 err 时,将该 err 包装到一个 PathError 对象中返回:

    func Stat(name string) (fi FileInfo, err error) {
        var stat syscall.Stat_t
                err = syscall.Stat(name, &stat)
        if err != nil {
            return nil, &PathError {"stat", name, err}
        }
        return fileInfoFromStat(&stat, name), nil
    }
2.3、defer

关键字 defer 是Go语言引入的一个非常有意思的特性,defer关键字声明的代码或者方法无论是否有错误出现都会继续执行下去,比如这些关闭资源的方法,可以用defer声明。

    func CopyFile(dst, src string) (w int64, err error) {
        srcFile, err := os.Open(src)
        if err != nil {
            return
        }
        defer srcFile.Close()
        dstFile, err := os.Create(dstName)
        if err != nil {
            return
        }
        defer dstFile.Close()
        return io.Copy(dstFile, srcFile)
    }

即使其中的 Copy() 函数抛出异常,Go仍然会保证 dstFile 和 srcFile 会被正常关闭。
如果觉得一句话干不完清理的工作,也可以使用在 defer 后加一个匿名函数的做法:

defer func() {
	// 做你复杂的清理工作
} ()

另外,一个函数中可以存在多个 defer 语句,因此需要注意的是, defer 语句的调用是类似于堆栈(Stack)遵照先进后出的原则,即最后一个 defer 语句将最先被执行。

2.4、panic()和recover()

Go语言引入了两个内置函数 panic() 和 recover() 以报告和处理运行时错误和程序中的错误场景:

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

当在一个函数执行过程中调用panic()函数时,正常的函数执行流程将立即终止,但函数中之前使用defer关键字延迟执行的语句将正常展开执行,之后该函数将返回到调用函数,并导致逐层向上执行 panic 流程,直至所属的goroutine中所有正在执行的函数被终止。错误信息将被报告,包括在调用 panic() 函数时传入的参数,这个过程称为错误处理流程。

从 panic() 的参数类型interface{}我们可以得知,该函数接收任意类型的数据,比如整
型、字符串、对象等
。调用方法很简单,下面为几个例子:

panic(404)
panic("network broken")
panic(Error("file not exists"))

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

go语言中的错误处理详解 go语言的错误处理机制 阅读详情

相关推荐

35、掌握Go语言函数返回值:多值返回与错误处理技巧

本文深入探讨了Go语言中函数返回值的用法,重点介绍了如何返回多个值以及处理返回的错误。文章通过生动的实例和实用的技巧,展示了函数返回多个值在数据处理、资源管理等方面的应用,并强调了错误处理的最佳实践。同时,本文还介绍了命名返回值、链式调用、错误处理的高级用法等高级特性,帮助读者掌握Go语言函数返回值的要点,提升代码的可读性和可维护性。

silenceallat的博客 1409

Golang : Try...Catch...

简介 Go语言中抓取异常,当你觉得代码某部分很难避免或者可能出现异常的时候, 像C++、Java等语言都有Try...Catch, 于是乎你想使用,怎么办呢... Go异常机制 下面这一篇文章已经介绍的很清楚了 http://zengzhihai.com/study/wiki/type/Z29fc3R1ZHlfaW5mbw==/id/59b54210a55d5080678b456c Try...Catch...实现 /* 抓取到的错误,catch出来 */ func catchEr..

听我一言的博客 2612

go语言实现PKCS5填充(附完整源码)

go语言实现PKCS5填充(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 347

Go语言(golang)的错误(error)处理的推荐方案

对于Go语言(golang)的错误设计,相信很多人已经体验过了,它是通过返回值的方式,来强迫调用者对错误进行处理,要么你忽略,要么你处理(处理也可以是继续返回给调用者),对于golang...

flysnow_org的博客 1268

仓储控制系统(WCS)设计

WCS系统设计方法

cetclyb的博客 2万+

详述字符集与汉字编码

字符集与字符编码是文本处理的基础概念。字符集定义字符集合(如ASCII、GB2312、Unicode),字符编码则规定字符如何存储为二进制数据。汉字编码经历了从区域化(GB2312、GBK、BIG5)到全球化(Unicode)的演进,Unicode通过UTF-8、UTF-16等编码方案实现跨语言兼容。UTF-8因兼容ASCII、节省空间且无乱码风险,成为中文互联网的主流编码。正确处理编码问题需统一标准、明确声明格式,并注意生僻字的特殊处理。

零零发不爱ai的博客 806

golang 函数返回 error

func getNum() (v int, err error) { return 0, fmt.Errorf("err %s", "haha") } func main() { if v, err := getNum(); err != nil { fmt.Println(err) // err haha } else { fmt.Println(v) } }

goddnss的博客 1374

用Python实现古诗词填字游戏(三)

古诗词做填字游戏的第三部分代码,也是最核心的部分。实现对诗文和关键字的选定,并确定文字的输出位置。

PosPro的专栏 6119

Go 语言函数返回错误 error 的方法

参见示例: import ( ... "errors" ... ) ... func TestError() error { ... return errors.New("My Error Message!") }

程序猿视角 1万+

国产FPGA开发实战:紫光同创编程软件中的约束文件详解与常见问题

本文详细解析了紫光同创FPGA编程软件中约束文件的关键配置技巧与常见问题。通过基础架构解析、时钟约束实践、物理约束调控及典型问题排查指南,帮助开发者高效掌握国产FPGA开发中的约束文件应用,提升开发效率与设计稳定性。

gin88的博客 912

CTF实战:Wireshark数据包分析从入门到精通(附经典题型解析)

本文详细介绍了Wireshark在CTF比赛中的数据包分析技巧,从基础抓包到高级协议解析,涵盖HTTP流量分析、USB键盘数据还原等实战案例。通过经典题型解析,帮助读者掌握精准过滤、文件提取等核心技能,提升CTF竞赛中的网络流量分析能力。

pz890123的博客 587

go-sqlite自定义函数开发指南:扩展SQLite功能的终极方法

go-sqlite是一款纯Go实现的SQLite驱动程序,它完全嵌入SQLite引擎,无需外部依赖。本文将详细介绍如何在go-sqlite中开发自定义函数,这是扩展SQLite功能的终极方法。通过自定义函数开发,你可以将Go的强大功能直接集成到SQL查询中,实现更复杂的数据处理逻辑。 ## 🚀 为什么需要自定义函数? SQLite本身提供了丰富的内置函数,但在实际应用中,我们经常需要: -

gitblog_00642的博客 495

【即插即用模块】注意力篇 | TGRS 2025 | CDFIM:通道+空间多尺度注意力,双模态特征融合增强,性能翻倍!

C2DFF-Net提出了一种轻量级跨模态特征融合模块CDFIM,通过模态差异感知和多尺度深度滤波增强双模态互补信息。该模块采用通道-空间注意力协同机制,以极低计算成本(仅增加0.26M参数)提升多模态目标检测性能,在三个遥感数据集上平均提升mAP约1.7%。适用于无人机等边缘设备的实时检测任务,为跨模态融合提供高效解决方案。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 626

【Go工具】go-playground除了validator还有哪些常用的库

go-playground 组织提供了多个实用的 Go 开发库,其中最值得使用的 6 个包括: form - 自动绑定表单/URL 参数到结构体,适合原生 net/http 解析参数。 universal-translator - 国际化翻译核心库,支持多语言错误提示。 errors - 增强错误处理,支持堆栈、类型和字段信息。 locales - 提供多语言本地化数据,配合翻译库使用。 pure - 轻量 HTTP 路由,零依赖且高效。 pkg - 工具函数合集,增强标准库功能。

顺顺利利的专栏 263

解决Gradle中NPM命令失效问题

摘要:本文分析了IntelliJ IDEA中Gradle执行npm命令失败的问题,报错显示"npm"文件不存在。通过确认npm安装路径、检查系统PATH与Gradle环境的差异,提出两种解决方案:1) 在build.gradle中使用npm绝对路径;2) 通过launchctl修改用户PATH。实例展示了如何修改Gradle脚本或系统配置来解决该问题,指出跨平台开发中环境变量配置的重要性。文章为开发者提供了处理类似问题的实用方法。

2501_90323865的博客 91

第58篇:AI技术实战:基于深度学习的智能音频内容审核系统

深度学习技术为智能音频内容审核系统提供了强大的支持,通过CNN、RNN和Transformer等模型,能够实现高效的音频内容检测和过滤。使用TensorFlow和Keras可以快速构建和训练音频审核模型,而预训练模型则可以进一步提升性能。数据预处理、特征提取和性能优化是提升智能音频审核系统性能的关键。希望本文的代码示例和注意事项能帮助你更好地理解和应用这些技术。接下来,我们将继续探索更多AI技术实战案例。

加入“Super Entity”,与全能开发团队共探AI智能体与数字人项目,开启前沿技术之旅。 709

【go每日一题】 并发编程

在 TestConcur 中,select 中的每个分支直接赋值给 res.ResultText、res.ResultImage 和 res.ResultVideo,这样会导致一旦有一个结果返回,其他通道可能会被阻塞。应该考虑提前判断超时逻辑,避免在业务处理逻辑中阻塞。由于 select 中的 ctx.Done() 通道已经处理了超时信号,可以直接返回并结束函数,不需要再创建额外的错误信息。context 的取消机制已经处理得很好,但为了提高代码可读性和灵活性,可以把超时设置提取为常量,而不是直接硬编码。

YiGeiGiaoGiao的博客 719

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

别再写“屎山”了!聊聊KISS原则在Python/Go项目中的5个实战技巧

本文探讨了KISS原则在Python和Go项目中的5个实战技巧,帮助开发者避免编写复杂难懂的代码。通过函数拆分、命名优化、适度抽象、错误处理和工具链约束等方法,提升代码可读性和可维护性,适用于现代软件开发场景。

cnma55226的博客 433

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

如何使用validator.v2实现Go结构体的5种基础验证

在Go语言开发中,数据验证是确保应用健壮性的关键环节。validator.v2是一个功能强大的Go结构体验证库,它通过标签(tag)系统为开发者提供了简单高效的验证方案。本文将详细介绍如何使用validator.v2实现Go结构体的5种基础验证方法,帮助您快速掌握这个实用的工具。 ## 📦 安装与基本配置 首先,通过简单的go get命令安装validator.v2: ```bash go

gitblog_00158的博客 355

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

深入剖析 Golang 的错误处理机制:让你的代码更加健壮与优雅

在 Go 语言中,错误(error)是一种内置接口类型,用于表示函数执行中出现的异常情况。与其他语言的异常机制不同,Go 的错误通过显式返回值传递,而不是抛出异常。开发者需要自行处理函数的返回值来决定下一步的操作。Go 的error任何实现了Error()方法的类型都可以作为error,并被用于函数的返回值中。虽然 Go 提供了errors.New和fmt.Errorf来生成简单的错误信息,但在某些复杂的场景下,我们可能需要定义自己的错误类型,以提供更多上下文信息。

Linke的博客 2516

【Golang学习之旅】Go 语言错误处理(error 接口、panic、recover)

✅ 适合人群:Golang 开发者 | 后端开发工程师 | 并发编程初学者✅ 文章亮点:深入解析 error、panic、recover + 代码示例 + 实战场景✅ 目标:掌握 Go 语言错误处理机制,编写健壮、高质量的 Go 代码!error🔹 Go 语言错误处理的基本原则:✅ 普通错误使用error处理(推荐方式)✅ 严重错误使用panic处理✅ 程序应尽可能优雅地恢复panic用于表示程序发生严重错误,无法继续执行,通常用于不可恢复的错误,如:✅ 数组越界✅ 空指针引用。

程序员林北北的博客 1278

[go-06] 函数、包和错误处理

函数的命名,首字母不能是数字,首字母大写是public 首字母小写是private。(重载:同名不同参的函数,重写,子类重新定义父类同名同参的函数,从而实现多态)定义的变量叫全局变量,作用域在整个包都有效,如果其首字母为大写,则作用。遇到函数,开辟一个新栈区,每一个栈区都是独立的,数据也是相互隔离的。函数的形参列表,和返回值可以是多个,可以说是值类型和引用类型。如果希望函数内的变量能修改函数外的变量,可以传入变量的地址。,可以赋值给一个变量,则该变量就是一个函数类型的变量。

m0_38134048的博客 1664

100天精通Golang(基础入门篇)——第23天:错误处理的艺术: Go语言实战指南

错误通常指的是预期可能会出现问题的地方确实出现了问题。例如,当尝试打开一个文件失败时,这种情况通常是可以预料到的。异常则是指在不应出现问题的地方却出现了问题。例如,发生了空指针引用,这种情况通常是出乎人们的意料之外的。从这可以看出,错误通常是业务过程的一部分,而异常则不是。创建自定义错误可以使用errors包下的New()函数,以及fmt包下的:Errorf()函数。//errors包://fmt包:在使用New()函数创建自定义错误之前,让我们了解它是如何实现的。下面提供了错误包中的新功能的实现。

猫头虎技术团队:授渔优于赠鱼,兴趣引领智慧,探索之乐尤显珍贵。商务合作+:Libin9iOak ,万粉变现+:优快云WF,猫头虎承诺每年免费为100名C站创作者做账号流量诊断服务!全网搜:猫头虎技术团队,点击文章底部名片或直接私信我一切皆可谈,快找虎哥! 5万+

golang学习笔记13——golang的错误处理深度剖析

在某些情况下,可以使用自定义错误类型来表示特定的错误情况。自定义错误类型可以提供更多的错误信息,方便调试和排查问题。Golang 中的错误处理是一个非常重要的方面,它直接影响到程序的稳定性和可靠性。通过显式的错误处理方式,Golang 使得错误处理代码与正常的业务逻辑代码分离,更加清晰易读。在实际开发中,我们应该遵循错误处理的最佳实践,尽早处理错误,提供详细的错误信息,避免忽略错误,使用自定义错误类型,并进行错误日志记录。这样可以提高程序的稳定性和可靠性,减少潜在的错误和问题。关注我看更多有意思的文章哦!

GoppViper的博客 1888

17 go语言(golang) - 错误处理

error使用errors.New或创建简单的文本描述性错误。err1 := errors.New("自定义错误1")err2 := fmt.Errorf("自定义错误2")输出自定义错误1自定义错误2如果需要更复杂或结构化的信息,可以定义自己的类型并实现Error()方法。code intmsg string404,"自定义错误!",输出code:404,msg:自定义错误!{404 自定义错误!

瑞瑞的博客 1190

golang学习笔记——错误处理

之类的内置函数来管理程序中的异常或意外行为。但错误是已知的失败,你的程序应该可以处理它们。函数,向错误添加更多上下文,但仍返回原始错误。将错误返回给调用方,而不执行其他任何操作。使用以下代码片段来练习各种错误处理策略。使用重试策略调用函数三次并等待两秒钟。函数允许你比较获得的错误的类型。函数,以展示如何处理错误。我们将重点介绍如何修改。函数创建错误并重复使用。

mirana的专栏 1349
上一篇: Golang(4)-数据类型
下一篇: Golang(2)-类型系统
BoringRong
BoringRong 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 2万+粉丝 386原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BoringRong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值