返回并处理错误

处理错误是健壮代码的基本特征。在本节中,您将向greetings模块添加一些代码以返回错误,然后在调用方中处理它。

  1. 在greetings/greetings.go中,添加下方突出显示的代码。

    如果不知道向谁问好,返回问候语就毫无意义。如果名称为空,则向调用方返回错误。将以下代码复制到greetings.go中并保存文件。

    package greetings
    
    import (
        "errors"
        "fmt"
    )
    
    // Hello 返回对指定人员的问候语。
    func Hello(name string) (string, error) {
        // 如果未提供名称,则返回带有消息的错误。
        if name == "" {
            return "", errors.New("empty name")
        }
    
        // 如果收到了名称,则返回一个将名称嵌入问候消息的值。
        message := fmt.Sprintf("Hi, %v. Welcome!", name)
        return message, nil
    }
    

    在此代码中,您:

    • 更改了函数,使其返回两个值:一个string和一个error。您的调用方将检查第二个值以查看是否发生了错误。(任何Go函数都可以返回多个值。更多信息,请参阅Effective Go。)
    • 导入Go标准库的errors包,以便使用其errors.New函数
    • 添加了一个if语句来检查无效请求(在应该是名称的地方为空字符串),并在请求无效时返回错误。errors.New函数返回一个内部包含您的消息的error
    • 在成功的返回值中添加了nil(表示无错误)作为第二个值。这样,调用方就可以看到函数已成功执行。
  2. 在您的hello/hello.go文件中,现在处理Hello函数返回的错误以及非错误值。

    将以下代码粘贴到hello.go中。

    package main
    
    import (
        "fmt"
        "log"
    
        "example.com/greetings"
    )
    
    func main() {
        // 设置预定义Logger的属性,包括日志条目前缀和一个标志以禁用打印时间、源文件和行号。
        log.SetPrefix("greetings: ")
        log.SetFlags(0)
    
        // 请求一条问候消息。
        message, err := greetings.Hello("")
        // 如果返回了错误,则将其打印到控制台并退出程序。
        if err != nil {
            log.Fatal(err)
        }
    
        // 如果没有返回错误,则将返回的消息打印到控制台。
        fmt.Println(message)
    }
    

    在此代码中,您:

    • 配置了log,使其在日志消息开头打印命令名称("greetings: "),而不带时间戳或源文件信息。
    • Hello的两个返回值(包括error)都赋给了变量。
    • Hello的参数从Gladys的名字更改为空字符串,以便您可以测试错误处理代码。
    • 查找一个非nil的error值。在这种情况下继续执行没有意义。
    • 使用标准库log包中的函数来输出错误信息。如果遇到错误,您使用log包的Fatal函数来打印错误并停止程序。
  3. hello目录的命令行中,运行hello.go以确认代码有效。

    现在您传入了一个空名称,您将收到一个错误。

    $ go run .
    greetings: empty name
    exit status 1
    

这是Go中常见的错误处理方式:将错误作为值返回,以便调用方可以检查它。

接下来,您将使用Go切片来返回一个随机选择的问候语。