【笔记】Go语言的函数

前言

Go语言的函数学习笔记

函数的定义

  • 函数的作用域是全局的,可以在任意文件中写任意函数,可以在任意文件中调用任意函数
  • 函数定义时不需要考虑顺序

无参无返回值

1
2
3
func 函数名() {
...
}

有参

单个参数

1
2
3
func 函数名(参数名 数据类型) {
...
}

多个参数

1
2
3
func 函数名(参数名1 数据类型, 参数名2 数据类型) {
...
}
省略数据类型
  • 如果多个参数的数据类型相同,那么除了最后一个参数,其他参数的数据类型都可以省略
1
2
3
func 函数名(参数名1, 参数名2 数据类型) {
...
}

不定参

1
2
3
4
5
func 函数名(args ...数据类型) {
for i := 0; i < len(args); i++ {
args[i]
}
}
传递不定参
1
2
3
4
5
6
7
8
9
func main() {
f1(1, 2)
}
func f1(args ...int) {
f2(args[0:]...)
}
func f2(args ...int) {

}

有返回值

单个返回值

定义时不包含返回值名
1
2
3
4
5
6
func 函数名() 返回值类型 {

...

return 返回值
}
定义时包含返回值名
  • 如果定义了返回值的名,则返回时无需指定返回值,会自动返回对应名称的变量
1
2
3
4
5
6
func 函数名() (返回值名 返回值类型) {

...
返回值名 = 返回值值
return
}

多个返回值

1
2
3
4
5
6
func 函数名() (返回值名1 返回值类型, 返回值名2 返回值类型) {

...
返回值名1, 返回值名2 = 返回值值1, 返回值值2
return
}

函数的调用

无参无返回值

1
函数名()

有参

1
函数名(参数列表)

有返回值

1
2
变量名 := 函数名()
变量名1, 变量名2 := 函数名()

使用函数的类型

先定义类型然后使用函数类型

  • 将函数赋值给类型时,要求参数列表和返回值类型必须对应
  • 在赋值时不需要加(),在调用时需要加()
1
2
3
4
5
6
7
8
func 函数名(参数名 参数类型) 返回值类型 {}
// 定义类型
type 类型名 func(参数类型) 返回值类型
func main() {
// 使用类型
var 变量名 类型名 = 函数名
变量名(参数列表)
}

不定义类型直接使用函数类型

1
2
3
4
5
6
func 函数名(参数名 参数类型) 返回值类型 {}
func main() {
// 使用类型
var 变量名 函数名(参数类型) 返回值类型 = 函数名
变量名(参数列表)
}

自动类型推倒

  • 无需定义函数的类型
1
2
3
4
5
func main() {
// 使用类型
变量名 := 函数名
变量名(参数列表)
}

函数数据作用域

  • 如果程序中出现了相同的名称的变量
    • 如果本函数内有自己的变量,就使用本函数内的变量
    • 如果本函数内没自己的变量,就向上层寻找

局部变量

  • 在函数内部定义的变量
  • 局部变量的作用域是当前函数及其子函数
  • 局部变量存储位置在内存中的栈区
1
2
3
func main() {
var 变量名 = 变量值
}

全局变量

  • 在函数外部定义的变量
  • 全局变量的作用域是所有函数
  • 全局变量存储位置在内存中的数据区
  • 所有用const修饰的常量也在内存中的数据区存储
1
2
3
4
5
var 变量名 = 变量值

func main() {
...
}

匿名函数

定义匿名函数

1
2
3
{
...
}
1
2
3
func (){
...
}

匿名函数自调用

1
2
3
func(形参列表) {
...
}(实参列表)

接收返回值

1
2
3
返回值变量名 := func(形参列表) {
...
}(实参列表)

匿名函数赋值给变量

1
2
3
4
5
变量名 := func() {
...
}

变量名()

闭包

  • 函数的返回值是一个匿名函数,这个匿名函数的返回值可以自定义
  • 闭包中,匿名函数之外的变量只会声明一次,之后不会发生改变
1
2
3
4
5
6
7
8
func 函数名() func() 返回值类型 {

...

return func() {
return 返回值
}
}

递归函数

  • 函数在定义时调用函数本身
1
2
3
func 函数名() {
函数名()
}

init函数

  • init()函数用于完成初始化的工作,会在main()函数执行之前执行
    • 如果一个.go文件有全局变量的定义,执行顺序为:变量定义->init()->main()
  • 每一个.go文件都可以定义一个init()函数
  • 在其他.go文件引入包时也会先执行init()函数
    • 在引入多个层级的包都包含init()函数时,最后一个引入的包会最先执行init()函数
1
2
3
func init() {
...
}

defer关键字

  • defer关键字用于释放资源,当程序执行到defer修饰的代码时,会将被修饰的代码压入到defer栈中,暂时不执行,在当前函数执行结束之前,按照先入后出的原则依次执行defer栈中的代码
    • 在将defer修饰的代码压入defer栈时,会一同将代码中的变量值一同压入栈中
1
2
3
func 函数名() {
defer 代码
}

完成

参考文献

哔哩哔哩——喔咔咔耶耶
哔哩哔哩——Python路飞
哔哩哔哩——尚硅谷
哔哩哔哩——筱筱知晓