函数名 | 功能 |
append | 把元素添加到slice,返回修改后的slice |
copy | 复制slice,返回复制的数目 |
delete | 从map中删除key对应的value |
panic | 停止常规的goroutine |
recover | 允许程序定义goroutine的panic动作 |
make | 用于slice,map,channel的创建 |
real | 返回complex的实部 |
imag | 返回complex的虚部 |
new | 返回指定类型零值的指针 |
cap | 返回容量(capacity) |
close | 关闭channel |
len | 返回 长度 |
2.1 定义格式
func FuncName(/*参数列表*/)(a type1,b type2/*返回类型*/){
/*函数体*/
return v1, v2 //返回多个值
}
注:a.函数由关键字func开始声明,函数声明告诉了编译器函数的名字,返回参数和类型
b.FuncName即函数名称,根据约定:函数名首字母小写只能再包内使用;大写可以被包外使用;
c.返回类型:
1.上面返回值声明了名变量名a和b(命名返回参数),变量名不是必须需要,可以只有类型没有变量名;
2.如果只有一个返回值且不声明返回值变量,可以省略变量名和返回值的括号,保留变量类型;
3.如果没有返回值,那么就直接省略最后的返回信息。如果有返回值,那么必须再函数的内部添加return语句。
2.2 函数参数
2.2.1 参数分类
参数 | 定义 | 二者关系 |
形式参数 | 函数定义中命名的参数 | 函数调用时,主调函数把实参的值传送给被调函数的形参,从而实现主调函数向被调函数的数据传送。 |
实际参数 | 调用有惨函数时,函数名后面括号中的参数 |
注:a.形参只有在被调用时才分配内存单元,调用结束后,即刻释放所分配的内存单元。
b.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,再进行函数调用时,他们都必须具有确定的值,以便把这些值传递给形参;
c.形参和实参在数量上、类型上、顺序上应严格一致,否则会发生类型不匹配的错误;
d.函数调用中发生的数据传送是单向的,即只能把实参的值传递给形参,而不能把形参的值反向地传递给实参,因此在函数调用过程中,形参的值发生改变,而实参的值不会变化。
2.2.2参数传递
类型 | 定义 |
值传递 | 调用函数时将实际参数复制一份传递到函数中,在函数中对参数进行修改,经不会影响到实际参数。 |
引用传递 | 在调用函数时将实际参数的地址(指针)传递到函数中,再函数中对参数所进行的修改,将影响到实际参数 |
Demo
package main
import "fmt"
func swap1(a1, b1 int) {
//值传递
a1, b1 = b1, a1
}
func swap2(c1, d1 *int) {
//引用传递:c1,d1为指针变量
*c1, *d1 = *d1, *c1
}
func main() {
var a int = 2
var b int = 1
swap1(a, b)//a,b的值传递给a1,b1
fmt.Printf("值传递:a = %d, b = %d\n", a, b)
var c int = 2
var d int = 1
swap2(&c, &d)//c,d的地址传递给c1,d1
fmt.Printf("指针传递:c = %d, d = %d\n", c, d)
}
2.3 自定义函数种类
类型 | 定义 |
无参无返回值 | 既没有传入参数,也没有返回值 |
有参数,无返回值 (普通参数、不定参数) |
有传入的参数,没有返回值 |
无参有返回值 (一个返回值、多个返回值) |
没有传入参数,有返回值的函数 |
有参有返回值 | 有传入的参数,有返回值 |
Demo
package main
import "fmt"
func test1() {
fmt.Println("无参无返回值")
}
func test2(v1, v2 int) {
fmt.Printf("有参(普通参数)无返回值:v1=%d, v2=%d\n", v1, v2)
}
func test3(args ...int) { //不定参数,args本质是一个切片
fmt.Println("有参(不定参数)无返回值:", args)
}
func test4() (value int) {
value = 250
return value
}
func test5() (a int, str string) {
b := 250
c := "aha"
return b, c
}
func minAndMax(num1 int, num2 int) (min int, max int) {
if num1 > num2 {
min = num2
max = num1
} else {
max = num2
min = num1
}
return
}
func main() {
test1()
test2(11, 22)
test3()
test3(1)
test3(1, 2, 3, 4)
v4 := test4()
fmt.Println("无参有返回值(一个返回值) ", v4)
_, v5 := test5()
fmt.Println("无参有返回值(多个返回值) ", v5)
min, max := minAndMax(33, 22)
fmt.Printf("有参有返回值:min = %d, max = %d\n", min, max)
}
类型 | 定义 |
局部变量 | 参数即函数内部定义的变量 |
全局变量 | 函数外部定义的变量 |
a.在同一个作用域内,就近访问最近的变量
b.如果作用域没有声明此变量,则访问全局变量
c.全局变量也没有,则报错
Demo
package main
import "fmt"
var a int
func test01(a float32) {
fmt.Printf("a type = %T\n", a)
}
func main() {
fmt.Printf("a type = %T\n", a)
var a uint8
fmt.Printf("a type = %T\n", a)
test01(3.14)
test02()
}
func test02() {
fmt.Printf("a type = %T\n", a)
}
4.1
类型 | 定义 | 两者关系 |
匿名函数 | 没有定义函数名的函数 | 在Go语言中所有匿名函数都是闭包 |
闭包 | 能够读取其他函数内部常量、变量的函数 |
a.闭包就是通过匿名函数“捕获”和它在同一作用域的其他常量和变量
b.当闭包被调用的时候,不管再程序什么地方调用,闭包都能 使用这些常量或变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,只要闭包还在使用它,这些变量就会存在。
4.2
定义 | 描述 |
直接调用 | func(){ }() |
声明函数类型后调用 | var f1 func()=func(){ } f1() |
自动推导类型 | f2:=func(){ } f2() |
直接调用并传参(有参有返回值, 返回值赋值给了一个变量) |
v:=func(a,b int)(result int){ result = a+b return }(1,1) |
Demo
package main
import "fmt"
func square() func() int { //返回值是匿名函数
var x int
return func() int { //匿名函数
x++ //闭包通过此匿名函数“捕获”了函数square()定义的变量x
return x * x
}
}
func main() {
s := square() //square()调用后为一匿名函数,则变量s为匿名函数
fmt.Println(s())
fmt.Println(s()) //匿名哈数还在被调用,它内部的变量x仍然没有被释放
fmt.Println(s())
fmt.Println(s())
}
5.1 defer的操作使用
序号 | 描述 | 示例 |
1 | 延迟一个自定义函数的调用 | defer A() |
2 | 延迟第三方包中的函数的执行 | defer fmt.Pprintln("Hello") |
3 | 延迟匿名函数的调用 | defer func(){ fmt.Println("Hello") }() |
defer 语句只能出现在函数的内部。
Demo
package main
import "fmt"
func main() {
a, b := 10, 20
defer func(x int) { // a以值传递方式传给x
fmt.Println("defer:", x, b) // b闭包引用,由于延迟调用,获取改变和的b
}(a)
a += 10
b += 100
fmt.Printf("a = %d, b = %d\n", a, b)
}
运行结果:
a = 20, b = 120
defer: 10 120
5.2 多个defer
如果一个函数中有多个defer语句,他们会以LIFO(后进先除)的顺序执行,哪怕函数或某个延迟调用发生错误,这些调用依旧会被执行。
package main
import "fmt"
func test(x int) {
fmt.Println(100 / x)
}
func main() {
defer fmt.Println("aaaaaaaa")
defer fmt.Println("bbbbbbbb")
defer test(10)
defer fmt.Println("cccccccc")
}
递归函数就是再运行过程中不断地调用自己。
语法格式
func recursion() {
recursion()
}
func main() {
recursion()
}
Demo
阶乘
package main
import "fmt"
func factorial(n int) (result int) {
if n > 0 { //结束条件,递归必须有终结条件,否则一直递归下去会造成堆栈溢出
result = n * factorial(n-1)
return result
}
return 1
}
func main() {
var i = 15
fmt.Printf("%d的阶乘是: %d\n", i, factorial(i))
}
斐波那契数列
package main
import "fmt"
func fibonacci(n int) int {
if n < 2 {
return n
}
return fibonacci(n-2) + fibonacci(n-1)
}
func main() {
var i int
for i = 1; i < 10; i++ {
fmt.Printf("%d\t", fibonacci(i))
}
}