定义
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()
}