小熊今天有意外收获,忍不住给大家分享我愉快的心情!昨天中午下楼取外卖的时候被一个同事认出来了,他问我:“是不是【编程三分钟】的作者,文章写的不错”。
你知道吗!我当时就是一愣,然后差点感动到哭出来,虽然小熊的号比不上大牛的号,不能随便发一篇文章都有成千上万的阅读量;但是非常开心的是,我还有你们,默默的关注我,爱你们~!
golang
异常处理思想
gotry catchtry catchtry
go
nilif
所以异常应该总是掌握在我们的手上,保证每次操作产生的影响达到最小,保证程序即使部分地方出现问题,也不会影响整个程序的运行,及时的处理异常,这样就可以减轻上层处理异常的压力。
同时也不要让未知的异常使你的程序崩溃。
异常的形式
我们应该让异常以这样的形式出现
func Demo() (int, error)
我们应该让异常以这样的形式处理(卫述语句)
_,err := errorDemo()
if err!=nil{
fmt.Println(err)
return
}
自定义异常
00
func divisionInt(a, b int) (int, error) {
if b == 0 {
return -1, errors.New("除数不能为0")
}
return a / b, nil
}
这个函数应该被这么调用
a, b := 4, 0
res, err := divisionInt(a, b)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(a, "除以", b, "的结果是 ", res)
可以注意到上面的两个知识点
errors.New("字符串")err.Error()
只要记得这些,你就掌握了自定义异常的基本方法。
errors.New("字符串")fmt.Errorf
err = fmt.Errorf("产生了一个 %v 异常", "喝太多")
详细的异常信息
errors
errorserrorErrorstring
type error interface {
Error() string
}
只要结构体实现了这个方法就行,源码的实现方式如下
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
// 多一个函数当作构造函数
func New(text string) error {
return &errorString{text}
}
error
这个自定义异常可以在报错的时候存储一些信息,供外部程序使用
type FileError struct {
Op string
Name string
Path string
}
// 初始化函数
func NewFileError(op string, name string, path string) *FileError {
return &FileError{Op: op, Name: name, Path: path}
}
// 实现接口
func (f *FileError) Error() string {
return fmt.Sprintf("路径为 %v 的文件 %v,在 %v 操作时出错", f.Path, f.Name, f.Op)
}
调用
f := NewFileError("读", "README.md", "/home/how_to_code/README.md")
fmt.Println(f.Error())
输出
路径为 /home/how_to_code/README.md 的文件 README.md,在 读 操作时出错
defer
上面说的内容很简单,在工作里也是最常用的,下面说一些拓展知识。
Godeferdefer
比如下面的例子是在一个函数内的三条语句,他是这么怎么执行的呢?
defer fmt.Println("see you next time!")
defer fmt.Println("close all connect")
fmt.Println("hei boy")
defer
hei boy
close all connect
see you next time!
deferc++
defer
tcp
defer
panic
defer
Gopaincgoroutinedefer
有时候在程序运行缺乏必要的资源的时候应该手动触发宕机(比如配置文件解析出错、依赖某种独有库但该操作系统没有的时候)
defer fmt.Println("关闭文件句柄")
panic("人工创建的运行时异常")
报错如下
panic recover
panic
然后再借助运维监控系统对日志的监控,发送告警给运维、开发人员,进行紧急修复。
语法如下:
func divisionIntRecover(a, b int) (ret int) {
defer func() {
if err := recover(); err != nil {
// 打印异常,关闭资源,退出此函数
fmt.Println(err)
ret = -1
}
}()
return a / b
}
调用
var res int
datas := []struct {
a int
b int
}{
{2, 0},
{2, 2},
}
for _, v := range datas {
if res = divisionIntRecover(v.a, v.b); res == -1 {
continue
}
fmt.Println(v.a, "/", v.b, "计算结果为:", res)
}
输出结果
runtime error: integer divide by zero
2 / 2 计算结果为: 1
panicrecoverdeferrecover
go
github