Go 语言入门很简单:Go 语言的错误处理(上)

简介: 文将介绍 Go 中的错误处理,以及为什么我们需要错误处理。

什么是错误处理

异常处理是任何语言都不能绕不开的话题。Go 语言没有提供传统的 try...catch 语句来处理异常,而是通过使用 error 来处理错误,用 panicrecover 来处理异常。


错误封装是将一个错误包裹到另一个错误的过程。假设我们有一个访问数据库的 Web 服务器,并试图从数据库中获取一条记录。如果数据库调用返回一个错误,我们可以决定是捕获这个错误还是从网络服务中发送我们自己的自定义错误。

基础 error

error 接口


error 是一种内建的接口类型,内建意味着不需要 import 任何包就可以直接使用,使用起来就像基础类型一样自然。

type error interface {
    Error() string
}


error 接口只声明了一个 Error() 方法,任何实现了该方法的结构体都可以作为 error 来使用。


  • error 的实例代表一种异常状态
  • Error() 方法用于描述该异常状态
  • 值为 nil 的 error 代表没有异常


标准库 errors 包中的 errorString 就是实现 error 接口的一个例子:

type errorString struct {
    s string
}
func (e *errorString) Error() string {
    return.s
}


创建 error


标准库提供了两种 error 的方法:


  • errors.New()
  • fmt.Errorf()


  1. error.New()  的实现极其简单,只是简单地构造一个 errorString 实例便返回:
package errors
func New(text string) error {
    return &errorString{text}
}


  1. fmt.Errorf()


error.New() 单调地接收一个字符串参数来构造 error,而实际场景中往往需要使用 fmt.Sprintf()  生成字符串,这时可以直接使用 fmt.Errorf()

package fmt
func Errorf(format string, a ...interface{}) error {
    return errors.New(Sprintf(format,  a...))


联系与区别: fmt.Errorf() 只是对 error.New() 的简单封装,使用前者可以使得代码更加简洁。而两者的区别在于 fmt.Errorf() 适用于需要格式化输出错误字符串的场景,如果不需要格式化字符串,则建议使用  error.New()

异常处理

针对 error 而言,异常处理包括如何检查错误,如何传递错误。


  1. 检查 error


最常见的检查 error 的方式是与 nil 值进行比较:

if err != nil {
    // 错误处理逻辑
}


与预定义的 error 进行比较(可以是自定义也可以是标准库中的,比如 os 库中的常见错误):

var noRows = errors.New("no rows found")
if err == noRows {
}


  1. 传递 error


在一个函数中收到一个 error,往往需要附加一些上下文信息再把 error 继续向上层抛


可以看一下如下的例子:

package main
import (
  "errors"
  "fmt"
)
var noRows = errors.New("no rows found")
func getRecords() error {
  return noRows
}
func webService() error {
  if err := getRecords(); err != nil {
    return fmt.Errorf("Error %s when calling DB", err)
  }
  return nil
}
func main() {
  if err := webService(); err != nil {
    fmt.Printf("Error: %s when calling webService\n", err)
    return
  }
  fmt.Println("webService call successful")
}


运行结果:

$ go run .
Error: Error no rows found when calling DB when calling webService


在上面的程序中,我们在调用 getRecords 函数时,发送错误的字符串描述,虽然这可能看起来像错误处理,但实际上并不是。让我们接着看下去吧。

相关文章
|
3天前
|
安全 网络协议 Go
Go语言网络编程
【10月更文挑战第28天】Go语言网络编程
89 65
|
3天前
|
网络协议 安全 Go
Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
【10月更文挑战第28天】Go语言进行网络编程可以通过**使用TCP/IP协议栈、并发模型、HTTP协议等**方式
23 13
|
3天前
|
网络协议 安全 Go
Go语言的网络编程基础
【10月更文挑战第28天】Go语言的网络编程基础
17 8
|
2天前
|
Go
go语言的复数常量
【10月更文挑战第21天】
13 6
|
2天前
|
Go
go语言的浮点型常量
【10月更文挑战第21天】
9 4
|
2天前
|
编译器 Go
go语言的整型常量
【10月更文挑战第21天】
8 3
|
3天前
|
Go
go语言编译时常量表达式
【10月更文挑战第20天】
11 3
|
2天前
|
Serverless Go
Go语言中的并发编程:从入门到精通
本文将深入探讨Go语言中并发编程的核心概念和实践,包括goroutine、channel以及sync包等。通过实例演示如何利用这些工具实现高效的并发处理,同时避免常见的陷阱和错误。
|
3天前
|
安全 Go 开发者
代码之美:Go语言并发编程的优雅实现与案例分析
【10月更文挑战第28天】Go语言自2009年发布以来,凭借简洁的语法、高效的性能和原生的并发支持,赢得了众多开发者的青睐。本文通过两个案例,分别展示了如何使用goroutine和channel实现并发下载网页和构建并发Web服务器,深入探讨了Go语言并发编程的优雅实现。
10 2
|
3天前
|
Go
go语言常量的类型
【10月更文挑战第20天】
9 2