大家好,欢迎来到IT知识分享网。
1.简介
- 函数:为完成某一功能的程序指令(语句)的集合
- 在Go中,函数分为自定义函数、系统函数
2.基本语法
func 函数名(形参列表) (返回值列表) {
函数体
return 返回值列表
}
3.递归
- 函数体内调用自己
package main
import "fmt"
func test(n int) {
if n > 2 {
n--
test(n)
}
fmt.Println("n = ", n)
}
func main() {
test(4)
}
- 执行一个函数时,就创建一个新的受保护的独立空间
- 函数的局部变量是独立的,不会相互影响
- 递归必须向退出递归的条件逼近,否则就会出现无限递归
- 当一个函数执行完毕,或者遇到
return
,就会返回,遵守谁调用就将结果返回给谁。
4.递归练习
- 1.求第N个斐波那契数列对应的值
package main
import "fmt"
func feb(n int) int {
if n <= 2 {
return 1
}
return test(n-1) + test(n-2)
}
func main() {
result := feb(6)
fmt.Println(result)
}
- 2.已知函数
f(1) = 3
,f(n) = 2*f(n-1) + 1
,求f(n)
的值
package main
import "fmt"
func test(n int) int {
if n == 1 {
return 3
}
return 2*test(n-1) + 1
}
func main() {
result := test(6)
fmt.Println(result)
}
- 3.有一堆桃子,猴子第一天吃了其中的一半,并在多吃了一个!以后每天猴子都吃其中的一半,然后再多吃一个。当到
第十天
准备吃时,发现只剩了1个桃子
。问题:最初总共多少个桃子
- 从上图可以看出其通项公式为:
(1 + f(n+1))* 2
,n代表天数
package main
import "fmt"
func getPeach(n int) int {
if n == 10 {
return 1
}
return (1 + getPeach(n+1)) * 2
}
func main() {
result := getPeach(1)
fmt.Println(result)
}
5.函数使用注意细节
-
1.函数的形参列表和返回值列表都可以是多个
-
2.形参列表和返回值列表都可以是值类型或引用类型
-
3.函数命名遵循标识符命名规则,首字母不能是数字,首字母如果是大写,则可以被其他文件或包调用,否则只能在当前文件被调用
-
4.函数的变量是局部的,函数外不生效
-
5.基本类型和数组默认都是值传递,即进行值拷贝,在函数内修改,不会影响到原来的值
-
6.如果希望函数内的变量能修改函数外的变量,可以传递变量的地址
&
,函数内以指针方式操做变量 -
7.Go函数不支持重载(即一个包下不允许存在同名的函数)
-
8.在Go语言中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量,通过该变量可以对函数进行调用
-
9.函数既然是一种数据类型,因此在Go语言中,函数可以作为形参,并且调用
package main import "fmt" func test(myFunc func(int, int) int, num1, num2 int) int { return myFunc(num1, num2) } func getSum(a, b int) int { return a + b } func main() { resp := test(getSum, 1, 2) fmt.Println(resp) }
-
10.为了简化数据类型定义,Go语言支持自定义数据类型
- 基本语法:
type myInt int
,myInt就可以当作int类型来使用,但不完全一致,不能将一个myInt类型的值直接赋值给int类型的变量,需要使用int()来强转一下。 - 也可以使用type来定义一个函数类型
package main import "fmt" type myFuncType func(int, int) int func test(myFunc myFuncType, num1, num2 int) int { return myFunc(num1, num2) } func getSum(a, b int) int { return a + b } func main() { resp := test(getSum, 1, 2) fmt.Println(resp) }
- 基本语法:
-
11.支持对函数返回值命名
package main import "fmt" type myFuncType func(int, int) int func test(myFunc myFuncType, num1, num2 int) int { return myFunc(num1, num2) } // 将函数返回值重命名为sum func getSum(a, b int) (sum int) { sum = a + b return } func main() { resp := test(getSum, 1, 2) fmt.Println(resp) }
-
12.使用
_
来忽略返回值 -
13.Go支持可变参数
参数名 ...
,必须放在参数最后位置package main import "fmt" func getSum(args ...int) int { sum := 0 for i := 0; i < len(args); i++ { sum += args[i] } return sum } func main() { resp := getSum(1, 2, 3) fmt.Println(resp) }
6.init函数
- 每个源文件都可以包含一个init函数,该函数会在
main
函数前执行,被Go运行框架调用。 - 通常在init函数中完成初始化工作,每个文件都可以有一个init函数
package main import "fmt" func init() { fmt.Println("init函数自动执行") } func main() { fmt.Println("开始执行主函数") }
- 如果一个文件中同时包含
全局变量
、init函数
、main函数
,则执行顺序为:全局变量 > init > main
package main import "fmt" var money = test() func test() int { fmt.Println("test()") return 100 } func init() { fmt.Println("init函数自动执行") } func main() { fmt.Println("开始执行主函数...money=", money) } // test() // init函数自动执行 // 开始执行主函数...money= 100
7.匿名函数
- Go支持匿名函数,如果我们某个函数只希望使用一次,可以考虑使用匿名函数,匿名函数可以实现多次调用
- 示例一:在定义时就调用
package main import "fmt" func main() { res := func(n1, n2 int) int { return n1 + n2 }(10, 20) fmt.Println("result =", res) }
- 示例二:将匿名函数赋值给一个变量(函数变量),再通过该变量来调用匿名函数
package main import "fmt" func main() { sum := func(n1, n2 int) int { return n1 + n2 } res := sum(10, 20) fmt.Println("result =", res) }
- 示例三:全匿名函数,将函数赋值给一个全局变量,就成为一个全局函数,可以在程序有效
package main import "fmt" var multi = func(n1, n2 int) int { return n1 * n2 } func main() { res := multi(10, 20) fmt.Println("result =", res) }
8.闭包
-
闭包就是一个
函数
和与其相关的引用环境
组合的一个整体 -
闭包必须满足三个条件:
1、必须有一个内嵌函数
2、内嵌函数必须引用外部函数中的变量
3、外部函数返回值必须是内嵌函数 -
闭包可以使得变量常驻内存
package main import "fmt" func Closure() func(int) int { var n1 = 10 return func(n2 int) int { n1 = n1 + n2 return n1 // return n1 + n2 // 这样的结果完全不一样, n1 = n1 + n2会修改局部变量n1的值,如果直接返回n1 + n2,则不会修改局部变量n1的值 } } func main() { res := Closure() fmt.Println("result =", res(30)) // 40 fmt.Println("result =", res(31)) // 71 }
-
nodejs
function closure() { var a = 10; function inner(b) { a = a + b; return a } return inner; } var func = closure(); console.log(func(30)); // 40 console.log(func(31)); // 71
-
python
# 变量 a 对于 inner来说是外部变量,因此不能直接进行修改 def closure(): a = 10 def inner(b): a = a + b return a return inner # UnboundLocalError: local variable 'a' referenced before assignment # 但对于inner来说是可以直接使用的 def closure(): a = 10 def inner(b): return a + b return inner # 必须使用 nonlocal 来修改变量a的作用域,从而对其进行操做 def closure(): a = 10 def inner(b): nonlocal a a = a + b return a return inner func = closure() print(func(30)) # 40 print(func(31)) # 71
-
案例:使用闭包方式,实现检查文件后缀名是否为
.jpg
,如果不是,则内部实现拼接.jpg
,否则直接返回package main import ( "fmt" "strings" ) func Closure(endFix string) func(string) string { return func(name string) string { if strings.HasSuffix(name, endFix) { return name } return name + endFix } } func main() { res := Closure(".jpg") fmt.Println("result =", res("aaa.jpg")) fmt.Println("result =", res("bbb")) }
9.函数参数传递
- 值类型:基本数据类型:int系列、float系列、bool、string、数组、结构体
- 引用类型:指针、slice切片、map、管道chan、interface等
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30437.html