✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑
文章目录
Go语言中的函数
1. 什么是函数
在Go语言中,函数(Function)是基本的代码块,用于执行特定的任务,并通过输入参数和返回值与外部环境进行交互。
函数是一段具有特殊功能的、可重用的语句组。(将代码封装起来)
特点:可以反复调用,提高代码的复用性,提高开发效率,便于维护管理
- 函数就是一段代码的集合
- go语言中至少要有一个 main函数
- 函数需要有一个名字,独立定义的情况下。见名知意
- 函数可能需要有一个结果,也可能没有
go语言中,函数和方法完全是不一样的东西,面向对象里面才有方法
2. 函数的定义
Go语言中,使用func关键字开始,后跟函数名、参数列表(参数名和参数类型)、返回值类型(如果有的话),以及函数体(用大括号{}包围的语句块)。
基本语法如下:
funcfunctionName(parameters) returnType {// 函数体 return returnValue // 可选 }
3. 函数的调用
在Go语言中,函数的调用非常直接,只需要使用函数名加上括号,如果有参数,加上必要的参数即可。如果函数有返回值,可以将返回值赋给变量,或者直接使用(如果不需要处理返回值)。
4. 常见函数类型
1、无参无返回值函数
无返回值函数,不用指定返回值类型
package main
import"fmt"// 定义函数// 1、无参、没有返回值函数funcadd(){
fmt.Println("计算加法函数")}funcmain(){add()}
2、无参有返回值函数
// 2、无参数有返回值函数
//需要指定函数返回值类型,并且用return将返回值返回//在调用处用变量接收funcadd()int{return3}
3、有参有一个返回值函数
// 有参,有一个返回值函数//指定参数类型,和返回值类型funcadd(x int, y int)int{return x + y
}
4、有参有多个返回值函数
//4、有参,有多个返回值函数//需要指明参数类型,和多个返回值类型,多个返回值返回类型需要用括号括起来//多个返回值用逗号隔开//调用的时候,用多个变量接收返回值funcadd(x int, y int)(int,int){return x + y, y
}
给出两个数,得到其中较大者
package main
import"fmt"funcmain(){
num :=max(3,5)
fmt.Println(num)}// 定义比较大小函数funcmax(x, y int)int{var result intif x > y {
result = x
}else{
result = y
}return result
}
5、定义函数时给返回值命名
返回多个值,需要括号,需要表明返回值类型,返回值也可以命名。命名后,最后返回只需写return即可,也可以根据命名的返回值return。
直接调用return不带结果,那么则返回 函数返回值定义的顺序进行结果返回。
package main
import"fmt"funcmain(){
a, b :=getresult(5,6)
fmt.Println(a, b)}// 要求:给出长方形的两个变长,得出长方形的周长和面积// 可以在定义函数时,指定函数的返回值变量名funcgetresult(x, y int)(zhouchang, mianji int){
zhouchang =(x + y)*2
mianji = x * y
//函数定义处返回值命名了,return时要么和命名的变量名一样,要么可以直接不写//return zhouchang, mianjireturn}
return的结果值命名和定义函数返回值的命名无关.
5. 可变参数函数
当一个函数的参数类型确定,参数的个数不确定,可以使用可变参数
可变参数函数是一种可以接受可变数量的参数的函数,通过使用三个省略号…来声明可变参数,可以使得函数接受任意数量的相同类型的参数。
可变参数函数在调用时,传递给函数的参数会被当作一个切片传递给函数。在函数内部,可以使用切片来访问和操作这些参数。
类似于python中的普通收集参数
语法格式
funcfunctionName(参数名 ... 参数类型) returnType {// 函数体 return returnValue // 可选 }
这里面参数名表示的参数是一个切片,可以循环取出里面的值
如果函数有其他指定的参数,可变参数必须放在函数的最后一个参数位置。比如下面的可变参数nums,放在函数的最后一个参数位置
package main
import"fmt"funcmain(){
fmt.Println(getSum(10,20,30))}// 可变参数: 一个函数的参数类型确定,参数的个数不确定,可以使用可变参数// 可变参数如果有多个参数必须放在最后一个参数// 求和 , 参数是可变的,intfuncgetSum(nums ...int)int{
sum :=0
fmt.Println("可变参数的长度为:",len(nums))//循环通过下标取出nums中的值for i :=0; i <len(nums); i++{
fmt.Println("可变参数下标", i,":", nums[i])// 取出来//sum = sum + nums[i]
sum += nums[i]}return sum
}// 接收多个参数 nums 可变参数// 使用下标来接收,下标是从0开始的// nums : 100,200,300,400,500// nums[0] = 100// nums[1] = 200// nums[2] = 300// 了解传递了多少个数字 len()函数,获取可变参数的长度
6. 函数的参数传递
Go语言默认使用按值传递,这意味着传递给函数的参数是原始数据的副本。对副本的任何修改都不会影响原始数据。但是,如果传递的是指针,则可以通过指针修改原始数据。
调用函数时,可以通过两种方式来传递参数:一种是值传递,另一种是引用传递。
值传递是指在调用函数时,将实际参数复制一份传递到函数中。这样,在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递是指在调用函数时,将实际参数的地址传递到函数中。这样,在函数中对参数所进行的修改,将影响到实际参数。
默认情况下,Go语言使用的是值传递,即在调用过程中不会影响到实际参数。
1、值传递
示例:按值传递
package main
import"fmt"funcincrement(x int){
x++// 只修改了副本}funcmain(){
y :=5increment(y)
fmt.Println(y)// 输出: 5,因为y的值没有被修改}
2、引用传递
示例:按引用传递(通过指针)
引用传递,在定义函数时和参数操作时,都要在参数类型或参数名的前面加*
package main
import"fmt"funcincrement(x *int){*x++// 修改了原始数据}funcmain(){
y :=5increment(&y)
fmt.Println(y)// 输出: 6,因为y的值被修改了}
7. 函数中作用域
函数作用域
局部变量
1、函数内部定义的变量,只能在函数内部调用
全部变量(全局变量)
1、函数外部定义的变量,默认我们定义在上面,方便文件统一查看和管理全局变量
定义一个只在 if中生效的变量 if 临时变量(a,b := 1,2);条件判断{}
小作用域可以用到大作用域中的变量,反之则不行。
对于很多一次性的变量,都可以这么写
package main
import"fmt"// 函数作用域// 局部变量// 1、函数内部定义的变量,只能在函数内部调用// 全部变量(全局变量)// 1、函数外部定义的变量,默认我们定义在上面,方便文件统一查看和管理全局变量var num int=1funcmain(){
temp :=100// 定义一个只在 if 中生效的变量 if 临时变量(a,b := 1,2);条件判断{}// 小作用域可以用到大作用域中的变量,反之则不行。// 对于很多一次性的变量,都可以这么写// 生产中我们尽量优先使用局部变量if a :=1; a <=10{
fmt.Println(temp)
fmt.Println(num)
fmt.Println(a)// 就近原则if a :=2; a <=10{
fmt.Println(a)}}
fmt.Println(num)}funcf1(){
fmt.Println(num)}funcf2(){}
8. 递归函数
在Go语言中,可以使用递归函数,也就是一个函数在自身内部调用自身。
递归函数通常用于解决需要重复执行相同操作的问题,比如:计算阶乘、斐波那契数列等。
需要注意的是,递归函数必须有一个终止条件。否则,会无限递归下去,导致栈溢出甚至程序崩溃。
package main
import"fmt"/*
定义:一个函数自己调用自己,就叫做递归函数
注意:递归函数需要有一个出口,逐渐向出口靠近,没有出口就会形成死循环。
*/funcmain(){// overflows 栈溢出
sum :=getSum2(10)
fmt.Println(sum)}funcgetSum2(n int)int{//fmt.Println(n)//递归出口if n ==1{return1}//将自己返回,自己调用自己returngetSum2(n-1)+ n
}// 假设 getSum(5)// 求和 sum 1 + 2 + 3 + 4 + 5// getSum(5)☟=15// getSum(4)☟=10 + 5// getSum(3)☟=6 + 4// getSum(2)☟=3 + 3// // getSum(1)=1 + 2
如果计算的数太大,会造成内存溢出
fatal error: stack overflow
递归步骤分析
递归计算斐波那契数
利用递归计算斐波那契数列第n个值是多少
package main
import"fmt"funcmain(){
fmt.Println(feibo(5))}// 使用递归实现斐波那契数列,计算出第n个值是多少// 斐波那契数列 1 1 2 3 5 8 13 .....funcfeibo(n int)int{if n ==1|| n ==2{return1}//第n个数是第n-1个数与第n-2个数的和returnfeibo(n-1)+feibo(n-2)}
版权归原作者 景天科技苑 所有, 如有侵权,请联系我们删除。