36.笔记go语言——函数
函数是构建Go程序的基础部件.Go不允许函数嵌套。然而你可以利用匿名函数实现它.
作用域
在Go中,定义在函数外的变量是全局的,那些定义在函数内部的变量,对于函数来说是局部的。如果命名覆盖——一个局部变量与一个全局变量有相同的名字——在函数执行的时候,局部变量将覆盖全局变量。
代码:
package main
var a = 6
func main() {
p()
q()
p()
}
func p() {
println(a)
}
func q() {
a:= 5
println(a)
}
输出:
6
5
6
多值返回
Go一个非常特别的特性(对于编译语言而言)是函数和方法可以返回多个值(Python 和 Perl 同样也可以)。这可以用于改进一大堆在 C 程序中糟糕的惯例用法:修改参数的方式,返回一个错误(例如遇到EOF则返回-1)。在Go中,Write返回一个计数值和一个错误:“是的,你写入了一些字节,但是由于设备异常,并不是全部都写入了。”
代码:
package main
func main() {
a:= []byte{'1', '2', '3', '4'}
varx int
println(len(a))
fori := 0; i < len(a); {
x,i = nextInt(a, i)
println(x)
}
}
func nextInt(b []byte, i int) (int, int) {
x:= 0
//假设所有的都是数字
for; i < len(b); i++ {
x= x*10 + int(b[i]) - '0'
}
returnx, i
}
没有元组作为原生类型,多返回值可能是最佳的选择。你可以精确的返回希望的值,而无须重载域空间到特定的错误信号上。
命名返回值
Go函数的返回值或者结果参数可以指定一个名字,并且像原始的变量那样使用,就像输入参数那样。如果对其命名,在函数开始时,它们会用其类型的零值初始化;如果函数在不加参数的情况下执行了 return语句,结果参数的当前值会作为返回值返回。用这个特性,允许(再一次的)用较少的代码做更多的事。
名字不是强制的,但是它们可以使得代码更加健壮和清晰:这是文档。例如命名int类型的nextPos返回值,就能说明哪个代表哪个。
由于命名结果会被初始化并关联于无修饰的return,它们可以非常简单并且清晰。
延迟代码
假设有一个函数,打开文件并且对其进行若干读写。在这样的函数中,经常有提前返回的地方。如果你这样做,就需要关闭正在工作的文件描述符。
为了解决这些,Go有了defer语句。在defer后指定的函数会在函数退出前调用。
延迟的函数是按照后进先出(LIFO)的顺序执行.
函数符号也就是被叫做闭包的东西
变参
接受变参的函数是有着不定数量的参数的。为了做到这点,首先需要定义函数使其接受变参.
arg ...int告诉Go这个函数接受不定数量的参数。注意,这些参数的类型全部是int。
函数作为值
就像其他在Go中的其他东西一样,函数也是值而已。
例如代码:
package main
func main() {
a:= func() {
println("Hello")
}
a()
}
回调
当函数作为值时,就可以很容易的传递到其他函数里,然后可以作为回调。
恐慌(Panic)和恢复(Recover)
Go没有像Java那样的异常机制:不能抛出一个异常。作为替代,它使用了恐慌和恢复(panic-and-recover)机制。一定要记得,这应当作为最后的手段被使用,你的代码中应当没有,或者很少的令人恐慌的东西。这是个强大的工具,明智的使用它。
Panic
panic是一个内建函数,可以中断原有的控制流程,进入一个令人恐慌的流程中。当函数F调用panic,函数F的执行被中断,并且F中的延迟函数会正常执行,然后F返回到调用它的地方。在调用的地方,F的行为就像调用了panic。这一过程继续向上,直到程序崩溃时的所有goroutine返回。恐慌可以直接调用panic产生。也可以由运行时错误产生,例如访问越界的数组。
Recover
一个内建的函数,可以让进入令人恐慌的流程中的 goroutine 恢复过来。recover仅在延迟函数中有效。
对应异常机制,Go 的这种错误机制或许可以叫做恐慌机制:当你遇到它时应该感到恐慌(panic),然后应该恢复(recover)它.在正常的执行过程中,调用recover会返回nil并且没有其他任何效果。如果当前的goroutine陷入恐慌,调用recover可以捕获到panic的输入值,并且恢复正常的执行。
有疑问加站长微信联系(非本文作者)