目录
2.2 程序中触发了panic会终止后面的语句,defer语句还是会按倒序执行
1.错误:
概念:程序运行过程中可能报错的代码,是可以预见的,需要手动处理
1.1 Go语言声明错误的两种方式
package main
import (
"errors"
"fmt"
)
/*
Go语言声明错误的两种方式
1.errors.New("错误描述")
2.fmt.Errorf("错误描述",错误码)
*/
func main() {
//方式一
err1 := errors.New("errors声明的错误")
fmt.Printf("类型:%T,内容:%v\n", err1, err1)
//方式二
err2 := fmt.Errorf("fmt声明的错误,错误码:%d", 500)
fmt.Printf("类型:%T,内容:%v\n", err2, err2)
//errors实现年龄校验
err3 := func(age int) error {
if age < 0 {
return errors.New("年龄不能小于0")
}
return nil
}(-1)
if err3 != nil {
fmt.Printf("年龄校验不通过,原因:%v\n", err3)
}
//fmt实现性别校验
err4 := func(gender string) error {
if gender != "男" && gender != "女" {
return fmt.Errorf("性别必须为男|女,code:%d", 500)
}
return nil
}("未知")
if err4 != nil {
fmt.Printf("性别校验不通过,原因:%v\n", err4)
}
}
1.2 查看源码,学习如何自定义错误
package main
import (
"errors"
"fmt"
"net"
"os"
)
/*
查看源码,学习自定义错误
*/
func main() {
//打开文件方法
file, err := os.Open("day11//note.txt1")
if err != nil {
fmt.Printf("文件打开失败,原因:%v\n", err) //文件打开失败,原因:open day11//note.txt1: no such file or directory
} else {
fmt.Printf("文件打开成功,文件名:%s\n", file.Name())
}
//根据域名查看ip地址方法
host, err2 := net.LookupHost("www.baidu.com1")
if err2 != nil {
fmt.Println(err2) //lookup www.baidu.com1: no such host
var dnsError *net.DNSError
ok := errors.As(err2, &dnsError)
if ok {
if dnsError.IsTimeout {
fmt.Println("超时错误")
} else if dnsError.IsTemporary {
fmt.Println("临时错误")
} else if dnsError.IsNotFound {
fmt.Println("地址错误") //地址错误
} else {
fmt.Println("其他错误")
}
}
}
fmt.Printf("域名访问成功,地址:%v", host)
}
1.3 自定义错误
package main
import (
"errors"
"fmt"
)
/*
自定义错误
1.自定义结构体
2.实现error接口的Error()string方法,定义打印格式,
*/
type DiyError struct {
Code int
Msg string
}
func (e *DiyError) Error() string {
return fmt.Sprintf("{code:%d,msg:%s}", e.Code, e.Msg)
}
func main() {
//自定义校验年龄方法,校验不通过,抛出自定义异常
err := func(age int) error {
if age < 0 {
return &DiyError{500, "年龄不能小于0"}
}
return nil
}(-1)
if err != nil {
fmt.Println(err)
var diyError *DiyError
ok := errors.As(err, &diyError)
if ok {
fmt.Printf("年龄校验不通过,原因:%s,错误码:%d", diyError.Msg, diyError.Code)
}
}
}
2.异常
2.1 Go语言中抛出异常
/*
异常:代码运行过程中不可预见的报错,会抛出panic,针对代码中可能出现的panic可以recover处理panic
*/
func main() {
//手动抛出异常
panic("我是一个panic")
}
2.2 程序中触发了panic会终止后面的语句,defer语句还是会按倒序执行
/*
异常:代码运行过程中不可预见的报错,会抛出panic,模拟代码抛出panic
*/
func main() {
defer fmt.Println("main-->1")
defer fmt.Println("main-->2")
fmt.Println("main-->3")
test(-1)
defer fmt.Println("main-->4")
fmt.Println("main-->5")
}
func test(i int) {
defer fmt.Println("test-->1")
defer fmt.Println("test-->2")
fmt.Println("test-->3")
if i < 0 { //如果i<0,手动抛出一个panic,正常业务逻辑中可能就是代码自动抛出的
panic("出现了panic")
}
defer fmt.Println("test-->4")
fmt.Println("test-->5")
}
2.3 使用defer执行匿名函数+recover处理异常
func main() {
defer fmt.Println("main-->1")
defer fmt.Println("main-->2")
fmt.Println("main-->3")
test(-1)
defer fmt.Println("main-->4")
fmt.Println("main-->5")
}
func test(i int) {
//最终代码执行完,不希望预见不到的异常抛出,可以使用defer执行匿名函数+recover处理
defer func() {
if msg := recover(); msg != nil {
fmt.Println("recover处理了异常,msg:", msg)
}
}()
defer fmt.Println("test-->1")
defer fmt.Println("test-->2")
fmt.Println("test-->3")
if i < 0 { //如果i<0,手动抛出一个panic,正常业务逻辑中可能就是代码自动抛出的
panic("出现了panic")
}
defer fmt.Println("test-->4")
fmt.Println("test-->5")
}