广告
返回顶部
首页 > 资讯 > 后端开发 > GO >golang 语言中错误处理机制
  • 291
分享到

golang 语言中错误处理机制

2024-04-02 19:04:59 291人浏览 薄情痞子
摘要

与其他主流语言如 javascript、Java 和 python 相比,golang 的错误处理方式可能和这些你熟悉的语言有所不同。所以才有了这个想法根大家聊一聊 Golang 的

与其他主流语言如 javascript、Java 和 python 相比,golang 的错误处理方式可能和这些你熟悉的语言有所不同。所以才有了这个想法根大家聊一聊 Golang 的错误处理方式,以及实际开发中应该如何对错误进行处理。因为分享面对 Golang有一个基本的了解 developers, 所以一些简单地方就不做赘述了。

如何定义错误

在 golang 语言中,无论是在类型检查还是编译过程中,都是将错误看做值来对待,和 string 或者 integer 这些类型值并不差别。声明一个 string 类型变量和声明一个 error 类型变量是没什么区别的。

你可以定义接口作为 error 的类型,有关 error 能够提供什么样信息都是由自己决定的,这是 error 在 golang 作为值的好处,不过这样做也自然有其坏处,有关 error 定义好坏就全由其定义开发人员所决定,也就是有关 error 融入过多人为的主观因素。


package main

import (
	"fmt"
	"io/ioutil"
)

func main(){
	dir, err := ioutil.TempDir("","temp")

	if err != nil{
		fmt.Errorf("failed to create temp dir: %v",err)
	}
}

错误在语言中的重点地位

在 Go 语言中错误处理设计一直大家喜欢讨论的内容,错误处理是该语言的核心,但该语言并没有规定如何处理错误。社区已经为改进和规范错误处理做出了努力,但许多人忽略了错误在我们应用程序领域中的核心地位。也就是说,错误与客户和订单类型一样重要。

Golang中的错误

错误表示在应用程序中发生了不需要的情况。比方说,想创建一个临时目录,在那里可以为应用程序存储一些文件,但这个目录的创建失败了。这是一个不期望的情况,就可以用错误来表示。

通过创建自定义错误可以将更丰富错误信息传递给调用者。个返回值返回将错误交给调用函数人来处理错误。Golang 本身允许函数具有多个返回值,所以通常把错误作为函数最后一个参数返回给调用者来处理。

errors 是 I/O

  • 有时候开发人员是 error 的生产者(写 error)
  • 有时候开发人员又是 error 的消费者(读 error)

也就是我们开发程序一部分工作是读取和写入 error

errors 的上下文
什么是 error 的上下文呢? 如何定义 error 需要考虑一些因素,例如在不同程序我们定义 error 和处理 error 方式也不仅相同

  1. CLI 工具
  2. 长时间运行的系统

而且我们需要考虑使用程序的人群,他们是什么方式来使用系统,这些因素都是我们设计也好定义错误信息要考虑的因素。

错误的类型

就错误核心,那么错误可能是我们预料之中的错误,错误也可能是我们没有考虑到,例如无效内存,数组越界,也就是单靠代码自身暂时是解决不了的错误 ,这样的误差往往让代码恐慌,所以 Panic。通常这样错误对于程序是灾难性的失败,无法修复的。

自定义错误

如前所述,错误使用内置的错误接口类型来表示,其定义如下。


type error interface {  
    Error() string
}

下面举了 2 例子来定义 error ,分别定义两个 struct 都实现了 Error() 接口即可


type SyntaxError struct {
    Line int
    Col  int
}

func (e *SyntaxError) Error() string {
    return fmt.Sprintf("%d:%d: syntax error", e.Line, e.Col)
}

type InternalError struct {
    Path string
}

func (e *InternalError) Error() string {
    return fmt.Sprintf("parse %v: internal error", e.Path)
}

该接口包含一个方法 Error() ,以字符串形式返回错误信息。每一个实现了错误接口的类型都可以作为一个错误使用。当使用 fmt.Println 等方法打印错误时,Golang 会自动调用 Error() 方法。

在 Golang 中,有多种创建自定义错误信息的方法,每一种都有自己的优点和缺点。

基于字符串的错误

基于字符串的错误可以用 Golang 中两个开箱即用方法来自定义错误,适用哪些仅返回描述错误信息的相对来说比较简单的错误。


err := errors.New("math: divided by zero")

将错误信息传入到 errors.New() 方法可以用来新建一个错误


err2 := fmt.Errorf("math: %g cannot be divided by zero", x)

fmt.Errorf 通过字符串格式方式,可以将错误信息包含你错误信息中。也就是为错误信息添加了一些格式化的功能。

自定义数据结构的错误

可以通过在你的结构上实现 Error 接口中定义的 Error() 函数来创建自定义的错误类型。下面是一个例子。

Defer, panic 和 recover

Go 并不像许多其他编程语言(包括 Java 和 Javascript )那样有异常,但有一个类似的机制,即 "Defer, panic 和 recover"。然而,panic 和 recover 的使用情况与其他编程语言中的异常非常不同,因为代码本身无法应对时候和不可恢复的情况下使用。

Defer

有点类似析构函数,在函数执行完毕后做一些资源释放等收尾工作,好处其执行和其在代码中位置并没有关系,所以可以将其写在你读写资源语句后面,以免随后忘记做一些资源释放的工作。关于 defer 输出也是面试时,面试官喜欢问的一个问题。


package main

import(
	"fmt"
	"os"
)

func main(){
	f := createFile("tmp/Machinelearning.txt")
	defer closeFile(f)
	writeFile(f)
}

func createFile(p string) *os.File {
	fmt.Println("creating")
	f, err := os.Create(p)
	if err != nil{
		panic(err)
	}
	return f
}

func closeFile(f *os.File){
	fmt.Println("closing")
	err := f.Close()

	if err != nil{
		fmt.Fprintf(os.Stderr, "error:%v\n",err)
		os.Exit(1)
	}
}

func writeFile(f *os.File){
	fmt.Println("writing")
	fmt.Fprintln(f,"machine leanring")
}

defer 语句会将函数推入到一个栈结构中。同时栈结构中的函数会在 return 语句执行后被调用。


package main


import "fmt"

func main(){
	// defer fmt.Println("Word")
	// fmt.Println("hello")

	fmt.Println("hello")
	for i := 0; i <=3; i++ {
		defer fmt.Println(i)
	}
	fmt.Println("world")
}

hello
world
3
2
1
0

可以通过在你的结构上实现 Error 接口中定义的 Error() 函数来实现自定义错误类型,下面是一个例子。

Panic

panic 语句向 Golang 发出信号,这时通常是代码无法解决当前的问题,所以停止代码的正常执行流程。一旦调用了 panic,所有的延迟函数都会被执行,并且程序会崩溃,其日志信息包括 panic 值(通常是错误信息)和堆栈跟踪。

举个例子,当一个数字被除以0时,Golang会出现 panic。


package main

import "fmt"

func main(){
	divide(5)
}

func divide(x int){
	fmt.Printf("divide(%d)\n",x+0/x)
	divide(x-1)
}

divide(5)
divide(4)
divide(3)
divide(2)
divide(1)
panic: runtime error: integer divide by zero

goroutine 1 [running]:
main.divide(0x0)
        /Users/zidea2020/Desktop/mysite/go_tut/main.go:10 +0xdb
main.divide(0x1)
        /Users/zidea2020/Desktop/mysite/go_tut/main.go:11 +0xcc
main.divide(0x2)
        /Users/zidea2020/Desktop/mysite/go_tut/main.go:11 +0xcc
main.divide(0x3)
        /Users/zidea2020/Desktop/mysite/go_tut/main.go:11 +0xcc
main.divide(0x4)
        /Users/zidea2020/Desktop/mysite/go_tut/main.go:11 +0xcc
main.divide(0x5)
        /Users/zidea2020/Desktop/mysite/go_tut/main.go:11 +0xcc
main.main()
        /Users/zidea2020/Desktop/mysite/go_tut/main.go:6 +0x2a
exit status 2

Recover

Go语言提供了recover内置函数,前面提到,一旦panic,逻辑就会走到defer那,那我们就在defer那等着,调用recover函数将会捕获到当前的panic,被捕获到的panic就不会向上传递了。然后,恢复将结束当前的 Panic 状态,并返回 Panic 的错误值。


package main

import "fmt"

func main(){
	accessSlice([]int{1,2,5,6,7,8}, 0)
}

func accessSlice(slice []int, index int) {
	defer func() {
		if p := recover(); p != nil {
			fmt.Printf("internal error: %v", p)
		}
	}()

	fmt.Printf("item %d, value %d \n", index, slice[index])
	defer fmt.Printf("defer %d \n", index)
	accessSlice(slice, index+1)
}

包装错误

Golang 也允许对错误进行包裹,通过错误嵌套,在原有错误信息上添加一个额外信息帮助调用者对问题判断以及后续应该如何处理信息。以通过使用 %w 标志和 fmt.Errorf 函数来对原有的错误进行保存提供一些特定的信息,如下例所示。


package main

import (
	"errors"
	"fmt"
	"os"
)

func main() {
	err := openFile("non-existing")

	if err != nil {
		fmt.Printf("error running program: %s \n", err.Error())
	}
}

func openFile(filename string) error {
	if _, err := os.Open(filename); err != nil {
		return fmt.Errorf("error opening %s: %w", filename, err)
	}

	return nil
}

上面已经通过代码演示如何包装一个错误,程序会打印输出使用 fmt.Errorf 添加文件名的包装过的错误,也打印了传递给 %w 标志的原有错误信息。这里再补充一个 Golang 还提供的功能,通过使用 error.Unwrap 来还原错误信息,从而获得原有的错误信息。


package main

import (
	"errors"
	"fmt"
	"os"
)

func main() {
	err := openFile("non-existing")

	if err != nil {
		fmt.Printf("error running program: %s \n", err.Error())

		// Unwrap error
		unwrappedErr := errors.Unwrap(err)
		fmt.Printf("unwrapped error: %v \n", unwrappedErr)
	}
}

func openFile(filename string) error {
	if _, err := os.Open(filename); err != nil {
		return fmt.Errorf("error opening %s: %w", filename, err)
	}

	return nil
}

错误的类型转换

有时候需要在不同的错误类型之间进行转换,有情况需要通过类型转换来为错误添加信息,或者换一种表达方式,。 errors.As 函数提供了一个简单而安全的方法,通过寻找错误链中匹配错误类型进行转化输出。如果没有找到匹配的,该函数返回 false 。


package main

import (
	"errors"
	"fmt"
	"io/fs"
	"os"
)

func main(){
	// Casting error
	if _, err := os.Open("non-existing"); err != nil {
		var pathError *os.PathError
		if errors.As(err, &pathError) {
			fmt.Println("Failed at path:", pathError.Path)
		} else {
			fmt.Println(err)
		}
	}
}

在这里,试图将通用错误类型转换为 os.PathError ,这样就可以访问该特定的错误信息,这些信息保存在结构体中的 Path 属性上。

错误类型检查

Golang 提供了 errors.Is 函数来用于检查错误类型是否为指定的错误类型,该函数返回一个布尔值值来表示是否为指定错误类型。


package main

import (
	"errors"
	"fmt"
	"io/fs"
	"os"
)

func main(){
	// Check if error is a specific type
	if _, err := os.Open("non-existing"); err != nil {
		if errors.Is(err, fs.ErrNotExist) {
			fmt.Println("file does not exist")
		} else {
			fmt.Println(err)
		}
	}
}

到此这篇关于golang 语言中错误处理机制的文章就介绍到这了,更多相关golang 错误处理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

本文标题: golang 语言中错误处理机制

本文链接: https://www.lsjlt.com/news/133947.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • golang 语言中错误处理机制
    与其他主流语言如 Javascript、Java 和 Python 相比,Golang 的错误处理方式可能和这些你熟悉的语言有所不同。所以才有了这个想法根大家聊一聊 golang 的...
    99+
    2022-11-12
  • SpringBoot2.1.4中的错误处理机制
    目录SpringBoot 2.1.4 错误处理机制SpringBoot错误机制原理SpringBoot 2.1.3 错误处理机制引用的问题做个标记错误处理机制SpringBoot 2...
    99+
    2022-11-12
  • Go语言中怎么有效处理错误
    今天就跟大家聊聊有关Go语言中怎么有效处理错误,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、简介Go语言受到诟病最多的一项就是其错误处理机制。如...
    99+
    2022-10-19
  • Go语言的错误处理方式
    这篇文章主要介绍“Go语言的错误处理方式”,在日常操作中,相信很多人在Go语言的错误处理方式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Go语言的错误处理方式”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-15
  • PHP中的错误及其处理机制
    目录什么是错误?Fatal Error:致命错误(脚本终止运行)Parse Error:编译时解析错误,语法错误(脚本终止运行)Warning Error:警告错误(仅给出提示信息,...
    99+
    2022-11-12
  • Go语言中路由的错误处理技巧
    Go语言中路由的错误处理技巧引言:在使用Go语言开发Web应用程序时,路由是一个非常重要的组件。路由的作用是根据请求的URL路径将请求映射到相应的处理程序。然而,在处理请求时,很容易出现错误。本文将介绍一些在Go语言中处理路由错误的技巧,并...
    99+
    2023-12-18
    Go语言 路由 错误处理
  • Golang异常控制处理程序错误流程
    目录panic和recover使用使用示例注意子函数panic主函数recover子协程panic主函数recover使用总结使用panic的几点担心性能性能对比安全panic和re...
    99+
    2023-05-17
    Golang异常处理机制 Golang错误处理 Golang panic和recover使用
  • PHP中的错误处理机制是什么?
    PHP是一种流行而强大的服务器端编程语言,可以用来开发各种Web应用程序。就像其他编程语言一样,PHP也有可能会出现错误和异常。这些错误和异常可能由各种原因引起,如程序错误、服务器错误、用户输入错误等等。为了确保程序的运行稳定性和可靠性,P...
    99+
    2023-05-14
    PHP错误处理 异常处理 错误日志记录
  • node.js express和koa中间件机制和错误处理机制
    目录一、前言二、中间件问题解析三、错误逻辑捕获3.1 express的错误捕获逻辑3.2 同步逻辑错误获取的底层逻辑3.3 异步逻辑错误获取的底层逻辑3.4 koa的错误获取逻辑一、...
    99+
    2022-11-13
  • php异常和错误处理机制
    文章目录 基本概念标准异常处理自定义异常处理 异常处理最佳使用场景控制异常代码影响范围保证数据统一性 错误处理错误等级定义标准错误处理自主处理非致命错误自主处理致命错误抛出自定义错误 ...
    99+
    2023-09-13
    php
  • springmvc错误处理机制是什么
    这篇“springmvc错误处理机制是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“springmvc错误处理机制是什么...
    99+
    2023-06-17
  • Golang中怎么优雅地处理错误
    本文小编为大家详细介绍“Golang中怎么优雅地处理错误”,内容详细,步骤清晰,细节处理妥当,希望这篇“Golang中怎么优雅地处理错误”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、错误分类在 Golang ...
    99+
    2023-07-05
  • Golang中怎么对错误进行处理
    这期内容当中小编将会给大家带来有关Golang中怎么对错误进行处理,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。首先介绍几种常见的创建错误的方法基于字符串的错误err1&...
    99+
    2022-10-19
  • Golang中的错误处理深入分析
    目录一、Go的内建类型error二、怎么判断一个错误值具体代表那一类错误知道错误类型的所属范围知道错误变量是哪几个值三、错误值体系的两种方法立体的-错误类型体系扁平的-错误值列表一、...
    99+
    2023-01-09
    Go错误处理 GoLang错误处理
  • 理解ASP.NET Core 错误处理机制(Handle Errors)
    目录使用中间件进行错误处理开发人员异常页IDeveloperPageExceptionFilter异常处理程序通过lambda提供异常处理程序异常处理程序页无响应正文的Http错误状...
    99+
    2022-11-12
  • Go错误处理机制实例分析
    这篇文章主要讲解了“Go错误处理机制实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Go错误处理机制实例分析”吧!Go 错误处理机制Go 内置 errorsGo 语言中的 e...
    99+
    2023-07-02
  • Node.js的错误处理机制是什么
    本篇内容介绍了“Node.js的错误处理机制是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Node.js 是一个基于 Chrome V...
    99+
    2023-07-05
  • Go语言的错误处理方法有哪些
    这篇文章主要介绍了Go语言的错误处理方法有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Go语言的错误处理方法有哪些文章都会有所收获,下面我们一起来看看吧。与其他语言的快速比较在 Go 中,所有的错误都是值...
    99+
    2023-06-17
  • go语言规范RESTful API业务错误处理
    目录错误码为什么需要业务错误码错误码功能错误码设计错误码调研业务错误码错误格式错误码实现错误包错误包功能错误包设计错误码及错误包的使用使用示例使用建议使用尽量少的 HTTP 状态码使...
    99+
    2023-03-08
    go RESTful API错误处理 go RESTful API
  • go语言错误处理的方法有哪些
    Go语言中的错误处理方法有以下几种:1. 返回错误值:函数可以返回一个额外的错误值,通常是一个error类型的值,用于表示函数执行过...
    99+
    2023-08-15
    go语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作