学习golang(7) 初探:函数(2)

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

昨天我们已经了解了go函数部分,接下来我们继续来看下函数剩下的部分,若昨天所述,我们应当在学习中保持空杯心态,不浮躁不焦虑,看了不一等会,但是看了,能够总结,并且以博文的方式表达出来,这应该才是学了,加油哦,运维小学生。

变长参数

什么是变长参数

函数在调用的时候有可变的参数,这个就被称之为变长函数。

还记得,我们使用输出语句么?它就可以接收多个参数。

mainStart := time.Now()
...
fmt.Println("主函数运行了: " , time.Since(mainStart))

我们可以看到,上述 fmt.Println("主函数运行了: " , time.Since(mainStart))函数中调用了多个参数变量,我们可以切进去看下

发现参数是 a ...interface{} ,所以这个也被称为变长参数,我们调用有这个类型的函数的时候,可以传递任何参数

其实这个参数传进去的是切片,我们可以一下例子来看下

我们执行下

变长参数有什么用

我们可以来写这样一个经典的案例,定义一个函数,传入2各值: ab,我们返回一个最大值

以上例子,我们很快就写出来了。我们执行下

如果后期修改需求,有3个参数,5个参数,n个参数呢? 我们要定义n个函数来处理么?

我们可以使用变长参数,例如,我们修改下代码

我们执行查看下

可以看到,我们正常返回了,没有问题的

我们假如已经存在了一个slice,我们如何调用呢? 我们只需要在后面加一个省略号,即可调用,即: f1(slice1...)

panic

panic简单案例

我们来编写一个程序,其中定义一个切片,我们访问一下切片外的数据,模拟越界

我们执行下

我们看到抛错了,一般而言,go panic 会打印出 某个函数调用的语句,我们可以根据信息,来检测程序问题,而panic语句后的代码,将不会被执行了。

go 为什么使用panic

一开始看到panic的时候,我觉得很神奇,对于目前现在的编程语言,类似c++pythonjava其实都有处理异常机制,那就是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即可

总结

panicrecover都和错误有关,那么我们应该如何定义错误呢,其实这对于我们运维深有感悟,面对程序业务日志,我们再做日志分析的时候,我们不清楚哪些是应该抓出来,要不就是一条不够,要查询上下文,当协程足够多的时候,查询起来会分麻烦,所以,作为运维,希望在设计错误消息的时候,确保每条日志包含的信息足够多,最好不需要借助文件上下文分析的最好。

panicrecover看了一个大概。哎。

posted @ 2022-04-27 15:00  pdudos  阅读(0)  评论(0编辑  收藏  举报  来源