跳到主要内容

Go 错误处理

提示
  1. 错误生成与处理: 在Go中,程序错误(例如整数除以零)会停止程序执行,因此需要有效的错误处理。
  2. 使用New()Errorf()函数处理错误: New()用于创建自定义错误消息,而Errorf()允许格式化错误消息。
  3. 自定义错误类型: 通过在结构体上实现error接口的Error()方法,可以创建自定义错误类型,提供更具体的错误信息。

在编程中,我们的程序有时会运行不正常并产生错误。例如,

package main
import "fmt"

func main() {

for i := 0; i < 5; i++ {
result := 20 / i
fmt.Println(result)
}
}

运行这段代码时,我们会遇到一个叫做整数除以零的错误。

在第一次迭代中,i 的值为 0,因此代码 result := 20 / i 尝试用 0 去除一个数。

在这种状态下,程序停止执行,这就是所谓的Go错误。这里的 "integer divide by zero" 是编译器返回的错误信息。

注意: 我们在前一个例子中遇到的错误是内置错误。在 Go 语言中,我们也可以自己创建错误,以实现更高效的编程。

Golang 错误处理

当发生错误时,程序的执行会完全停止,并显示内置错误消息。在 Go 中,我们可以处理这些异常。因此,处理程序中的异常非常重要。

与其他编程语言不同,我们在 Go 中不使用 try/catch 来处理错误。我们可以使用以下方法来处理错误:

  • New() 函数
  • Errof() 函数

1. 使用 New() 函数处理 Go 错误

在 Go 中,我们可以使用 New() 函数来处理错误。这个函数定义在 errors 包内,允许我们创建自己的错误信息。

看一个例子,

package main

// 导入 errors 包
import (
"errors"
"fmt"
)

func main() {

message := "Hello"

// 使用 New() 函数创建错误
myError := errors.New("WRONG MESSAGE")

if message != "Programiz" {
fmt.Println(myError)
}

}

输出

WRONG MESSAGE

在上面的例子中,我们使用 errors.New() 函数创建了一个错误。

myError := errors.New("WRONG MESSAGE")

这里,New() 函数内的 "WRONG MESSAGE" 是自定义错误信息。当 message 变量与给定的字符串 "PROGRAMIZ" 不匹配时,它会被打印出来。

示例:使用 New() 函数处理错误

package main

// 导入 errors 包
import (
"errors"
"fmt"
)

// 检查名字是否为 Programiz 的函数
func checkName(name string) error {

// 创建一个新错误
newError := errors.New("Invalid Name")

// 如果名字不是 Programiz,则返回错误
if name != "Programiz" {
return newError
}

// 如果没有错误,则返回 nil
return nil
}

func main() {

name := "Hello"

// 调用函数
err := checkName(name)

// 检查 err 是否为 nil
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Valid Name")
}

}

输出

Invalid Name

在上面的例子中,我们创建了一个名为 checkName() 的函数

checkName(name string) error {...}

这个函数的返回值是一个 error,意味着这个函数将返回一个错误类型的值

在函数内部,我们使用 New() 函数创建了一个错误。这里,如果名字不是 Programiz,我们返回新创建的错误消息。

然而,如果名字是 Programiz,我们返回 nil(表示没有错误)。

main() 函数中,我们使用

err := checkName(name)

调用了 checkName() 函数。这里,返回的错误将被赋值给 err。然后我们检查 err 中的值是否为 nil。

2. 在 Golang 中使用 Errorf() 处理错误

我们还可以使用 Errorf() 函数来处理 Go 错误。与 New() 不同,我们可以使用 Errorf() 格式化错误消息。

这个函数位于 fmt 包中,所以如果我们已经导入了 `

fmt` 包,就可以直接使用它。

看一个例子。

package main
import "fmt"

func main() {

age := -14

// 使用 Errorf() 创建错误
error := fmt.Errorf("%d is negative\nAge can't be negative", age)

if age < 0 {
fmt.Println(error)
} else {
fmt.Println("Age: %d", age);
}
}

输出

-14 is negative
Age can't be negative

在上面的例子中,我们使用了 Errorf() 函数来创建一个新的格式化错误。

error := fmt.Errorf("%d is negative\nAge can't be negative", age)

在这里,你可以看到我们使用了格式化符号 %d 来在错误信息中使用 age 的值。

示例:使用 Errorf() 处理错误

package main
import "fmt"

func divide(num1, num2 int) error {

// 如果 num2 为 0,则返回错误
if num2 == 0 {
return fmt.Errorf("%d / %d\nCannot Divide a Number by zero", num1, num2)
}

// 返回除法的结果
return nil
}

func main() {

err := divide(4,0)

// 发现错误
if err != nil {
fmt.Printf("error: %s", err)

// 未发现错误
} else {
fmt.Println("Valid Division")
}
}

输出

error: 4 / 0
Cannot Divide a Number by zero

在上面的例子中,我们创建了一个名为 divide() 的函数。

func divide(num1, num2 int) error {...}

这个函数的返回类型是 error,意味着这个函数将返回一个错误值。

在函数内部,我们使用 Errorf() 创建了一个格式化错误。如果条件 num2==0 成立,那么函数 divide 返回 Errorf() 中的错误信息。

然而,如果 num2 不是 0,我们返回 nil,表示没有错误。

Golang 中的自定义错误

在 Go 中,我们可以通过在结构体上实现 error 接口来创建自定义错误。

error 接口

type error interface {
Error() string
}

这里,如果存在错误,Error() 方法会以字符串形式返回错误信息。否则,它返回 nil

现在,要创建一个自定义错误,我们必须在 Go 结构体 上实现 Error() 方法。

看一个例子,

package main

import "fmt"

type DivisionByZero struct {
message string
}

// 在结构体上定义 Error() 方法
func (z DivisionByZero) Error() string {
return "Number Cannot Be Divided by Zero"
}

func divide(n1 int, n2 int) (int, error) {

if n2 == 0 {
return 0, &DivisionByZero{}
} else {
return n1 / n2, nil
}
}

func main() {

number1 := 15
// 改变 number2 的值以得到不同的结果
number2 := 0

result, err := divide(number1, number2)

// 检查是否发生错误
if err != nil {
fmt.Println(err)
} else {
fmt.Printf("Result: %d", result)
}
}

输出

Number Cannot Be Divided by Zero

在上面的例子中,我们在 DivisionByZero 结构体上实现了 error 接口的 Error() 方法。

func (z DivisionByZero) Error() string {
return "Number Cannot Be Divided by Zero"
}

这里,

  • z DivisionByZero - DivisionByZero 结构体的一个实例
  • string - 方法的返回类型
  • "Number Cannot Be Divided by Zero" - 错误信息

然后,我们创建了一个 divide() 方法,它接收两个参数并返回结果和一个 error

func divide(n1 int, n2 int) (int, error) {...}

如果 n2 的值为 0,函数返回 0&DivisionByZero{}。这里,&DivisionByZero{} 是该结构体的一个实例。要了解更多,请访问 Go 指针和结构体

main() 函数内部,如果返回的错误类型不是 nil,我们就打印出错误信息。

请注意,我们在程序中任何地方都没有调用 Error() 方法,但我们可以使用结构体实例访问它的返回值。