本博客涉及内容:函数的定义、固定参数、不定参数、延迟调用
函数初识
函数定义
函数是一种程序中的基本构建块,用于执行特定的任务或操作。在编程中,函数通常被用来封装一些列操作,并且可以输入参数并返回输出结果。函数可以看作是程序中的子程序或子例程,用于实现特定的功能或完成特定的任务。
函数就是一段代码,类似于一个专门做一类事的工具,它可能需要我们提供一些数据,然后将我们提供的数据进行处理返回。我们提供的数据叫做参数
,它返回的值叫做返回值
。简单而言,你给它一些东西,它给你返回一些东西。
函数基本语法
func 函数名(参数列表) 返回值类型 {
// 函数体
}
- 函数名:函数的名称用于唯一标识函数,并在代码中进行调用。
- 参数列表:函数可以接收零个或多个参数作为输入。参数列表定义了函数接收的输入数据的类型和顺序。
- 函数体:函数体包括函数的的实际执行逻辑。在函数内部,可以进行各种操作,包括计算、控制流操作、变量定义等。
- 返回值:函数可以返回零个或多个值作为结果,返回值类型定义了函数返回的数据类型。
普通参数列表
给函数的参数列表都是定义好的。例如:
package main
import "fmt"
// 函数指定参数个数
func Test(a int, b int) {
fmt.Printf("a=%d, b=%d", a, b)
fmt.Println()
}
func Add(a, b int) {
var sum int
sum = a + b
fmt.Println("和为", sum)
}
func main() {
Test(3, 5)
var num1, num2 int
fmt.Println("请输入第一个数")
fmt.Scanf("%d\n", &num1)
fmt.Println("请输入第二个数")
fmt.Scanf("%d\n", &num2)
Add(num1, num2)
}
本代码中定义了三个函数:main()、Add()、Test()。其中main()函数作为程序的入口,首先调用了Test()函数。此时我们的注意力由main()函数转移到Test()函数:
func Test(a int, b int) {
fmt.Printf("a=%d, b=%d", a, b)
fmt.Println()
}
Test为函数名(在调用时需要带括号)。a int, b int
为函数的参数列表,此处定义了两个int类型的参数(确定了参数个数和参数类型)。在调用时需要传入两个参数Test(3, 5)
。fmt.Printf("a=%d, b=%d", a, b) fmt.Println()
为函数体,执行Test()函数的实际执行逻辑,此处逻辑为打印传入的值。代码运行情况如下:
同理可推Add()函数的执行顺序。
【注意】
-
- 参数的传递:在本例中,我们定义了一个Test()函数,它有两个参数,我们称之为
形参
,在调用时传入了3和5
两个参数,我们称之为实参。调用的过程中,我们会把两个实参传递给Test()函数,这个过程就叫做参数的传递。
- 参数的传递:在本例中,我们定义了一个Test()函数,它有两个参数,我们称之为
-
- 在定义函数时,形参和实参的参数个数和数据类型都需要保持一致。
不定参数列表
在定义函数时可以根据需求定义参数的个数和类型,但是在无法确定参数个数的时候呢?
package main
import "fmt"
// 函数不定参数列表
func Test(args ...int) {
//for i := 0; i < len(args); i++ {
// fmt.Print(args[i])
//}
for _, data := range args {
fmt.Print(data)
}
fmt.Println()
}
func main() {
Test(1)
Test(1, 2)
Test(1, 2, 3)
Test(1, 2, 3, 4)
}
函数执行情况如下:
Test()函数的参数名字叫args(参数的名字可以随便起),类型是整型的。在args后面跟了三个点,就是表示该参数可以接收0或多个整数值。所以,args这个参数我们可以想象成是一个集合(类似数学中集合),可以存放多个值。在调用过程中分别使用了1--4个int类型的实参
,函数的输出结果跟着实参个数的变化而变化。
【注意】
在使用不定参数时,要注意以下几个问题:
- 只能放在形参的最后一个参数
- 对函数进行调用时,固定参数必须传值,不定参数可以根据需求是否传值。
函数返回值
直接从代码出发:
func AddResult(num1, num2 int) int { // 表示指定函数返回的数据的类型
var sum int
sum = num1 + num2
return sum // 将变量sum中存储的值返回
}
func main() {
var s int
s = AddResult(3, 6) // 将函数的返回值的结果赋值给了变量s
fmt.Println(s)
}
- 定义函数时,在后面加了
int
,表示该函数的返回值是一个int
类型的数据。 - AddResult() 函数要返回数据,必须将要返回的数据放在return关键词之后(通过return关键字会将数据返回)。
- 在main() 函数中调用 AddResult() 函数,会执行AddResult() 函数中的代码,当执行完
return sum
时,会将sum变量中的保存的值返回。 - AddResult() 函数中的返回值会赋值给 main() 函数中的 变量
s
。
同时也可以定义多个返回值:
func GerResult() (int, int) {
var num1 int = 10
var num2 int = 20
return num1, num2
}
func main() {
var s1 int
var s2 int
s1, s2 = GerResult() // 在这里,函数返回两个值,所以定义两个变量进行接收
fmt.Println("s1=", s1)
fmt.Println("s2=", s2)
}
go语言同时定义了其它两种返回值的写法:
案例练习:
package main
import "fmt"
/*
函数案例:
模拟用户注册,当用户输入完用户名,密码和邮箱后,进行校验。如果发现用户名,密码和邮箱是空的,则给出“信息不能为空,
用户注册失败”的提示,否则,进行邮件发送,并给出“用户注册成功”的提示。
1、用户注册
2、校验信息
3、发送邮件
*/
// 用户注册
func Register() {
// 接收用户输入的信息
var userName string = "admin"
var userPwd string = "123"
var userEmail string = "admin@gmail.com"
// 进行校验
b := CheckInfo(userName, userPwd, userEmail)
// 如果校验成功了,调用发送邮件的函数
if b {
SendEmail()
fmt.Println("用户注册成功!")
} else {
fmt.Println("信息不完整,无法完成用户注册!!")
}
}
// 校验信息
func CheckInfo(name string, pwd string, email string) bool {
if name != "" && pwd != "" && email != "" {
return true
} else {
return false
}
}
// 发送邮件
func SendEmail() {
fmt.Println("邮件发送成功!")
}
func main() {
Register()
}
延迟调用
defer
关键词的使用,直接调用时,会立即执行该函数。但是在加入defer
参数后,会对它进行延迟调用(具体应用请参考其它资料)。
package main
import "fmt"
// 如果一个函数中出现了多个defer,它会以后进先出的顺序执行
func main() {
defer fmt.Println("111") // 延迟调用
defer fmt.Println("222")
defer fmt.Println("333")
}