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

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

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



变长参数


什么是变长参数


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


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

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

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


image.png


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

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

image.png


我们执行下

image.png


变长参数有什么用

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

image.png

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

image.png


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

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

我们执行查看下

image.png



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

image.png

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



panic


panic简单案例

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

image.png


我们执行下

image.png


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



go 为什么使用panic

一开始看到panic的时候,我觉得很神奇,对于目前现在的编程语言,类似c++pythonjava其实都有处理异常机制,那就是try-catch, 而为什么go需要自己来获取错误呢? 之所以go不提供try-catch,是因为这会让程序变得复杂,所以不提供,但是Go提供了另外一个函数,那就是recover


执行panic后发送了什么

当我们程序panic后,程序会停止,不会执行下面的语句,若我们之前定义了defer语句,则defer语句会被执行,且程序异常后会打印出问题的信息,供开发者查看

我们举个例子

image.png


我们按照上述的意思,若panic之后,下列语句就不执行了,我们来看下

image.png

从结果,可知,的确是这样的。



recover


panic后,我们可以使用recover来恢复程序,recover需要写在defer中,因为它在程序结尾处运行,还记得上一节提到的go中为什么没有try-catch么,go使用recover的意义是在于让我们来判断该panic是否是我们预想的,若是我们预想的,那么我们可以像普通函数一样来处理该panic,若不是的话,则我们的确需要来触发panic


我们可以通过例子来说明

我们编写一个读取josn配置文件的程序,当文件不存在时,我们使用recover恢复一下,当使用json.Unmarshal解析失败时,我们认为此函数异常,则抛出panic

我们先看下,不添加recover,正常逻辑的程序的输出


image.png


我们定义conf.json

image.png

我们运行程序

image.png

我们来修改下程序

image.png



增加如下语句

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 改一下名称,再次执行程序

image.png


这里并没有抛panic,应该说,这里抛了panic,被我们给恢复了,

我们再试试让json解析失败呢

我们只需要将 server_id给调整的大一些,让其溢出即可

image.png


我们再尝试一下程序

image.png

这里就抛panic了,若想恢复该panic,我们可以在main函数中定义recover即可



总结


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


panicrecover看了一个大概。哎。


相关文章
|
2月前
|
Go
Golang语言之函数(func)进阶篇
这篇文章是关于Golang语言中函数高级用法的教程,涵盖了初始化函数、匿名函数、闭包函数、高阶函数、defer关键字以及系统函数的使用和案例。
64 3
Golang语言之函数(func)进阶篇
|
2月前
|
Go
Golang语言之函数(func)基础篇
这篇文章深入讲解了Golang语言中函数的定义和使用,包括函数的引入原因、使用细节、定义语法,并通过多个案例展示了如何定义不返回任何参数、返回一个或多个参数、返回值命名、可变参数的函数,同时探讨了函数默认值传递、指针传递、函数作为变量和参数、自定义数据类型以及返回值为切片类型的函数。
62 2
Golang语言之函数(func)基础篇
|
1月前
|
安全 Java Go
【Golang入门】简介与基本语法学习
Golang语言入门教程,介绍了Go语言的简介、基本语法、程序结构、变量和常量、控制结构、函数、并发编程、接口和类型、导入包、作用域以及错误处理等关键概念,为初学者提供了一个全面的学习起点。
24 0
|
2月前
|
Unix Go
Golang语言标准库time之日期和时间相关函数
这篇文章是关于Go语言日期和时间处理的文章,介绍了如何使用Go标准库中的time包来处理日期和时间。
48 3
|
6月前
|
Go
golang中置new()函数和make()函数的区别
golang中置new()函数和make()函数的区别
|
3月前
|
机器学习/深度学习 存储 人工智能
Golang bytes 包学习
Golang bytes 包学习
25 3
|
4月前
|
编译器 Go C语言
通过例子学习在golang中调试程序
【7月更文挑战第4天】Go语言支持使用cgo进行汇编调试,官方文档在golang.org/doc/asm。注意,调试Go运行时可能遇到变量不可用或行号错误,需谨慎使用step命令。
74 1
通过例子学习在golang中调试程序
|
6月前
|
Go
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
【4月更文挑战第21天】Go语言函数是代码组织的基本单元,用于封装可重用逻辑。本文介绍了函数定义(包括基本形式、命名、参数列表和多返回值)、调用以及匿名函数与闭包。在函数定义时,注意参数命名和注释,避免参数顺序混淆。在调用时,要检查并处理多返回值中的错误。理解闭包原理,小心处理外部变量引用,以提升代码质量和可维护性。通过实践和示例,能更好地掌握Go语言函数。
100 1
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
|
6月前
|
Go
golang学习参考记录
golang学习参考记录
|
6月前
|
JSON Go 数据格式
golang学习7,glang的web的restful接口结构体传参
golang学习7,glang的web的restful接口结构体传参