函数

函数概述

  • 函数是对一段能够重复使用的代码的封装
  • 函数的参数定义了外界给函数输入的数据
  • 函数的返回值定义了函数给外界输出的数据
  • Go语言函数支持不定长参数和多个返回值

函数的调用机制

介绍:为了让大家更好的理解函数调用过程, 看两个案例,并画出示意图,这个很重要

  1. 传入一个数+1

(1) 在调用一个函数时,会给该函数分配一个新的空间,编译器会通过自身的处理让这个新的空间
和其它的栈的空间区分开来

(2) 在每个函数对应的栈中,数据空间是独立的,不会混淆
(3) 当一个函数调用完毕(执行完毕)后,程序会销毁这个函数对应的栈空间。
2) 计算两个数,并返回

@函数定义和调用

1
2
3
4
5
6
//定义函数
func sayHello() {
fmt.Println("fuck off!")
}
//调用函数
sayHello()

@函数参数 无参函数

1
2
3
func add0() {
fmt.Println("没参数,add你妹啊")
}

带参函数

1
2
3
4
func add1(a int) {
fmt.Println("收到一个参数", a)
fmt.Println("一个参数,add你妹啊")
}

多个参数

1
2
3
4
5
6
7
8
9
10
11
12
//多个参数
func addm1(a int, b int) {
fmt.Println("加和是", a+b)
}
//类型相同的参数被合写在一起了
func addm2(a, b int) {
fmt.Println("加和是", a+b)
}
//类型不同的参数
func addm3(a, b int, c float32) {
fmt.Println("加和是", float32(a)+float32(b)+c)
}

不定长参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func addx(x ...int) {
//参数的长度是 5
fmt.Println("参数的长度是", len(x))
//参数的类型是[]int
fmt.Printf("参数的类型是%T\n", x)
var result = 0
//遍历不定长参数
for i, v := range x {
fmt.Println(i, v)
result += v
}
//加和是 15
fmt.Println("加和是", result)
}

@函数返回值 无返回值

1
2
3
4
//无返回值
func sub0(a, b int) {
fmt.Println("相减的结果是", a-b)
}

有返回值

1
2
3
4
5
6
7
8
9
10
//有返回值
func sub11(a, b int) int {
fmt.Println("相减的结果是", a-b)
return a - b
}
func sub12(a, b int) (ret int) {
fmt.Println("相减的结果是", a-b)
ret = a - b
return
}

多个返回值

1
2
3
4
5
6
7
8
9
10
11
//多个返回值
func subm1(a, b int) (int, string) {
fmt.Println("相减的结果是", a-b)
return a - b, "你妹"
}
func subm2(a, b int) (ret int, remark string) {
fmt.Println("相减的结果是", a-b)
ret = a - b
remark = "你妹"
return
}

递归调用快速入门

代码 1

上面代码的分析图:

代码 2

对上面代码分析的示意图:

函数递归需要遵守的重要原则:

  1. 执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)
  2. 函数的局部变量是独立的,不会相互影响
  3. 递归必须向退出递归的条件逼近,否则就是无限递归,死龟了:)
  4. 当一个函数执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当函数执行完毕或者返回时,该函数本身也会被系统销毁

递归课堂练习题

题 1:斐波那契数

请使用递归的方式,求出斐波那契数 1,1,2,3,5,8,13…
给你一个整数 n,求出它的斐波那契数是多少?
思路:

  1. 当 n == 1 || n ==2 , 返回 1
  2. 当 n >= 2, 返回 前面两个数的和 f(n-1) + f(n-2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
请使用递归的方式,求出菲波拉契数1,1,2,3,5,8,13...
给你一个整数n,求出它的菲波拉契数是多少?
*/

func fbn(n int) int {
if (n == 1 || n ==2){
return 1
}else{
retrun fbn(n -1) + fbn(n -2)
}
}

func main(){
res := fbn(3)
//测试
fmt.Println("res=:",res)
fmt.Println("res=:",4)//3
fmt.Println("res=:",5)//5
fmt.Println("res=:",6)//8
}

题 2:求函数值

已知 f(1)=3; f(n) = 2*f(n-1)+1;
请使用递归的思想编程,求出 f(n)的值?
思路:

直接使用给出的表达式即可完成

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
import("fmt")

/*
题2:求函数值已知 f(1)=3; f(n) = 2*f(n-1)+1; 请使用递归思想编程,求出f(n)的值
*/
func f(n int) int {
if n == 1 {
return 3
}else {
return 2* f(n-1)+1
}
}

func main(){

//测试一下
fmt.Println("f(1)",f(1))
fmt.Println("f(5)",f(5))

}

题 3:猴子吃桃子问题

有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!以后每天猴子都吃其中的一半,然后
再多吃一个。 当到第十天时 , 想再吃时 ( 还没吃 ) , 发现只有 1 个桃子了。问题:最初共多少个桃子?

思路分析:

  1. 第 10 天只有一个桃子
  2. 第 9 天有几个桃子 = (第 10 天桃子数量 + 1) * 2
  3. 规律: 第 n 天的桃子数据 peach(n) = (peach(n+1) + 1) * 2

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import("fmt")
func peach(n int) int {
if n > 10 || n < 1 {
fmt.println("输入的天数不对")
return 0//返回0表示满意得到正确的数量
}
if n == 10{
return 1
}else{
return (peach(n + 1) + 1) *2
}
}

func main(){

fmt.Println("第1天桃子数量=:",peach(1))//1534
}