从零开始学GO ---- 错误处理
Go 语言通过内置的错误接口提供了非常简单的错误处理机制--------error类型接口。在这个接口类型的声明中只包含了一个方法Error。Error方法不接受任何参数,但是会返回一个string类型的结果。它的作用是返回错误信息的字符串表示形式。
type error interface {
Error() string
}
使用error类型的方式通常是:
在函数声明的结果列表的最后,声明一个该类型的结果,同时在调用这个函数之后,先判断它返回的最后一个结果值是否“不为nil”。如果这个值“不为nil”,那么就进入错误处理流程,否则就继续进行正常的流程。
两个例子:
定义除法,如果除数为0,则附带返回error信息,否则就返回正常结果:
package main
import (
"fmt"
)
// 定义一个 DivideError 结构
type DivideError struct {
dividee int
divider int
}
// 实现 `error` 接口
func (de *DivideError) Error() string {
strFormat := `
Cannot proceed, the divider is zero.
dividee: %d
divider: 0
`
return fmt.Sprintf(strFormat, de.dividee)
}
// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
if varDivider == 0 { //如果除数是0,则返回error
dData := DivideError{
dividee: varDividee,
divider: varDivider,
}
errorMsg = dData.Error()
return
} else {
return varDividee / varDivider, ""
}
}
func main() {
// 正常情况
if result, errorMsg := Divide(100, 10); errorMsg == "" {
fmt.Println("100/10 = ", result)
} // 100/10 = 10
// 当除数为零的时候会返回错误信息
if _, errorMsg := Divide(100, 0); errorMsg != "" {
fmt.Println("errorMsg is: ", errorMsg)
}
/*
errorMsg is:
Cannot proceed, the divider is zero.
dividee: 100
divider: 0
*/
}
写一个函数echo,如果参数的string不是空字符串,则打印,否则报错。
调用echo函数之后,都会把它返回的结果值赋给变量resp和err,并且总是先检查err的值是否“不为nil”,如果是,就打印错误信息,否则就打印常规的响应信息。
package main
import (
"errors"
"fmt"
)
func echo(request string) (response string, err error) {
if request == "" {
err = errors.New("empty request")
return
}
response = fmt.Sprintf("echo: %s", request)
return
}
func main() {
for _, req := range []string{"", "hello!"} {
fmt.Printf("request: %s\n", req)
resp, err := echo(req)
if err != nil {
fmt.Printf("error: %s\n", err)
continue
}
fmt.Printf("response: %s\n", resp)
}
}
/*
request:
error: empty request
request: hello!
response: echo: hello!
*/
对于具体错误的判断,Go 语言中都有哪些惯用法?
- 对于类型在已知范围内的一系列错误值,一般使用类型断言表达式或类型switch语句来判断;
- 对于已有相应变量且类型相同的一系列错误值,一般直接使用判等操作来判断;
- 对于没有相应变量且类型未知的一系列错误值,只能使用其错误信息的字符串表示形式来做判断。