|
|
@@ -3,10 +3,9 @@
|
|
|
Go 有一个预先定义的 error 接口类型
|
|
|
|
|
|
```go
|
|
|
-type error interface {
|
|
|
+type error interface {
|
|
|
Error() string
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
错误值用来表示异常状态;我们可以在 [5.2 节](05.2.md)中看到它的标准用法。处理文件操作的例子可以在 12 章找到;我们将在 15 章看到网络操作的例子。errors 包中有一个 errorString 结构体实现了 error 接口。当程序处于错误状态时可以用 `os.Exit(1)` 来中止运行。
|
|
|
@@ -17,7 +16,6 @@ type error interface {
|
|
|
|
|
|
```go
|
|
|
err := errors.New(“math - square root of negative number”)
|
|
|
-
|
|
|
```
|
|
|
|
|
|
在示例 13.1 中你可以看到一个简单的用例:
|
|
|
@@ -39,7 +37,6 @@ func main() {
|
|
|
fmt.Printf("error: %v", errNotFound)
|
|
|
}
|
|
|
// error: Not found error
|
|
|
-
|
|
|
```
|
|
|
|
|
|
可以把它用于计算平方根函数的参数测试:
|
|
|
@@ -51,7 +48,6 @@ func Sqrt(f float64) (float64, error) {
|
|
|
}
|
|
|
// implementation of Sqrt
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
你可以像下面这样调用 Sqrt 函数:
|
|
|
@@ -60,7 +56,6 @@ func Sqrt(f float64) (float64, error) {
|
|
|
if f, err := Sqrt(-1); err != nil {
|
|
|
fmt.Printf(“Error: %s\n”, err)
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
由于 `fmt.Printf` 会自动调用 `String()` 方法 (参见 [10.7 节](10.7.md)),所以错误信息 “Error: math - square root of negative number” 会打印出来。通常(错误信息)都会有像 “Error:” 这样的前缀,所以你的错误信息不要以大写字母开头。
|
|
|
@@ -78,17 +73,15 @@ type PathError struct {
|
|
|
func (e *PathError) String() string {
|
|
|
return e.Op + “ ” + e.Path + “: “+ e.Err.Error()
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
如果有不同错误条件可能发生,那么对实际的错误使用类型断言或类型判断(type-switch)是很有用的,并且可以根据错误场景做一些补救和恢复操作。
|
|
|
|
|
|
-```go
|
|
|
+```go
|
|
|
// err != nil
|
|
|
if e, ok := err.(*os.PathError); ok {
|
|
|
// remedy situation
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
或:
|
|
|
@@ -99,11 +92,10 @@ switch err := err.(type) {
|
|
|
PrintParseError(err)
|
|
|
case PathError:
|
|
|
PrintPathError(err)
|
|
|
- ...
|
|
|
+ ...
|
|
|
default:
|
|
|
fmt.Printf(“Not a special error, just %s\n”, err)
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
作为第二个例子考虑用 json 包的情况。当 json.Decode 在解析 JSON 文档发生语法错误时,指定返回一个 SyntaxError 类型的错误:
|
|
|
@@ -116,7 +108,6 @@ type SyntaxError struct {
|
|
|
}
|
|
|
|
|
|
func (e *SyntaxError) String() string { return e.msg }
|
|
|
-
|
|
|
```
|
|
|
|
|
|
在调用代码中你可以像这样用类型断言测试错误是不是上面的类型:
|
|
|
@@ -126,7 +117,6 @@ if serr, ok := err.(*json.SyntaxError); ok {
|
|
|
line, col := findLine(f, serr.Offset)
|
|
|
return fmt.Errorf(“%s:%d:%d: %v”, f.Name(), line, col, err)
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
包也可以用额外的方法(methods)定义特定的错误,比如 net.Errot:
|
|
|
@@ -137,7 +127,6 @@ type Error interface {
|
|
|
Timeout() bool // Is the error a timeout?
|
|
|
Temporary() bool // Is the error temporary?
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
在 [15.1 节](15.1.md) 我们可以看到怎么使用它。
|
|
|
@@ -153,7 +142,6 @@ r, err := syscall.Open(name, mode, perm)
|
|
|
if err != 0 {
|
|
|
fmt.Println(err.Error())
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
os 包也提供了一套像 os.EINAL 这样的标准错误,它们基于 syscall 错误:
|
|
|
@@ -161,13 +149,12 @@ os 包也提供了一套像 os.EINAL 这样的标准错误,它们基于 syscal
|
|
|
```go
|
|
|
var (
|
|
|
EPERM Error = Errno(syscall.EPERM)
|
|
|
- ENOENT Error = Errno(syscall.ENOENT)
|
|
|
+ ENOENT Error = Errno(syscall.ENOENT)
|
|
|
ESRCH Error = Errno(syscall.ESRCH)
|
|
|
EINTR Error = Errno(syscall.EINTR)
|
|
|
EIO Error = Errno(syscall.EIO)
|
|
|
- ...
|
|
|
+ ...
|
|
|
)
|
|
|
-
|
|
|
```
|
|
|
|
|
|
## 13.1.2 用 fmt 创建错误对象
|
|
|
@@ -180,7 +167,6 @@ var (
|
|
|
if f < 0 {
|
|
|
return 0, fmt.Errorf(“math: square root of negative number %g”, f)
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
第二个例子:从命令行读取输入时,如果加了 help 标志,我们可以用有用的信息产生一个错误:
|
|
|
@@ -190,10 +176,8 @@ if len(os.Args) > 1 && (os.Args[1] == “-h” || os.Args[1] == “--help”) {
|
|
|
err = fmt.Errorf(“usage: %s infile.txt outfile.txt”, filepath.Base(os.Args[0]))
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
```
|
|
|
|
|
|
-
|
|
|
## 链接
|
|
|
|
|
|
- [目录](directory.md)
|