6.1 介绍
Go的函数也可以作为一个参数,只要函数的返回值能对应上即可。
Go不支持函数重载,函数重载就是同名函数,有不同的形参不同的返回值。
现在Go支持泛型了,也就是支持多种类型的函数。
Go的函数可以返回多个值。
6.2 参数传递
传递给函数的参数,有两种:
- **值转递**,就是把变量的值复制一份副本传递给函数,函数内是对该副本进行操作。
- **引用传递**,就是把变量的指针复制一份副本传递给函数,函数内对该副本进行操作会影响到变量本身的值。
所以我们可以认为,引用传递其实也是值传递。
传递指针比传递值副本的消耗要低很多。
slice,map,interface,channel都是引用传递。
6.3 空白符
下划线_是Go中函数的空白符,用于接收函数的返回值,但是这个返回值后面用不到,但是Go中不用的量会编译出错。所以用空白符来接收。
实际上,空白符是一个只写不可读变量。空白符接收返回值,然后丢弃。
6.4 变长参数
变长参数就是一个函数的形参,可以接收任意个,不是固定指定数量。
package main
import (
"fmt"
)
func main() {
test(5, 6, 7, 8, 9, 10)
}
func test(s ...int) { //不指定参数数量
if len(s) == 0 {
fmt.Println("一个参数都没传进来")
} else {
for i, k := range s {
fmt.Print(i)
fmt.Println(k)
}
}
}
6.5 defer语句
defer语句是在函数返回之前最后执行的语句,一般是用来释放一些资源,以免忘记。
defer的位置可以任意放,但是defer语句的执行顺序是逆序的。
package main
import (
"fmt"
)
func main() {
fmt.Println("1")
defer fmt.Println("2")
fmt.Println("3")
}
//1 3 2
6.6 内置函数
内置函数不要导入包,就能直接使用。
名称 | 说明 |
---|---|
close() | 用于管道通信 |
len()、cap() | len() 用于返回某个类型的长度或数量(字符串、数组、切片、map 和管道);cap() 是容量的意思,用于返回某个类型的最大容量(只能用于数组、切片和管道,不能用于 map) |
new()、make() | new() 和 make() 均是用于分配内存:new() 用于值类型和用户定义的类型,如自定义结构,make 用于内置引用类型(切片、map 和管道)。它们的用法就像是函数,但是将类型作为参数:new(type)、make(type)。new(T) 分配类型 T 的零值并返回其地址,也就是指向类型 T 的指针。它也可以被用于基本类型:v := new(int)。make(T) 返回类型 T 的初始化之后的值,因此它比 new() 进行更多的工作。new() 是一个函数,不要忘记它的括号。 |
copy()、append() | 用于复制和连接切片 |
panic()、recover() | 两者均用于错误处理机制 |
print()、println() | 底层打印函数,在部署环境中建议使用 fmt 包 |
complex()、real ()、imag() | 用于创建和操作复数 |
6.7 递归函数
在函数体内,又调用自身,成为函数递归,最典型的就是阶乘计算和斐波那契数列。
package main
import "fmt"
func main() {
result := 0
for i := 0; i <= 10; i++ {
result = fibonacci(i)
fmt.Printf("fibonacci(%d) is: %d\n", i, result)
}
}
func fibonacci(n int) (res int) {
if n <= 1 {
res = 1
} else {
res = fibonacci(n-1) + fibonacci(n-2)
}
return
}
6.8 闭包
没有名称的函数成为匿名函数,如:func(a int, b int){}。
匿名函数不能像其他函数一样在main函数之外单独存在,有返回值的话,可以赋值给变量,然后通过变量来调用:
package main
import "fmt"
func main() {
result := func(a int, b int) int {
return a + b
}
fmt.Println(result(5, 6))
}
在函数内可以自调用,在函数后面传入参数:
package main
import "fmt"
func main() {
func(a int, b int) {
sum := a + b
fmt.Println(sum)
}(5, 6)
}
闭包 = 匿名函数 + 引用环境。
引用环境是什么意思呢?
package main
import "fmt"
func Bibao() func(int) int { //返回一个func(int)int类型
var n int = 10 //这个就是引用环境,它相当于C中的静态变量,会记忆上次的值
return func(i int) int { //这里是匿名函数
n = n + i
return n
}
}
func main() {
f := Bibao() //声明一个闭包
fmt.Println(f(1)) //10 + 1 = 11,参数是传到匿名函数中的
fmt.Println(f(1)) //11 + 1 = 12
}
多返回值也是可以的:
package main
import "fmt"
func Bibao(ss string) func(int, string) (int, string) { //返回一个func(int)int类型
var n int = 10 //这个就是引用环境,它相当于C中的静态变量,会记忆上次的值
return func(i int, s string) (int, string) { //这里是匿名函数
n = n + i
ss = ss + s
return n, ss
}
}
func main() {
f := Bibao("A") //声明一个闭包
fmt.Println(f(1, "a")) //11 Aa
fmt.Println(f(1, "b")) //12 Aab
}
闭包难以理解……….