2022-4-16 实习Day16

1、机构、客户测试数据部分不显示,配置修改 –2小时 100%
2、新一代贸金业务操作手册修改 –2.5小时 80%
3、客户账户管理打开报错,调试,寻找问题。–1.5小时 40%

Golang编程学习(part 11)

1、函数的return语句

① Go函数支持返回多个值,这一点是其他编程语言没有的。【案例演示】

func 函数名(形参列表) (返回值类型列表){

​ 语句…

​ return 返回值列表

}

【1】如果返回多个值,在接收时,希望忽略某个返回值,则使用_符号表示占位忽略

【2】如果返回值只有一个,(返回值类型列表) 可以不写()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

func main() {

i, j := getSumAndSub(30, 20)
fmt.Println(i, j)

// 希望忽略某个返回值,则使用 _ 符号表示占位忽略
k, _ := getSumAndSub(30, 20)
fmt.Println(k)

}

func getSumAndSub(n1 int, n2 int) (int, int) {
sum := n1 + n2
sub := n1 - n2
return sum, sub
}

2、函数的递归调用

一个函数在函数体内又调用了本身,我们称为递归调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import "fmt"

func test(n int) {
if n > 2 {
n--
test(n)
}

fmt.Println("n=", n)
}

func main() {
test(4)
}

n= 2
n= 2
n= 3

3、递归调用的总结

① 执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)
② 函数的局部变量是独立的,不会相互影响
③ 递归必须向递归的条件逼近,否则就是无限递归,死┏┛墓┗┓…(((m -__-)m龟了
④ 当一个函数执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当函数执行完毕或者返回时,该函数本身也会被系统销毁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

1:斐波那契数
请使用递归的方式,求出斐波那契数 1,1,2,3,5,8,13...
给你一个整数 n,求出它的斐波那契数是多少? 思路:
1) 当 n == 1 || n ==2 , 返回 1
2) 当 n >= 2, 返回 前面两个数的和 f(n-1) + f(n-2)

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

//用for循环的方式
func Fbnq(n int) {
var temp1 = 1
var temp2 = 1
for i := 1; i <= n; i++ {
if i == 1 || i == 2 {
fmt.Println(1)
} else {
//只要记录上一个数和当前数即可
temp := temp1
temp1 = temp2
temp2 = temp1 + temp
fmt.Println(temp2)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
3:猴子吃桃子问题
有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!以后每天猴子都吃其中的一半,然后再多吃一个。当到第十天时,想再吃时(还没吃),发现只有 1 个桃子了。问题:最初共多少个桃子?
思路分析:
1) 第 10 天只有一个桃子
2) 第 9 天有几个桃子 = (第 10 天桃子数量 + 1) * 2
3) 规律: 第 n 天的桃子数据 peach(n) = (peach(n+1) + 1) * 2
func chi(n int) int {
if n == 10 {
return 1
} else {
return 2 * (chi(n+1) + 1)
}
}

4、函数使用的注意事项和细节讨论

① 函数的形参列表可以是多个,返回值列表也可以是多个
② 形参列表和返回值列表的数据类型可以是值类型和引用类型
③ 函数的命名遵守标识符命名规范,首字母不能是数字,首字母大写表示该函数可以被本包文件和其他包文件使用,类似public,首字母小写,只能被本包文件使用,其他包文件不能使用,类似private
④ 函数中的变量是局部的,函数外不生效
⑤ 基本数据类型和数组默认都是值传递,即进行值拷贝。在函数内修改,不会影响到原来的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func test(n int) {
n = n + 10
fmt.Println(n)
}
func main() {
num := 20
test(num)
fmt.Println(num)
}

30
20
⑥ 如果希望函数内的变量能够修改函数外的变量(指的是默认以值传递方式的数据类型),可以传入变量的地址&,函数内以指针的方式操作变量。从效果上看类似引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func test(n *int) {
*n = *n + 10
fmt.Println(*n)
}
func main() {
num := 20
test(&num)
fmt.Println(num)
}

30
30
⑦ Go函数不支持函数重载(因为可以通过一个函数来实现重载的效果)
⑧ 在Go中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量了。通过该变量可以对函数调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func getSum(a int, b int) int {
return a + b
}
func main() {

a := getSum
fmt.Printf("a的类型%T,getSum的类型%T\n", a, getSum)

res := a(10, 20)
fmt.Println("res=", res)
}

a的类型func(int, int) int,getSum的类型func(int, int) int
res= 30
⑨ 函数既然是一种数据类型,因此在Go中,函数可以作为形参,并且调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func myFun(funVar func(int, int) int, a int, b int) int {
return funVar(a, b)
}
func getSum(a int, b int) int {
return a + b
}
func main() {
res := myFun(getSum, 10, 20)
fmt.Print(res)
}
30
⑩ 为了简化数据类型定义,Go支持自定义数据类型

基本语法:type 自定义数据类型名 数据类型 (理解:相当于一个别名)

案例:type myInt int(这时myInt就等价于int来使用了)

案例:type mySum func(int,int) int(这时mySum就等价一个函数类型 func(int,int) int)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import "fmt"

func getSum(a int, b int) int {
return a + b
}
func main() {
// 给int取了别名,在go中myInt和int虽然都是int类型,但是go认为他们两个是不同的类型
type myInt int
var num1 myInt
var num2 int
num1 = 10
num2 = 10
// 注意这里比较时需要显示转换,go认为myInt和int两个类型
fmt.Println(num1 == myInt(num2)) //true

}
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"

// 这时候myFunType 就是 func(int, int) int
type myFunType func(int, int) int

// 函数既然是一种数据类型,因此在Go中函数可以作为形参,并且调用
func myFun2(funvar myFunType, num1 int, num2 int) int {
return funvar(num1, num2)
}

func getSum(a int, b int) int {
return a + b
}
func main() {
res := myFun2(getSum, 10, 30)
fmt.Println("res=", res)
}
res= 40

11 支持对函数返回值命名(传统不带命名的要注意返回值顺序)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

// 支持对函数返回值命名
func getSumAndSub(n1 int, n2 int) (sum int, sub int) {
sum = n1 + n2
sub = n1 - n2
return
}
func main() {
i, j := getSumAndSub(18, 9)
fmt.Println(i, j)
}

12 使用 _ 标识符,忽略返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

// 支持对函数返回值命名
func getSumAndSub(n1 int, n2 int) (sum int, sub int) {
sum = n1 + n2
sub = n1 - n2
return
}
func main() {
i, _ := getSumAndSub(18, 9)
fmt.Println(i)
}

13 Go支持可变参数(切片可以理解为动态数组)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 支持0到多个参数
func sum(args... int) int{}

//支持1到多个参数
func sum(n int,args... int) int{}

// args是slice切片,通过args[index]可以访问到各个值
// 如果一个函数的形参列表中有可变参数,则可变参数需要放在形参列表最后
func sum(args... int) int{
sum:=0
for i:=0;i<len(args);i++{
sum+=args[i]
}
return sum
}