golang教程之错误处理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wyy626562203/article/details/83411504

错误处理

原文:https://golangbot.com/error-handling/

在这里插入图片描述

什么是错误?

错误表示程序中的异常情况。 假设我们正在尝试打开文件,文件系统中不存在该文件。 这是一种异常情况,它表示为错误。

Go中的错误是普通的旧值。 使用内置错误类型表示错误。

就像任何其他内置类型,如int,float64,…错误值可以存储在变量中,从函数返回等等。

例子

让我们立即开始尝试打开一个不存在的文件的示例程序。

package main

import (  
    "fmt"
    "os"
)

func main() {  
    f, err := os.Open("/test.txt")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(f.Name(), "opened successfully")
}

在上面的程序第9行中,我们试图在路径/test.txt(在playground上显然不存在)中打开文件。 os包的Open函数具有以下签名,

func Open(name string) (file *File, err error)

如果文件已成功打开,则Open函数将返回文件处理程序,错误将为nil。 如果打开文件时出错,将返回非零错误。

如果函数或方法返回错误,那么按照惯例,它必须是函数返回的最后一个值。 因此,Open函数返回err作为最后一个值。

在Go中处理错误的惯用方法是将返回的错误与nil进行比较。 nil值表示没有发生错误,非nil值表示存在错误。 在我们的例子中,我们检查错误是否存在,我们只需打印错误并从main函数返回。

运行此程序将打印

open /test.txt: No such file or directory  

完美。我们收到一条错误消息,指出该文件不存在。

错误类型表示

让我们深入一点,看看如何定义内置错误类型。 error是具有以下定义的接口类型,

type error interface {  
    Error() string
}

它包含一个带有签名Error() string的方法。 实现此接口的任何类型都可以用作错误。 此方法提供错误的描述。

打印错误时,fmt.Println函数在内部调用Error() string方法以获取错误的描述。 这是错误描述在第11行号中打印的方式。

从错误中提取更多信息的不同方法

现在我们知道错误是一种接口类型,让我们看看如何提取有关错误的更多信息。

在上面我们看到的例子中,我们刚刚打印了错误的描述。 如果我们想要导致错误的文件的实际路径,该怎么办? 一种可能的方法是解析错误字符串。 这是我们程序的输出,

open /test.txt: No such file or directory  

我们可以解析此错误消息并获取导致错误的文件的文件路径“/test.txt”,但这是一种糟糕的方式。 错误描述可以随时在较新版本的语言中更改,我们的代码将会中断。

有没有办法可靠地获取文件名? 答案是肯定的,它可以完成,标准的Go库使用不同的方式来提供有关错误的更多信息。 让我们逐一看看它们。

1.断言底层结构类型并从结构域中获取更多信息

如果仔细阅读Open函数的文档,可以看到它返回类型为* PathError的错误。 PathError是一种结构类型,它在标准库中的实现如下,

type PathError struct {  
    Op   string
    Path string
    Err  error
}

func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }  

如果您有兴趣知道上述源代码的存在位置,可以在此处找到https://golang.org/src/os/error.go?s=653:716#L11

从上面的代码中,您可以理解* PathError通过声明Error() string 方法来实现 error interface。 此方法连接操作,路径和实际错误并返回它。 因此我们收到了错误消息,

open /test.txt: No such file or directory  

PathError结构的Path字段包含导致错误的文件的路径。 让我们修改上面编写的程序并打印路径。

package main

import (  
    "fmt"
    "os"
)

func main() {  
    f, err := os.Open("/test.txt")
    if err, ok := err.(*os.PathError); ok {
        fmt.Println("File at path", err.Path, "failed to open")
        return
    }
    fmt.Println(f.Name(), "opened successfully")
}

在上面的程序中,我们在第10行中使用类型断言,获取错误接口的基础值。 然后我们使用第11行中的err.Path打印路径。该程序输出,

File at path /test.txt failed to open  

太棒了。 我们已成功使用类型断言从错误中获取文件路径。

2.断言底层结构类型并使用方法获取更多信息

获取更多信息的第二种方法是断言底层类型,并通过调用struct类型的方法获取更多信息。

让我们通过一个例子更好地理解这一点。

标准库中的DNSError结构类型定义如下,

type DNSError struct {  
    ...
}

func (e *DNSError) Error() string {  
    ...
}
func (e *DNSError) Timeout() bool {  
    ... 
}
func (e *DNSError) Temporary() bool {  
    ... 
}

从上面的代码中可以看出,DNSError结构有两个方法Timeout()boolTemporary()bool,它们返回一个布尔值,指示错误是由于超时还是临时错误。

让我们编写一个断言* DNSError类型的程序,并调用这些方法来确定错误是暂时的还是由于超时。

package main

import (  
    "fmt"
    "net"
)

func main() {  
    addr, err := net.LookupHost("golangbot123.com")
    if err, ok := err.(*net.DNSError); ok {
        if err.Timeout() {
            fmt.Println("operation timed out")
        } else if err.Temporary() {
            fmt.Println("temporary error")
        } else {
            fmt.Println("generic error: ", err)
        }
        return
    }
    fmt.Println(addr)
}

注意:DNS查找在playground上不起作用。 请在本地计算机上运行此程序。

在上面的程序中,我们试图在第9行中获取无效域名golangbot123.com的IP地址。 我们通过断言它来键入* net.DNSError来获取错误的基础值。 然后我们检查错误是由于超时还是临时的行号。

在我们的例子中,错误既不是暂时的也不是由于超时,因此程序将打印,

generic error:  lookup golangbot123.com: no such host  

如果错误是临时的或由于超时,则相应的if语句将被执行,我们可以适当地处理它。

3.直接比较

获取有关错误的更多详细信息的第三种方法是直接与类型错误的变量进行比较。 让我们通过一个例子来理解这一点。

filepath包的Glob函数用于返回与模式匹配的所有文件的名称。 模式格式错误时,此函数返回错误ErrBadPattern

ErrBadPatternfilepath包中定义如下。

var ErrBadPattern = errors.New("syntax error in pattern")  

errors.New()用于创建新错误。 我们将在下一个教程中详细讨论这个问题。

当模式格式错误时,Glob函数返回ErrBadPattern

让我们编写一个小程序来检查这个错误。

package main

import (  
    "fmt"
    "path/filepath"
)

func main() {  
    files, error := filepath.Glob("[")
    if error != nil && error == filepath.ErrBadPattern {
        fmt.Println(error)
        return
    }
    fmt.Println("matched files", files)
}

在上面的程序中,我们搜索模式的文件[这是一个格式错误的模式。 我们检查错误是否为零。 要获得有关错误的更多信息,我们直接将它与filepath.ErrBadPattern进行比较。如果满足条件,则错误是由于格式错误造成的。 这个程序将打印,

syntax error in pattern  

标准库使用上述任何方法提供有关错误的更多信息。 我们将在下一个教程中使用这些方法来创建自己的自定义错误。

猜你喜欢

转载自blog.csdn.net/wyy626562203/article/details/83411504