昨天我们已经了解了go
函数部分,接下来我们继续来看下函数剩下的部分,若昨天所述,我们应当在学习中保持空杯心态,不浮躁不焦虑,看了不一等会,但是看了,能够总结,并且以博文的方式表达出来,这应该才是学了,加油哦,运维小学生。
变长参数
什么是变长参数
函数在调用的时候有可变的参数,这个就被称之为变长函数。
还记得,我们使用输出语句么?它就可以接收多个参数。
mainStart := time.Now() ... fmt.Println("主函数运行了: " , time.Since(mainStart))
我们可以看到,上述 fmt.Println("主函数运行了: " , time.Since(mainStart))
函数中调用了多个参数变量,我们可以切进去看下
发现参数是 a ...interface{}
,所以这个也被称为变长参数,我们调用有这个类型的函数的时候,可以传递任何参数
其实这个参数传进去的是切片,我们可以一下例子来看下
我们执行下
变长参数有什么用
我们可以来写这样一个经典的案例,定义一个函数,传入2各值: a
、b
,我们返回一个最大值
以上例子,我们很快就写出来了。我们执行下
如果后期修改需求,有3个参数,5个参数,n
个参数呢? 我们要定义n个函数来处理么?
我们可以使用变长参数,例如,我们修改下代码
我们执行查看下
可以看到,我们正常返回了,没有问题的
我们假如已经存在了一个slice
,我们如何调用呢? 我们只需要在后面加一个省略号,即可调用,即: f1(slice1...)
panic
panic简单案例
我们来编写一个程序,其中定义一个切片,我们访问一下切片外的数据,模拟越界
我们执行下
我们看到抛错了,一般而言,go panic
会打印出 某个函数调用的语句,我们可以根据信息,来检测程序问题,而panic
语句后的代码,将不会被执行了。
go 为什么使用panic
一开始看到panic
的时候,我觉得很神奇,对于目前现在的编程语言,类似c++
、python
、java
其实都有处理异常机制,那就是try-catch
, 而为什么go
需要自己来获取错误呢? 之所以go
不提供try-catch
,是因为这会让程序变得复杂,所以不提供,但是Go
提供了另外一个函数,那就是recover
执行panic后发送了什么
当我们程序panic
后,程序会停止,不会执行下面的语句,若我们之前定义了defer
语句,则defer
语句会被执行,且程序异常后会打印出问题的信息,供开发者查看
我们举个例子
我们按照上述的意思,若panic
之后,下列语句就不执行了,我们来看下
从结果,可知,的确是这样的。
recover
在panic
后,我们可以使用recover
来恢复程序,recover
需要写在defer
中,因为它在程序结尾处运行,还记得上一节提到的go
中为什么没有try-catch
么,go
使用recover
的意义是在于让我们来判断该panic
是否是我们预想的,若是我们预想的,那么我们可以像普通函数一样来处理该panic
,若不是的话,则我们的确需要来触发panic
。
我们可以通过例子来说明
我们编写一个读取josn
配置文件的程序,当文件不存在时,我们使用recover
恢复一下,当使用json.Unmarshal
解析失败时,我们认为此函数异常,则抛出panic
我们先看下,不添加recover
,正常逻辑的程序的输出
我们定义conf.json
我们运行程序
我们来修改下程序
增加如下语句
defer func() { perr := recover() switch perr.(type) { case *os.PathError: // os.open错误 fmt.Println("error: ", conf, "未找到") case *json.UnmarshalTypeError: // json.Unmarshal错误 panic(fmt.Sprintf("%s , %v", "自定义 panic json UnmarshalTypeError", perr)) } }()
这里,我们使用断言,来判断,到底是 os.open错误 还是 json.Unmarshal错误 ,好的,我们来模拟下
我们将conf.json
改一下名称,再次执行程序
这里并没有抛panic
,应该说,这里抛了panic
,被我们给恢复了,
我们再试试让json
解析失败呢
我们只需要将 server_id
给调整的大一些,让其溢出即可
我们再尝试一下程序
这里就抛panic
了,若想恢复该panic
,我们可以在main
函数中定义recover
即可
总结
panic
和recover
都和错误有关,那么我们应该如何定义错误呢,其实这对于我们运维深有感悟,面对程序业务日志,我们再做日志分析的时候,我们不清楚哪些是应该抓出来,要不就是一条不够,要查询上下文,当协程足够多的时候,查询起来会分麻烦,所以,作为运维,希望在设计错误消息的时候,确保每条日志包含的信息足够多,最好不需要借助文件上下文分析的最好。
把panic
和recover
看了一个大概。哎。