函数

PPG007 ... 2021-12-26 About 3 min

# 函数

# 函数定义

Go 中的函数:

  • 无需声明原型。
  • 支持不定变参。
  • 支持多返回值。
  • 支持命名返回函数。
  • 支持匿名函数和闭包。
  • 函数也是一种类型,一个函数可以赋值给变量。
  • 一个包内不能有重名函数。
  • 不支持重载。
  • 不支持默认参数。

函数声明:

函数声明包含一个函数名,参数列表,返回值列表和函数体。

// 没有返回值的函数。
func swap(x *int, y *int) {
  temp := *x
  *x = *y
  *y = temp
}
// 有一个返回值的函数。返回值类型声明在括号后面。
func getTime() int {
  return time.Now().Year()
}
// 命名返回值,卸载括号后面,相当于在函数中声明了一个变量,return 后也不需要显式指定返回变量名。如果函数体内重新声明了一个重名变量,则需要显式返回。
func getTime() (currentYear int) {
  currentYear = time.Now().Year()
  return
}
// 多返回值。
func getDate() (year int, month int, day int) {
  t := time.Now()
  year = t.Year()
  month = int(t.Month())
  day = t.Day()
  return
}
// 简写参数类型。
// 当多个连续参数或返回值类型相同时,可以省略前面的类型,只指出最后一个类型。
func getDate() (year, month, day int) {
  t := time.Now()
  year = t.Year()
  month = int(t.Month())
  day = t.Day()
  return
}
// 可变长参数。参数是切片。
func demo(msg string, y ...int) {
  fmt.Println(y)
}
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
27
28
29
30
31
32
33
34
35
36

# defer 延迟执行

  • 关键字 defer 用于注册延迟调用。
  • defer 声明的语句直到 return 前才被执行。
  • 多个 defer 语句按现金后出的方式执行。
  • defer 语句中的变量在 defer 声明时就决定了。

defer 用途:

  • 关闭文件句柄。
  • 锁资源释放。
  • 数据库连接释放。
// 先输出年、月、日,再输出年、最后输出最开始声明的 defer,打印 t。
func getDate() (year, month, day int) {
  t := time.Now()
  defer fmt.Println(t)
  year = t.Year()
  defer fmt.Println(year)
  month = int(t.Month())
  day = t.Day()
  fmt.Println(year, month,day)
  return
}
1
2
3
4
5
6
7
8
9
10
11

Go 语言中 return 不是原子的,分为两步:为返回变量赋值、返回。defer 声明的语句将会在这两步之间执行。

对于命名返回值,如果 defer 声明的语句对返回值作出了修改,将会影响最后的结果,如果不是命名返回值,修改将不会生效。

func getYear() (int) {
  currentYear := time.Now().Year()
  defer func ()  {
    currentYear = 2000
  }()
  return currentYear // 2021
}
1
2
3
4
5
6
7
func getYear() (currentYear int) {
  currentYear = time.Now().Year()
  defer func ()  {
    currentYear = 2000
  }()
  return currentYear // 2000
}
1
2
3
4
5
6
7

# 闭包

闭包:一个拥有许多变量和绑定了这些变量的环境的表达式。

func a() func() int {
  i := 0
  b := func () int {
    i++
    return i
  }
  return b
}
func main() {
  c := a()
  fmt.Println(c()) // 1
  fmt.Println(c()) // 2
  fmt.Println(c()) // 3
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 异常处理

Go 语言中使用 panic 抛出错误,recover 捕获错误。

  • 利用 recover 处理 panic 指令,defer 必须放在 panic 之前定义,recover 只有在 defer 中才有用,且必须是在 defer 函数中才有效。
  • recover 处理异常后,逻辑不会恢复到 panic 那个点,函数跑到 defer 之后的那个点。
func a() func() int {
  i := 0
  b := func() int {
    defer func() {
      err := recover()
      if err != nil {
        fmt.Println(err)
        fmt.Println(err.(string))
      }
    }()
    i++
    if i%2 == 0 {
      panic("出现偶数")
    }
    return i
  }
  return b
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 单元测试

TODO

# 压力测试

TODO

Last update: December 26, 2021 03:54
Contributors: PPG007