defer_test

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. //f, _ := os.OpenFile("xxx.txt")
  7. //此处有大量的逻辑需要读取文件
  8. //defer f.Close()
  9. /*
  10. defer 语句是go提供的一种用于注册延迟调用的机制 它可以让当前函数执行完毕之后执行
  11. 对于python的with语句来说
  12. */
  13. //fmt.Println("hello1")
  14. //defer a++ error 可以做函数调用不能做表达式的书写 比如a++
  15. //a := 0
  16. //defer fmt.Println("defer hello")
  17. //panic("error")
  18. //fmt.Println("hello2")
  19. //如果有多个defer会出现什么情况
  20. //defer fmt.Println("test1")
  21. //defer fmt.Println("test2")
  22. //defer fmt.Println("test3")
  23. //多个defer是按照先入后出的顺序执行的
  24. //defer 语句执行时的拷贝机制
  25. //test := func() {
  26. // fmt.Println("test1")
  27. //}
  28. //defer test()
  29. //test = func() {
  30. // fmt.Println("test2")
  31. //}
  32. //fmt.Println("test3")
  33. //
  34. //x := 10 //压栈的是函数段
  35. //defer func(a int) {
  36. // fmt.Println(x) //11
  37. // fmt.Println(a) //10
  38. //}(x)
  39. //x++
  40. //defer func(a *int) {
  41. // fmt.Println(*a)
  42. //}(&x)
  43. //x++
  44. //闭包 此处的defer函数没有参数 - 函数内部使用的值是全局的值
  45. //defer func() {
  46. // fmt.Println(x) //11
  47. //}()
  48. //x++
  49. //defer func(x int) {
  50. // fmt.Println(x) //10
  51. //}(x)
  52. //x++
  53. fmt.Println(f1()) //10 是不是就意味着 defer中影响不到外部的值呢? - 不是
  54. fmt.Println(*f2())
  55. //defer本质上是注册了一个延迟函数 defer函数的执行顺序已经确定
  56. //defer没有嵌套 defer的机制是要取代try except finally的机制
  57. }
  58. func f1() int {
  59. x := 10
  60. defer func() {
  61. x++ //闭包里面的值 不影响
  62. }()
  63. tmp := x
  64. return tmp
  65. //return x
  66. }
  67. func f2() *int {
  68. a := 10
  69. b := &a
  70. defer func() {
  71. *b++ //闭包里面的值 不影响
  72. }()
  73. temp_data := b
  74. return temp_data
  75. return b
  76. }

err_exception

  1. package main
  2. import "fmt"
  3. func div(a, b int) (int, error) {
  4. if b == 0 {
  5. panic("被除数不能为0")
  6. }
  7. return a / b, nil
  8. }
  9. func main() {
  10. //错误就是能预知到可能出现的情况,这些情况会导致你的代码出问题 参数检查 数据库访问不了
  11. //data := 12
  12. //整数转字符串 字符串的内容形式不受限制
  13. //strconv.Itoa(data) //这个Itoa的函数不可能出错 所以没有必要返回error.
  14. //内部代码出错的时候, 应该抛出异常 panic
  15. //字符串转整数 因为字符串所包含的字符集是纯数字的超集 可能会出现中文字符 标点符号等情况 故会返回error
  16. //_, err := strconv.Atoi("12") //Atoi这个函数认为我的函数内部会出现一些预知错误情况
  17. //if err != nil {
  18. // //错误
  19. //}
  20. //异常 go语言如何抛出异常和如何接收/接收异常
  21. //go语言认为错误就要自己处理,就个人而言,go语言的这种想法是正确的。但是实际使用中确实有点烦人
  22. a := 12
  23. b := 0
  24. defer func() {
  25. err := recover()
  26. if err != nil {
  27. fmt.Println("异常被捕获到")
  28. }
  29. fmt.Println("wozen")
  30. }()
  31. fmt.Println(div(a, b))
  32. //panic的坑
  33. }

func_define

  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. //相比较其他静态语言 go语言的函数有很多两点
  7. //函数定义的几个要素: 1. 函数名 2. 参数 3. 返回值
  8. //函数第一种定义方法
  9. func add(a, b int) int {
  10. var sum int
  11. sum = a + b
  12. return sum
  13. }
  14. //函数的第二种定义方法
  15. func add2(a, b int) (sum int) {
  16. sum = a + b
  17. return sum
  18. }
  19. //函数的第三种定义方法
  20. func add3(a, b int) (sum int) {
  21. sum = a + b
  22. return
  23. }
  24. //函数的第四种定义方法
  25. //被除数为0 要返回多个值 -一个非常有用的特性
  26. //go语言的返回设置花样很多
  27. func div(a, b int) (int, error) {
  28. var result int
  29. var err error
  30. if b == 0 {
  31. err = errors.New("被除数不能为0")
  32. } else {
  33. result = a / b
  34. }
  35. return result, err
  36. }
  37. func div2(a, b int) (result int, err error) {
  38. if b == 0 {
  39. err = errors.New("被除数不能为0")
  40. } else {
  41. result = a / b
  42. }
  43. return
  44. }
  45. func main() {
  46. result, err := div2(12, 0)
  47. if err != nil {
  48. fmt.Println(err)
  49. } else {
  50. fmt.Println(result)
  51. }
  52. }

func_params

  1. package main
  2. import "fmt"
  3. //省略号 ...
  4. func add(params ...int) (sum int) {
  5. //不能解决一个问题我可能有不定个int值传递进来
  6. for _, v := range params {
  7. sum += v
  8. }
  9. return
  10. }
  11. func add2(params []int) (sum int) {
  12. //不能解决一个问题我可能有不定个int值传递进来
  13. for _, v := range params {
  14. sum += v
  15. }
  16. params[0] = 9
  17. return
  18. }
  19. type sub func(a, b int) int //sub就等同于 int map
  20. func subImpl(a, b int) int {
  21. return a - b
  22. }
  23. func filter(score []int, f func(int) bool) []int {
  24. reSlice := make([]int, 0)
  25. for _, v := range score {
  26. if f(v) {
  27. reSlice = append(reSlice, v)
  28. }
  29. }
  30. return reSlice
  31. }
  32. func main() {
  33. //通过省略号去动态设置多个参数
  34. fmt.Println(add(1, 2, 3))
  35. fmt.Println(add(1, 2, 3, 4))
  36. fmt.Println(add(1, 2, 3, 4, 5))
  37. //这种效果 - slice
  38. //区别 slice是一种类型 还是引用传递
  39. slice := []int{1, 2, 3, 4, 5}
  40. fmt.Println(add2(slice))
  41. fmt.Println(add(slice...)) //将slice打散
  42. fmt.Println(slice)
  43. //我们要慎重
  44. //省略号的用途
  45. //1. 函数参数不定长 2.将slice打散 3.
  46. arr := [...]int{1, 2, 3}
  47. fmt.Printf("%T\n", arr)
  48. //函数内部定义函数 函数内嵌
  49. //匿名函数
  50. fmt.Println(func(a, b int) int {
  51. return a + b
  52. }(1, 2))
  53. //fmt.Printf("%T\n", result) //func(...int) int
  54. //go语言中非常重要的特性 函数 一些trick 一些语法糖
  55. //函数的一等公民特性 - 可以作为参数 返回值 复制给另一个变量
  56. //函数也可以当作参数传递给一个函数
  57. var mySub sub = func(a, b int) int {
  58. return a - b
  59. }
  60. fmt.Println(mySub(1, 2))
  61. //mySub(1, 2)
  62. //将函数作为另一个函数的参数
  63. //写一个函数用于过滤一部分数据
  64. score := []int{10, 30, 40, 50, 90}
  65. //写一个函数 过滤掉不合格的成绩
  66. fmt.Println(filter(score, func(a int) bool {
  67. if a >= 90 {
  68. return true
  69. } else {
  70. return false
  71. }
  72. }))
  73. //gin python的装饰器
  74. //go语言并没有提供try except finally
  75. //1.大量嵌套 try finally 2.打开和关闭逻辑离得太远
  76. }

http_server

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func f1() {
  7. defer func() {
  8. err := recover()
  9. if err != nil {
  10. fmt.Println("捕获到了")
  11. }
  12. }()
  13. go func() {
  14. panic("出错了")
  15. }()
  16. time.Sleep(2 * time.Second) //为啥panic了?
  17. }
  18. func main() {
  19. f1()
  20. //http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
  21. //a := 10
  22. //b := 0
  23. //fmt.Println(a / b)
  24. //panic("error")
  25. //go func() {
  26. //操作redis的,有人觉得这段代码可以放到协程中去运行。有一个非常大的隐患了
  27. //panic("error")
  28. //}()
  29. //服务被停掉
  30. //writer.Write([]byte("hello world"))
  31. //})
  32. //http.ListenAndServe("127.0.0.1:8080", nil)
  33. //panic会引起主线程的挂掉 同时会导致其他的协程都挂掉
  34. //为什么直接在,在父协程中无法捕获走子协程出现的异常
  35. }