Skip to content

老陈是一个普通的文艺二逼青年

For The Dream

Golang 入门(五) —— 错误处理

Written by chen

1、error接口

Go语言引入了一个关于错误处理的标准模式,即error接口,该接口的定义如下:

1
2
3
4
type error interface {
    Error() string
}
 

对于大多数函数,如果需要返回错误,大致可以定义如下模式,将error作为多返回值中的最后一个即可,但是这并非是强制要求:

1
2
3
4
func Foo(i int) (n int, err error) {
    // ...
}
 

需要时,可以如下调用:

1
2
n, err := Foo(0)
 

下面使用Go库中的实际代码来示范如何自定义error类型。

1
2
3
4
5
6
7
8
9
10
type PathError struct {
    Op   string
    Path string
    Err  error
}
 
func (e *PathError) Error() string {
    return e.Op + " " + e.Path + " " + e.Err.Error()
}
 

调用可以如下:

1
2
3
4
5
6
    err = syscall.Stat(name, &stat)
 
    if err != nil {
        return nil, &PathError{"stat", name, err}
    }
 

2、defer

关键字defer允许我们推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数(为什么要在返回之后才执行这些语句?因为 return 语句同样可以包含一些操作,而不是单纯地返回某个值)。

关键字 defer 的用法类似于面向对象编程语言 Java 和 C# 的 finally 语句块,它一般用于释放某些已分配的资源。

下面的例子可以简单的解释defer的用法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func CopyFile(dst, src string) (w int64, err error) {
    srcFile, err := os.Open(src)
    if err != nil {
        return
    }
 
    defer srcFile.Close()
 
    dstFile, err := os.Create(dst)
    if err != nil {
        return
    }
 
    defer dstFile.Close()
 
    return io.Copy(dstFile, srcFile)
}
 

如果一句话干不完清理的工作,可以使用在defer后加一个匿名函数的做法:

1
2
3
4
    defer func() {
        // ...
    }()
 

另外,一个函数里可以存在多个defer,因此需要注意的是,defer语句遵循先进后出的原则,即最后一个defer第一个执行,第一个defer最后一个执行。

3、panic和recover

Go语言引入了两个内置函数panic()和recover(),用以报告和处理运行时错误和程序中的错误场景:

1
2
3
func panic(interface{})
func recover() interface{}
 

使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<br />func main() {
    fmt.Println("a")
    a()
    fmt.Println("b")
}
 
func a() {
    fmt.Println(1)
    fmt.Println(2)
    b()
    fmt.Println(3)
 
}
 
func b() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println(r)
        }
    }()
    fmt.Println("11")
    panic("Error")
    fmt.Println("12")
}
 

Go语言编程 · golang

Copyright © 2022 老陈是一个普通的文艺二逼青年. 沪ICP备13044041号-1