# 18 错误处理

错误处理基本用法：

```go
package main

import (
	"fmt"
	"math"
)

func sqrt(n float64) (float64, error) {
	if n < 0 {
		return 0, fmt.Errorf("invalid argument '%f', must be >= 0", n)
	}
	return math.Sqrt(n), nil
}

func printSqrt(n float64) {
	if res, err := sqrt(n); err == nil {
		fmt.Printf("sqrt of %f is %f\n", n, res)
	} else {
		fmt.Printf("sqrt of %f returned error '%s'\n", n, err)
	}

}

func main() {
	printSqrt(16)
	printSqrt(-16)
}

// 输出结果
// sqrt of 16.000000 is 4.000000
// sqrt of -16.000000 returned error 'invalid argument '-16.000000', must be >= 0'
```

跟C#和Python不同，Go的错误处理是直接返回错误值，而不是抛出异常。

Go也提供了[恐慌和恢复](/essential-go/20-panic-and-recover.md)的异常机制，但它们应该被尽量少用。

错误也是值，就像整数或字符串一样。

`error`类型是一个内置(built-in)接口类型，该接口规定了`Error() string`方法。

如果要表示执行成功，则把表示错误的变量置为`nil`返回。

若要表示执行失败，则把错误变量赋值为`errors.New(msg string)`或`fmt.Errorf(format string, args... interface{})`返回的值。

您也可以通过自定义一个结构体并实现`Error() string`方法来[自定义错误类型](/essential-go/18-error-handling/custom-error-types.md)。

如果一个函数要返回错误，那么错误值应当总是最后一个。

应始终检查函数的返回值中是否包含错误。编写鲁棒性强的软件的关键就是检查错误并进行适当处理。初学者通常放弃检查错误，然后面临调试神秘故障的麻烦。

## 译者注：`error`源码解读

```go
// error接口的定义
// src/builtin/builtin.go
type error interface {
	Error() string
}

// error的实现
// src/errors/errors.go

// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
	return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
	s string
}

func (e *errorString) Error() string {
	return e.s
}
```

就这么多，没了。是不是简单到爆。`error`仅仅是一种普通的`interface`类型，包含一个返回类型为字符串的`Error()`函数。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://denglj.gitbook.io/essential-go/18-error-handling.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
