Notes
Go
异常处理

异常处理

异常是指程序在执行过程中发生的错误,会导臹程序终止。Go 语言提供了一种机制来处理运行时错误,这种机制被称为异常处理。

创建异常

Go 内置了一个 error 类型,用于表示异常。error 类型是一个接口类型,定义如下:

type error interface {
    Error() string  // Error 方法,返回异常信息
}

使用 errors 包的 New 函数可以创建一个异常:

package main
 
import (
    "errors"
    "fmt"
)
 
func main() {
    err := errors.New("this is an error")
    fmt.Println(err)
}

抛出异常

Go 语言没有提供 throw 关键字来抛出异常,而是使用 panic 函数来抛出异常。panic 函数接收一个任意类型的参数,通常是一个字符串,用于描述异常信息。

func handleError() {
    panic(errors.New("this is an error"))
}
 
func main() {
 
    fmt.Println("start")
 
    handleError()
 
    fmt.Println("end")
}

输出结果:

start
panic: this is an error

goroutine 1 [running]:
main.handleError()
        /Users/jetzihan/Code/go/src/github.com/jetzihan/go-note/note/golang/error.go:8 +0x3b
main.main()
          /Users/jetzihan/Code/go/src/github.com/jetzihan/go-note/note/golang/error.go:13 +0x2d
exit status 2

自定义异常

Panic 函数允许用户自定义异常。

func panic(v any)

即 panic 函数接收任意类型的参数,可以是任意类型的值。

package main
 
import (
    "fmt"
)
 
func main() {
    panic("this is an error")
}

倘若想要携带错误码等更多的信息,可以使用结构体。

package main
 
import (
    "fmt"
)
 
type MyError struct {
    Code int
    Msg  string
}
 
func handleError() {
    e := MyError{Code: 100, Msg: "this is an error"}
 
    panic(e)
}
 
func main() {
 
    fmt.Println("start")
 
    handleError()
 
    fmt.Println("end")
}

输出结果:

start

panic: (*main.MyError) 0xc0000b2000

goroutine 1 [running]:
main.handleError()
        /Users/jetzihan/Code/go/src/github.com/jetzihan/go-note/note/golang/error.go:10 +0x3b
main.main()
          /Users/jetzihan/Code/go/src/github.com/jetzihan/go-note/note/golang/error.go:15 +0x2d
exit status 2

可以看到,输出的异常信息是 (*main.MyError) 0xc0000b2000,这是因为 panic 函数只能接收字符串类型的参数,没有按照我们希望的方式输出异常信息。我们可以实现 error 接口来自定义异常。

package main
 
import (
    "fmt"
)
 
type MyError struct {
    Code int
    Msg  string
}
 
func (e MyError) Error() string {
    return fmt.Sprintf("Code: %d, Msg: %s", e.Code, e.Msg)
}
 
func handleError() {
    e := MyError{Code: 100, Msg: "this is an error"}
 
    panic(e)
}
 
func main() {
 
    fmt.Println("start")
 
    handleError()
 
    fmt.Println("end")
}

输出结果:

start

panic: Code: 100, Msg: this is an error

goroutine 1 [running]:
main.handleError()
        /Users/jetzihan/Code/go/src/github.com/jetzihan/go-note/note/golang/error.go:10 +0x3b
main.main()
          /Users/jetzihan/Code/go/src/github.com/jetzihan/go-note/note/golang/error.go:20 +0x2d
exit status 2

捕获异常

Go 语言提供了 recover 函数来捕获异常。recover 函数只能在 defer 函数中调用,用于捕获异常。

func recover() any

recover 函数返回一个 interface{} 类型的值,表示捕获的异常信息。如果没有异常被抛出,recover 函数返回 nil。正确的做法是在 defer 函数中调用 recover 函数,然后判断返回值是否为 nil,如果不为 nil,则表示捕获到了异常。

package main
 
import (
    "fmt"
)
 
func handleError() {
    panic("this is an error")
}
 
func main() {
 
    fmt.Println("start")
 
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("recover:", err)
        }
    }()
 
    handleError()
 
    fmt.Println("end")
}