定义

Go支持普通函数、匿名函数和闭包。

Go函数本身可以作为值传递,Go的函数支持多返回值

func functionName([parameters]) [returnTypes] {
body
}

示例:

package main

import "fmt"

func main() {
 a := 1
 b := 2
 fmt.Printf("%d\n", sum(a, b))
 sum, multi := sumAndMulti(a, b)
 fmt.Printf("sum = %d, multi = %d", sum, multi)
}

func sum(a, b int) int {
 return a + b
}

func sumAndMulti(a, b int) (int, int) {
 return a + b, a * b
}

Go函数本身可以作为值传递示例:

package main

import "fmt"

// 定义函数类型
type OperateFunc func(a, b int) int

func main() {
 a := 10
 b := 20
 operator := "*"
 result := 0
 if operator == "+" {
  result = operate(sum, a, b)
 }
 if operator == "-" {
  result = operate(minus, a, b)
 }
    // 匿名函数
 if operator == "*" {
  result = operate(func(a, b int) int {
   return a * b
  }, a, b)
 }
 fmt.Println(result)
}

func sum(a, b int) int {
 return a + b
}

func minus(a, b int) int {
 return a - b
}
// 使用函数类型
func operate(fn OperateFunc, a, b int) int {
 return fn(a, b)
}


函数返回值

函数返回值可以有多个,同时支持返回值命名。多个返回值会默认赋予类型零值。

示例:

package main

import "fmt"

func main() {
 names, hashMap, age := fun1()
 fmt.Println(names, hashMap, age)
}

func fun1() (names []string, hashMap map[string]int, age int) {
 hashMap = make(map[string]int)
 hashMap["gender"] = 1
 return
}
// output
[] map[gender:1] 0

函数参数

函数参数有两种:

  • 值传递,实际调用函数时,参数会复制一份,实际操作的内容是赋值的内存,不会影响原值
  • 引用传递(地址传递),同样会复制一份地址值,所以实际操作会修改原值

经典例子交换两个数:

package main

import "fmt"

func main() {
 a := 1
 b := 2
 swap(a, b)
 fmt.Println(a, b)
 swap2(&a, &b)
 fmt.Println(a, b)
}

func swap(a, b int) {
 a, b = b, a
}

func swap2(a, b *int) {
 *a, *b = *b, *a
}
// output
1 2
2 1

Go也支持可变参数,只能有一个,且是最后一个,本质上是一个slice,参数传递时可以不用一个一个赋值,直接传递一个数组或者slice。

示例:

package main

import "fmt"

func main() {
 fmt.Println(sum(1, 2, 3))
 nums := []int{1, 2, 3}
 // 如果是切片传递方式,要加...
 fmt.Println(sum(nums...))
}
func sum(nums ...int) int {
 sum := 0
 for _, num := range nums {
  sum += num
 }
 return sum
}

匿名函数

不带函数名的声明方式,可以在定义时直接调用匿名函数。

示例:

package main

import "fmt"

func main() {
 fn1 := func(x int) int {
  return x
 }
 fmt.Println(fn1(10))

 func(x int) int {
  fmt.Println(x)
  return x
 }(10)
}
// output
10
10

匿名函数也可以当作函数返回值。

示例:

package main

import "fmt"

func main() {
 a := 10
 b := 20
 sumFunc, minusFun := operate()
 fmt.Println(sumFunc(a, b))
 fmt.Println(minusFun(a, b))

}
func operate() (func(a, b int) int, func(a, b int) int) {
 sum := func(a, b int) int {
  return a + b
 }
 minus := func(a, b int) int {
  return a - b
 }
 return sum, minus
}
// output
30
-10

defer
  • 直到return前才被执行,可以用来做资源清理(文件句柄释放、锁释放等)
  • 多个defer语句,按照先进后出顺序执行

示例:

package main

import "fmt"

func main() {
 nums := []int{1, 2, 3}
 for _, num := range nums {
  defer fmt.Println(num)
 }
}
// output
3
2
1

deferdefer

示例:

package main

import (
 "log"
 "time"
)

func main() {
 start := time.Now()
 log.Printf("start time:%v\n", start)
 defer log.Printf("diff:%v\n", time.Since(start))
 time.Sleep(3 * time.Second)
}
// output
2022/08/16 21:36:34 start time:2022-08-16 21:36:34.8768915 +0800 CST m=+0.001032201
2022/08/16 21:36:37 diff:4.6368ms

为了避免这种情况,可以把待执行语句放到匿名函数中。

package main

import (
 "log"
 "time"
)

func main() {
 start := time.Now()
 log.Printf("start time:%v\n", start)
 defer func() {
  log.Printf("diff:%v\n", time.Since(start))
 }()
 time.Sleep(3 * time.Second)
}
// output
2022/08/16 21:38:41 start time:2022-08-16 21:38:41.860342 +0800 CST m=+0.001027501
2022/08/16 21:38:44 diff:3.0190457s

panicrecoverdefer
panic
panicgoroutine
recover
panic

示例:

package main

import "fmt"

func main() {
 defer func() {
  if err := recover(); err != nil {
   // interface{} 类型转具体类型
   println(err.(string))
  }
 }()
 panic("error!")
 fmt.Println("success!")
}
// output
error!

defer

示例:

package main

import "fmt"

func main() {
 defer func() {
  if err := recover(); err != nil {
   // interface{} 类型转具体类型
   println(err.(string))
  }
 }()
 defer func() {
  panic("defer error!")
 }()
 panic("error!")
 fmt.Println("success!")
}
// output
defer error!

try catch

示例:

package main

import (
 "fmt"
 "log"
)

func main() {
 func() {
  defer func() {
   if err := recover(); err != nil {
    log.Println("error!")
   }
  }()
  panic("出现了错误")
  fmt.Println("继续执行!")
 }()
 fmt.Println("执行到代码结尾!")
}
// output
2022/08/16 22:07:21 error!
执行到代码结尾!

panicerror
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
 Error() string
}

errors.Newfmt.Errorferror

示例:

package main

import (
 "errors"
 "fmt"
)

var ErrDivideByZero = errors.New("除0错误")

func main() {
 defer func() {
  fmt.Println(recover())
 }()
 switch result, err := divide(10, 0); err {
 case nil:
  println(result)
 case ErrDivideByZero:
  panic(err)
 }
}

func divide(a, b int) (int, error) {
 if b == 0 {
  return 0, ErrDivideByZero
 }
 return a / b, nil
}
// output
除0错误

try catch
package main

import (
 "errors"
 "log"
)

var ErrDivideByZero = errors.New("除0错误")

func main() {
 Try(func() {
  // 正常执行代码
  panic(ErrDivideByZero)
 }, func(err interface{}) {
        // 判断不同错误类型,执行不同逻辑
  if err == ErrDivideByZero {
   log.Println("Error:", err)
  } else {
   log.Println("Else Error:", err)
  }
 })
}

func Try(fun func(), handler func(interface{})) {
 defer func() {
  if err := recover(); err != nil {
   handler(err)
  }
 }()
 fun()
}