Study Golang — (4) 函数

1、函数声明

每个函数声明都包含一个名字、一个形参列表、一个可选的返回列表以及函数体:

例如:

通过以上代码可以看出:

  • 关键字func用来声明一个函数funcName
  • 函数可以有一个或者多个参数,每个参数后面带有类型,通过逗号“,”分隔
  • 函数可以返回多个值
  • 返回值声明中,既可以声明变量,也可以不声明变量,直接就两个类型
  • 如果只有一个返回值且不声明返回值变量,那么你可以省略 包括返回值 的括号
  • 如果没有返回值,那么就直接省略最后的返回信息

函数的类型称为“函数签名”,当两个函数拥有两个相同的形参列表和返回列表时,认为这两个函数的类型或签名是相同的。形参和返回值的名字不会影响到函数类型,采用简写同样也不会影响到函数的类型。

2、函数变量

函数变量的零值是 nil(空值),调用一个空的函数变量将导致宕机。

3、匿名函数

函数字面量与函数声明类似,但在func关键字后面没有函数的名称,它是一个表达式,它的值称作匿名函数。
这种方式定义的函数能够获取到整个词法环境,因此里层的函数可以使用外层函数中的变量,例如:

函数squares返回了另一个函数,类型是func() int。

4、变长函数

变长函数被调用的时候可以有可变的参数个数。
在参数列表最后的类型名称之前使用省略号“…”表示声明一个变长函数。
调用这个函数的时候可以传递该类型任意数目的参数:

在函数体内,vals是一个int类型的slice。
当实参已经存在于一个slice中的时候调用变长函数,需要在最后一个参数后面放一个省略号:

尽管…int参数就像函数体内的slice,但变长函数的类型和一个带有普通slice参数的函数的类型不同:

变长函数通常用于格式化字符串。

5、defer:延迟函数调用

语法上,一个defer语句就是一个普通的函数或方法调用,在调用之前加上关键字defer。
无论正常情况下执行return语句或函数执行完毕,还是不正常情况下比如发生空压机,实际的调用推迟到包含defer语句的函数执行完后才执行。
defer语句没有限制使用次数,执行的时候以调用defer语句顺序的倒序进行。

上面有很多重复的代码,Go的defer有效解决了这个问题。使用它后,不但代码量减少了很多,而且程序变得更优雅。在defer后指定的函数会在函数退出前调用。

正确使用defer语句的地方是在成功获取到资源之后。

由于延迟函数不到函数的最后一刻是不会执行的,要注意循环里defer的使用:

一种解决方式是将循环体(包括defer语句)放到另一个函数里,每次循环迭代都会调用文件关闭函数:

6、宕机与恢复

由于宕机会引起程序异常退出,因此只有在发生严重的错误时才会使用宕机。

panic是一个内建函数,可以中断原有的控制流程,进入一个panic状态中。当函数F调用panic,函数F的执行被中断,但是F中的延迟函数会正常执行,然后F返回到调用它的地方。
在调用的地方,F的行为就像调用了panic。这一过程继续向上,直到发生panic的goroutine中所有调用的函数返回,此时程序退出。panic可以直接调用panic函数产生。也可以由运行时错误产生,例如访问越界的数组。

如果内置的recover函数在延迟函数的内部调用,而且这个包含defer语句的函数发生宕机,recover会终止当前的宕机状态并且返回宕机的值。函数不会从之前宕机的地方继续运行,而是正常返回。
recover仅在延迟函数中有效。在正常的执行过程中,调用recover会返回nil,并且没有其它任何效果。如果当前的goroutine陷入panic状态,调用recover可以捕获到panic的输入值,并且恢复正常的执行。

下面这个函数演示了如何在过程中使用panic

下面这个函数检查作为其参数的函数在执行时是否会产生panic:

————————————————————

原创文章,转载请注明: 转载自孙希栋的博客

本文链接地址: 《Study Golang — (4) 函数》

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Scroll Up