Go语言基础之函数!

函数的声明:

函数的声明:

  • 使用 func 关键字,后面依次接 函数名参数列表返回值列表用 {} 包裹的代码逻辑体
  • 形式参数列表描述了函数的参数名以及参数类型
    • 这些参数作为局部变量,其值由参数调用者提供
  • 返回值列表描述了函数返回值的变量名以及类型
    • 如果函数返回一个无名变量或者没有返回值,返回值列表的括号是可以省略的
1
2
3
func 函数名(形式参数列表)(返回值列表){
函数体
}

函数名:由字母、数字、下划线组成。

  • 但函数名的第一个字母不能是数字:函数名也不能重复命名。

参数:参数由参数变量和参数变量的类型组成,多个参数之间使用,分割

返回值:返回值由返回值变量和其变量类型组成

  • 也可以只写返回值的类型,多个返回值必须用()包裹,并用,分割

举个例子,定义一个 sum 函数,接收两个 int 类型的参数

  • 在运行中,将其值分别赋值给 a,b,并规定必须返回一个int类型的值
1
2
3
4
5
6
func sum(a int, b int) (int){
return a + b
}
func main() {
fmt.Println(sum(1,2))
}

无参数无返回值函数

函数可以有参数也可以没有参数,可以有返回值也可以没有返回值

1
2
3
4
5
6
7
8
9
10
11
func main() {
demo1()
}
func demo1(){
fmt.Println("执行demo1函数")
}

//上面代码等同于
//func main(){
// fmt.Println("执行demo1函数")
//}

可变参数函数

Go语言支持可变参数函数

可变参数指调用参数时,参数的个数可以是任意个

可变参数必须在参数列表最后的位置

  • 在参数名和类型之间添加三个点表示可变参数函数
1
2
3
4
5
6
7
8
9
10
11
12
13
func 函数(参数,参数,名称 ... 类型 ){
//函数体
}

func main() {
demo("看书", "写代码", "看抖音视频")
}

func demo(hover ... string) {
for a, b := range hover {
fmt.Println(a, b)
}
}

多返回值

函数如果有多个返回值时必须用()将所有返回值包裹起来。

匿名函数

匿名函数就是没有名称的函数

正常函数可以通过名称多次调用,而匿名函数由于没有函数名

  • 所以大部分情况都是在当前位置声明并立即调用(函数变量除外)

匿名函数声明完需要调用,在函数结束大括号后面紧跟小括号

  • 匿名函数都是声明在其他函数内部
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
func (){

}()//括号表示调用

//无参数匿名函数
func main(){
func(){
fmt.Println("这是匿名函数")
}()//括号表示调用
}

//有参数匿名函数
func main() {
func(s string) {
fmt.Println(s, "这是匿名函数")
}("传递参数") //调用时传递参数
}

//有参数有返回值匿名函数
func main() {
r := func(s string) int {
fmt.Println(s, "这是匿名函数")
return 110
}("传递参数") //调用时传递参数
fmt.Println(r)
}

函数作为参数或返回值

变量可以作为函数的参数或返回值类型,而函数既然可以当做变量看待

  • 函数变量也可以当做函数的参数或返回值

函数作为参数时,类型写成对应的类型即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func main() {
a(func(s string) {
fmt.Println(s)
})
}

func a(b func(s string)) {
fmt.Println("a执行")
b("传递给s的内容")
}

//函数作为返回值
func main() {
//此时result指向返回值函数.
result := a()
//调用函数,才能获取结果
fmt.Println(result())
}

func a() func() int {
return func() int {
return 110go
}
}

Defer语句

Go语言中的defer语句会将其后面跟随的语句进行延迟处理。

defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行

  • 也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

由于defer语句延迟调用的特性,所以defer语句能非常方便的处理资源释放问题。

  • 比如:资源清理、文件关闭、解锁及记录时间等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
fmt.Println("start")
defer fmt.Println(1)
defer fmt.Println(2)
defer fmt.Println(3)
fmt.Println("end")
}

输出结果:
start
end
3
2
1

defer执行时机:

  • 在Go语言的函数中return语句在底层并不是原子操作
    • 它分为给返回值赋值和RET指令两步。
  • defer语句执行的时机就在返回值赋值操作后,RET指令执行前。

img

全局变量

全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效。

在函数中可以访问到全局变量。

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

import "fmt"

// 定义全局变量
var num int64 = 10 // 不能使用 num := 10

func globalVar(){
fmt.Println(num) // 函数中可以访问到全局变量num
}

func main(){
globalVar() // num=10
}