Function
函数定义的方式:func plus(a int, b int) int {}
package main
import "fmt"
func plus(a int, b int) int {
return a + b
}
// 相同类型的入参可以这样定义
func plusPlus(a, b, c int) int {
return a + b + c
}
func main() {
res := plus(1, 2)
fmt.Println("1+2 =", res)
res = plusPlus(1, 2, 3)
fmt.Println("1+2+3 =", res)
}
多返回值
多返回值是Go的一大特色之一,非常有用。
package main
import "fmt"
func vals() (int, int) {
return 3, 7
}
func main() {
a, b := vals()
fmt.Println(a)
fmt.Println(b)
_, c := vals()
fmt.Println(c)
}
可变参数函数
这里的可变是指入参长度可变。可变参数函数的入参类型为:...类型:
package main
import "fmt"
// 传入之后,nums的实际类型就是[]int
func sum(nums ...int) {
fmt.Print(nums, " ")
total := 0
for _, num := range nums {
total += num
}
fmt.Println(total)
}
func main() {
// 调用时只需要按常规方式调用
sum(1, 2)
sum(1, 2, 3)
// 也可以将已经是slice的结构传入,但要在其后面加...(真神奇)
nums := []int{1, 2, 3, 4}
sum(nums...)
}
上面的程序输出:
$ go run variadic-functions.go
[1 2] 3
[1 2 3] 6
[1 2 3 4] 10
Closure闭包
这个翻译实在拗口。Go 支持可以形成闭包的匿名函数。当你想内联定义一个函数而不必命名时,匿名函数很有用。有些朋友已经想到了,没错,跟lambda有点像。闭包本质上是一个结构体,包含了函数入口和函数内定义的变量。
package main
import "fmt"
func intSeq() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
nextInt := intSeq()
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
newInts := intSeq()
fmt.Println(newInts())
}
上面的程序输出:
$ go run closures.go
1
2
3
1
闭包,到底包住了什么呢?比如上面的例子,包住了一个“函数变量i”,每个intSeq函数都捕捉着自己的i,在每次调用函数时,i都实现有状态变化。神奇,这搞出了类成员变量的感觉。
递归
递归两要素:1. 自己调自己;2. 有终止条件。
package main
import "fmt"
func fact(n int) int {
// 递归终止条件
if n == 0 {
return 1
}
return n * fact(n-1)
}
func main() {
fmt.Println(fact(7))
var fib func(n int) int
// 闭包也可以是递归的,但这需要var在定义闭包之前用类型显式声明闭包
fib = func(n int) int {
if n < 2 {
return n
}
return fib(n-1) + fib(n-2)
}
// 在main内部来说,fib就是一个闭包
fmt.Println(fib(7))
}
上面的程序输出:
$ go run recursion.go
5040
13
每日一Tip
Go的函数非常灵活,结合闭包的使用,可以实现类似Java的lambda效果。