函数时Go语言中的基础组件,函数定义如下:
type mytype int
func (p mytype) funcname(q int) (r,s int) {return 0,0}
1 2 3 4 5 6
1, 关键字func用于定义一个函数
2, 函数可以绑定到特定的类型上,这叫做接收者。有接收者的函数被称作method。
3, funcname是你的函数名字
4, int类型的变量q作为输入参数。参数以传值的方式传递。
5, 变量r和s是函数的两个命名返回值。在Go的函数中可以返回多个值。如果不想对返回的值命名,可以直接写(int,int)。 如果只返回一个值,可以省略圆括号。如果函数是一个子过程,并且没有任何返回值,也可以省略这些内容。
6, 这是函数体,注意return是一个语句,所以包裹返回值得括号可以省略。
作用域
var a int = 6 //全局变量
func main() {
p()
q()
p()
}
func p() {
println(a)
}
func q() {
a := 7 //局部变量
println(a)
}
//输出
6
7
6
var a int = 6
func main() {
p()
q()
p()
}
func p() {
println(a)
}
func q() {
a = 5 //全局变量重新赋值
println(a)
}
//输出
6
5
5
下面一个例子在p()中调用q()
var a int = 6
func main() {
p()
}
func p() {
a := 8
println(a)
q()
}
func q() {
println(a)
}
//输出
8
6
多返回值
Go一个非常特别的特性(对编译语言而言)是函数和方法可以返回多个值,这可以改进一大堆在C程序中糟糕的惯例用法: 修改参数的方式,返回一个错误(例如遇到EOF,返回-1),在Go中,Write函数返回一个计数值和一个错误
命名返回值
Go的函数的返回值或者结果参数可以指定一个名字,并且像原始变量那样使用,就像输入的参数那样。
如果对其命名,在函数开始时,它会用对应类型的0值初始化。如果函数执行了不带参数的return语句,结果参数返回。这允许用更少的代码干更多的事。
func max(a, b int) (sum int) {
sum = a + b
return
}
延迟代码
假设一个函数打开一个文件,对其进行若干次读写,在这样的函数中经常有提前返回的地方。如果你这样做就需要关闭正在工作的文件描述符。这会产生下面这样的代码
func ReadWrite() bool {
file.Open("file")
if failureX {
file.Close()
return false
}
if failureY {
file.Close()
return false
}
file.Close()
return true
}
这里有许多重复的代码。为了解决这些,Go有了defer语句,在defer后指定的函数,会在函数退出前调用,上面的代码可以被改写成下面这样:
func ReadWrite() bool {
file.Open("file")
defer file.Close()
if failureX {
return false
}
if failureY {
return false
}
return true
}
可以将多个函数加入defer列表中。比如下面的代码输出4 3 2 1 0
for i := 0; i < 5; i++ {
defer fmt.Println(i)
}
延迟的函数按照后进先出(LIFO)的顺序执行。利用defer甚至可以修改返回值。
func aaa() (n int) {
defer func() {
n = 1
}()
return -1
}
注意,上面这个函数返回1而不是-1