概述
函数
是将一个或者一类问题包装为一个代码块,可以被多次调用,提高代码重用性。
Go 函数中声明、定义、参数、返回值这些基础概念,和其他编程语言中的一致,这里不再赘述。
语法规则
Go 函数支持单个返回值和多个返回值。
# 单个返回值
# 参数可省略
func 函数名称(参数 1 值 参数 1 类型, 参数 2 值 参数 2 类型 ...) 返回值类型 {
// do something
}
# 多个返回值,不指定名称
# 参数可省略
func 函数名称(参数 1 值 参数 1 类型, 参数 2 值 参数 2 类型 ...) (返回值 1 类型, 返回值 2 类型) {
// do something
}
# 多个返回值,指定名称
# 参数可省略
func 函数名称(参数 1 值 参数 1 类型, 参数 2 值 参数 2 类型 ...) (返回值 1 名称 返回值 1 类型, 返回值 2 名称 返回值 2 类型) {
// do something
}
例子
单个返回值
package main
import "fmt"
func max(x, y int) int {
if x > y {
return x
} else {
return y
}
}
func main() {
fmt.Printf("max = %d\n", max(1, 2))
}
// $ go run main.go
// 输出如下
/**
max = 2
*/
多个返回值,不指定名称
package main
import "fmt"
func getNumbers() (int, int, int) {
return 1, 2, 3
}
func main() {
x, y, z := getNumbers()
fmt.Printf("x = %d, y = %d, z = %d\n", x, y, z)
}
// $ go run main.go
// 输出如下
/**
x = 1, y = 2, z = 3
*/
多个返回值,指定名称
package main
import "fmt"
func getNumbers() (x int, y float64, z string) {
x = 1024
y = 3.14
z = "hello world"
return
}
func main() {
x, y, z := getNumbers()
fmt.Printf("x = %d, y = %.2f, z = %s\n", x, y, z)
}
// $ go run main.go
// 输出如下
/**
x = 1024, y = 3.14, z = hello world
*/
参数/返回值 类型相同简化
- • 当参数类型相同时,可以将类型放在最后一个参数变量后面
- • 当返回值类型相同时,可以将类型放在最后一个返回值变量后面
package mainimport "fmt"func getMaxAndMin(x, y, z int) (max, min int) { if x > y { max = x min = y if x < z { max = z } else if z < y { min = z } } else { max = y min = x if y < z { max = z } else if z < x { min = x } } return}func main() { max, min := getMaxAndMin(100, 200, 300) fmt.Printf("max = %d, min = %d\n", max, min)}// $ go run main.go// 输出如下 /** max = 300, min = 100
*/
递归函数
经典语录: 要想理解递归,首先要理解递归。
例子
阶乘
package main
import "fmt"
func factorial(n int) int {
if n == 0 {
return 1
}
return n * factorial(n-1)
}
func main() {
fmt.Printf("1 * 2 * 3 * 4 * 5 = %d\n", factorial(5))
}
// $ go run main.go
// 输出如下
/**
1 * 2 * 3 * 4 * 5 = 120
*/
闭包函数
闭包的概念参考扩展阅读-3。
例子
自增序列号生成器
package main
import "fmt"
// 自增序列号生成器
func incSeq() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
next := incSeq()
fmt.Printf("初始值 = %d\n", next())
for i := 1; i <= 5; i++ {
fmt.Printf("第 %d 次迭代后, 值 = %d\n", i, next())
}
}
// $ go run main.go
// 输出如下
/**
初始值 = 1
第 1 次迭代后, 值 = 2
第 2 次迭代后, 值 = 3
第 3 次迭代后, 值 = 4
第 4 次迭代后, 值 = 5
第 5 次迭代后, 值 = 6
*/
内部函数
使用的场景:在函数内部有很多重复性代码并且严重依赖上下文变量。此时可以在函数内部声明一个函数,专门用来处理重复性的代码。
例子
内部求和函数
package main
import "fmt"
func main() {
var sum func(...int) int // 声明 sum 函数
sum = func(numbers ...int) int { // 定义 sum 函数
total := 0
for _, num := range numbers {
total += num
}
return total
}
fmt.Printf("1 + 2 + 3 = %d\n", sum(1, 2, 3))
}
// $ go run main.go
// 输出如下
/**
1 + 2 + 3 = 6
*/
扩展阅读
- 1. 函数 - 维基百科 (https://zh.wikipedia.org/wiki/%E5%87%BD%E6%95%B0%E5%8E%9F%E5%9E%8B)
- 2. 递归 - 维基百科 (https://zh.wikipedia.org/wiki/%E9%80%92%E5%BD%92)
- 3. 闭包 - 维基百科 (https://zh.wikipedia.org/wiki/%E9%97%AD%E5%8C%85_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6))