什么是错误error
什么是错误
错误指的是可能出现问题的地方出现了问题。比如打开一个文件时失败,这种情况在人们的意料之中。
和错误类似的还有一个异常,指的是不应该出现问题的地方出现了问题。比如引用了空指针,这种情况在人们的意料之外。可见,错误是业务过程的一部分,而异常不是。
打开文件,存在错误情况
package main
import (
"fmt"
"os"
)
func main() {
// 打开一个文件
file, err := os.Open("abc.txt")
if err != nil { //当有错误时,打印输出并返回
fmt.Println(err)
return
} else { //否则打开文件
fmt.Println(file)
}
}
/*
open abc.txt: The system cannot find the file specified.
*/
在实际工程项目中,我们希望通过程序的错误信息快速定位问题,但是又不喜欢错误处理代码写的冗余而又啰嗦。
Go语言没有提供像Java.c#语言中的try..catch异常处理方式,而是通过函数返回值逐层往上抛。
这种设计,鼓励工程师在代码中显式的检查错误,而非忽略错误
好处就是避兔漏掉本应处理的错误。但是带来一个弊端,让代码繁琐。
Go中的错误也是一种类型。错误用内置的error类型表示。就像其他类型的,如int, float64。错误值可以存储在变量中,从函数中返回,等等。
创建自己的errp错误信息
//创建一个自己的error错误信息,通过errors可以创建
1、errors.New("我是一个错误信息")
//也可以通过fmt创建
2、fmt.Errorf("我是一个错误信息%T", 500)
package main
import (
"errors"
"fmt"
)
func main() {
// 通过errors创建
errinfo := errors.New("我是一个错误信息")
fmt.Printf("%T\n", errinfo) //打印输出类型
err := setage(-1)
if err != nil {
fmt.Println(err)
}
// 还可以通过fmt创建
errinfo2 := fmt.Errorf("我是一个错误信息%T", 500)
fmt.Printf("%T\n", errinfo2) //打印输出类型
}
// 定义一个setage函数
func setage(age int) error {
if age < 0 {
return errors.New("年龄输入不合法")
} else {
fmt.Println(age)
return nil
}
}
/*
*errors.errorString
年龄输入不合法
*errors.errorString
*/
错误类型
error类型是一个接口类型
type error interface{
Error()string
}
通过断言,来判断具体的错误类型,然后进行对应的错误处理
package main
import (
"fmt"
"os"
)
func main() {
// 打开一个文件
file, err := os.Open("abc.txt")
if err != nil { //当有错误时,打印输出并返回
fmt.Println(err)
temp, ok := err.(*os.PathError)
if ok {
fmt.Println(temp.Op)
fmt.Println(temp.Err)
fmt.Println(temp.Path)
}
/*
open
The system cannot find the file specified.
abc.txt
*/
return
} else { //否则打开文件
fmt.Println(file)
}
}
package main
import (
"fmt"
"net"
)
func main() {
addrs, err := net.LookupHost("www.baidu.com")
fmt.Println(err)
dnsError, ok := err.(*net.DNSError)
if ok {
if dnsError.Timeout() {
fmt.Println("超时")
} else if dnsError.Temporary() {
fmt.Println("临时错误")
} else {
fmt.Println("其他错误")
}
}
fmt.Println(addrs)
}
/*
<nil>
[14.215.177.38 14.215.177.39]
*/
自定义错误类型
package main
import "fmt"
// 自定义一个错误结构体
type Mydiyerror struct {
msg string
code int
}
// 实现方法接收 对象为Mydiyerror, 返回值类型为string
func (e Mydiyerror) Error() string {
return fmt.Sprint("错误信息", e.msg, "状态码:", e.code)
}
func test04(i int) (int, error) {
if i != 0 {
return i, &Mydiyerror{"非零数据", 500}
}
return i, nil
}
func main() {
i, err := test04(1)
if err != nil {
myerr, ok := err.(*Mydiyerror)
if ok {
fmt.Println(myerr.msg)
fmt.Println(myerr.code)
}
}
fmt.Println(i)
}
/*
非零数据
500
1
*/
panic和recover
go语言追求简洁,所以go语言中没有try...catch语句
因为go语言的作者认为将异常和控制语句混在一起,很容易让这个程序变得混乱,异常也很容易被滥用。
所以在go语言中,为了防止异常被滥用,我们常常使用函数的返回值来返回错误,而不是用异常来代替错误
如果在一些场景下确实需要处理异常,就可以使用panic和recover
panic用来抛出异常,recover用来恢复异常
panic
如果函数F中书写并触发了panic语句,会终止其后要执行的代码。在panic所在函数F内如果存在要执行的defer函数列表,则按照defer书写顺序的逆序执行
package main
import "fmt"
func main() {
//2.执行顺序为main--3, test05方法中test 3 2 1,main 2 1
defer fmt.Println("main--1")
defer fmt.Println("main--2")
fmt.Println("main--3")
test05(1)
fmt.Println("main--4")
defer fmt.Println("main--5")
}
func test05(num int) {
//1.执行顺序分别是3 2 1 在panic后面的4和5不执行
defer fmt.Println("test--1")
defer fmt.Println("test--2")
fmt.Println("test--3")
if num == 1 {
panic("出现异常——————")
}
fmt.Println("test--4")
defer fmt.Println("test--5")
}
/*
main--3
test--3
test--2
test--1
main--2
main--1
panic: 出现异常——————
*/
recover
recover的作用是捕获panic,从而恢复正常代码执行
recover必须配合defer使用
recover没有传入的参数,但是有返回值,返回值就是panic传递的值
package main
import "fmt"
func main() {
defer fmt.Println("main--1")
defer fmt.Println("main--2")
fmt.Println("main--3")
test05(1)
fmt.Println("main--4")
defer fmt.Println("main--5")
}
func test05(num int) {
defer func() {
msg := recover()
if msg != nil {
fmt.Println("程序恢复了————")
}
}()
defer fmt.Println("test--1")
defer fmt.Println("test--2")
fmt.Println("test--3")
if num == 1 {
panic("出现异常——————")
}
fmt.Println("test--4")
defer fmt.Println("test--5")
}
/*
main--3
test--3
test--2
test--1
程序恢复了————
main--4
main--5
main--2
main--1
*/
- 触发panic
- 逆序执行test05函数中的panic前三条的语句
- 执行到第三条defer时,recover恢复恐慌并输出信息
- 返回外部函数,程序继续执行
由于recover恢复恐惧,所以程序就不会panic而退出执行,外部函数还能够正常执行下去
标签:defer,错误,--,fmt,Println,test,Go,狂神,main From: https://www.cnblogs.com/DuPengBG/p/17012201.html