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 函数时,发送错误的字符串描述,虽然这可能看起来像错误处理,但实际上并不是。让我们接着看下去吧。

相关文章
|
12月前
|
Linux Go iOS开发
Go语言100个实战案例-进阶与部署篇:使用Go打包生成可执行文件
本文详解Go语言打包与跨平台编译技巧,涵盖`go build`命令、多平台构建、二进制优化及资源嵌入(embed),助你将项目编译为无依赖的独立可执行文件,轻松实现高效分发与部署。
1696 162
|
11月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
723 4
|
11月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟蒋星熠Jaxonic,Go语言探索者。深耕云计算、微服务与并发编程,以代码为笔,在二进制星河中书写极客诗篇。分享Go核心原理、性能优化与实战架构,助力开发者掌握云原生时代利器。#Go语言 #并发编程 #性能优化
742 43
Go语言深度解析:从入门到精通的完整指南
|
JSON 中间件 Go
Go语言实战指南 —— Go中的反射机制:reflect 包使用
Go语言中的反射机制通过`reflect`包实现,允许程序在运行时动态检查变量类型、获取或设置值、调用方法等。它适用于初中级开发者深入理解Go的动态能力,帮助构建通用工具、中间件和ORM系统等。
817 63
|
12月前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟 蒋星熠Jaxonic,执着的星际旅人,用Go语言编写代码诗篇。🚀 Go语言以简洁、高效、并发为核心,助力云计算与微服务革新。📚 本文详解Go语法、并发模型、性能优化与实战案例,助你掌握现代编程精髓。🌌 从goroutine到channel,从内存优化到高并发架构,全面解析Go的强大力量。🔧 实战构建高性能Web服务,展现Go在云原生时代的无限可能。✨ 附技术对比、最佳实践与生态全景,带你踏上Go语言的星辰征途。#Go语言 #并发编程 #云原生 #性能优化
|
测试技术 程序员 Go
Go语言测试简明指南:深度解读go test命令
总的来说,go test是 Go 语言中一个强而有力的工具,每个 Go 程序员都应该掌握并把它融入到日常的开发和调试过程中。就像是一个眼镜过滤出的太阳,让我们在宽阔的代码海洋中游泳,而不是淹没。用好它,让我们的代码更健壮,让我们的生产力更强效。
868 23
|
数据可视化 测试技术 Go
Go 语言测试与调试:`go test` 工具用法
`go test` 是 Go 语言内置的测试工具,支持单元测试、基准测试、示例测试等功能。本文详解其常用参数、调试技巧及性能测试命令,并提供实际项目中的应用示例与最佳实践。
|
存储 缓存 安全
Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
`sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
599 1
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。

热门文章

最新文章