1.变量作用域

1.1全局变量

  1. var num = 10 //全局变量
  2. func main() {
  3. fmt.Println(num)
  4. }

1.2局部变量

如果局部变量和全局变量重名,优先访问局部变量

  1. var num = 10 //局部变量
  2. func main() {
  3. num :=15
  4. fmt.Println(num)
  5. }

2.函数类型与变量

  1. //定义函数类型
  2. type calc func(int,int) int
  3. func add(x,y int) int {
  4. return x+y
  5. }
  6. func sub(x, y int) int {
  7. return x-y
  8. }
  9. //函数类型变量
  10. func main() {
  11. var c calc
  12. c = add
  13. fmt.Printf("%T\n",c) //main.calc
  14. fmt.Println(c(1,2))
  15. f := add
  16. fmt.Printf("%T\n",f) //func(int, int) int
  17. fmt.Println(f(10,20))
  18. }

3.高阶函数

高阶函数分为函数作为参数函数作为返回值两部分

3.1函数作为参数

  1. func add(x, y int) int {
  2. return x+y
  3. }
  4. func sub(x, y int) int {
  5. return x-y
  6. }
  7. func calc(x,y int,op func(int,int) int) int {
  8. return op(x,y)
  9. }
  10. func main() {
  11. sum := calc(1, 2, add)
  12. sub := calc(10, 5, sub)
  13. fmt.Println(sum,sub)
  14. }

4.匿名函数和闭包

4.1匿名函数

  1. add := func(x, y int){
  2. fmt.Println(x+y)
  3. }
  4. add(10,20) //30
  1. func(x,y int){
  2. fmt.Println(x+y)
  3. }(10,20) //30

4.2闭包

闭包=函数+引用环境

  1. func adder() func(int) int {
  2. var x int
  3. return func(y int) int {
  4. x+=y
  5. return x
  6. }
  7. }
  8. func main() {
  9. var f = adder()
  10. fmt.Println(f(10))
  11. f1 := adder()
  12. fmt.Println(f1(50))
  13. }
  1. func adder(x int) func(int) int {
  2. return func(y int) int {
  3. x+=y
  4. return x
  5. }
  6. }
  7. func main() {
  8. var f = adder(10)
  9. fmt.Println(f(10))
  10. f1 := adder(50)
  11. fmt.Println(f1(50))
  12. }
  1. func calc(num int) (func(int) int,func(int) int) {
  2. add:= func(i int) int{
  3. num+=i
  4. return num
  5. }
  6. sub:= func(i int) int{
  7. num-=i
  8. return num
  9. }
  10. return add,sub
  11. }
  12. func main() {
  13. f1, f2 := calc(10)
  14. fmt.Println(f1(10),f2(10))
  15. }

5.defer语句

Go语言中的defer语句会将其后面跟随的语句进行延迟处理。将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

  1. fmt.Println("start")
  2. defer fmt.Println(1)
  3. defer fmt.Println(2)
  4. defer fmt.Println(3)
  5. fmt.Println("end")

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

  1. start
  2. end
  3. 3
  4. 2
  5. 1

经典案例

  1. func f1() int {
  2. x := 5
  3. defer func() {
  4. x++
  5. }()
  6. return x
  7. }
  8. func f2() (x int) {
  9. defer func() {
  10. x++
  11. }()
  12. return 5
  13. }
  14. func f3() (y int) {
  15. x := 5
  16. defer func() {
  17. x++
  18. }()
  19. return x
  20. }
  21. func f4() (x int) {
  22. defer func(x int) {
  23. x++
  24. }(x)
  25. return 5
  26. }
  27. func main() {
  28. fmt.Println(f1())
  29. fmt.Println(f2())
  30. fmt.Println(f3())
  31. fmt.Println(f4())
  32. }

6.内置函数

内置函数 介绍
close 主要用来关闭channel
len 用来求长度,比如string、array、slice、map、channel
new 用来分配内存,主要用来分配值类型,比如int、struct。返回的是指针
make 用来分配内存,主要用来分配引用类型,比如chan、map、slice
append 用来追加元素到数组、slice中
panic和recover 用来做错误处理

7.panic/recover

panic可以在任何地方引发,但recover只有在defer调用的函数中有效

  1. func f1() {
  2. fmt.Println("f1")
  3. }
  4. func f2() {
  5. //fmt.Println("f2")
  6. panic("panic in f2")
  7. }
  8. func f3() {
  9. fmt.Println("f3")
  10. }
  11. func main() {
  12. f1()
  13. f2()
  14. f3()
  15. }

image.png
可以通过recover将程序恢复回来,继续往后执行

  1. func f1() {
  2. fmt.Println("f1")
  3. }
  4. func f2() {
  5. defer func() {
  6. err := recover()
  7. //如果程序出出现了panic错误,可以通过recover恢复过来
  8. if err !=nil{
  9. fmt.Println("recover in f2")
  10. }
  11. }()
  12. panic("panic in B")
  13. }
  14. func f3() {
  15. fmt.Println("f3")
  16. }
  17. func main() {
  18. f1()
  19. f2()
  20. f3()
  21. }
  1. recover()必须搭配defer使用。
  2. defer一定要在可能引发panic的语句之前定义