只读只写channel

  1. // 管道可以声明只读或者只写
  2. package main
  3. import "fmt"
  4. func main() {
  5. // 1、 默认情况下,管道是双向的,可读可写
  6. // var chan1 chan int
  7. // 2、只写
  8. var chan2 chan<- int = make(chan<- int, 3)
  9. chan2 <- 20
  10. fmt.Println("chan2 = ", chan2)
  11. // 3、只读
  12. var chan3 <-chan int
  13. // num1 := <-chan3
  14. // chan3 <- 3 // invalid operation: chan3 <- 3 (send to receive-only type <-chan int)
  15. fmt.Println("chan3 = ", chan3)
  16. }

select + channel

使用 select 解决 从 channel 中取数据的阻塞问题。

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. )
  6. func main() {
  7. // 创建带缓冲的管道
  8. var intChan chan int = make(chan int, 5)
  9. for i := 0; i < 5; i++ {
  10. intChan <- i
  11. }
  12. // 创建带缓冲的管道
  13. var strChan chan string = make(chan string, 10)
  14. for i := 0; i < 10; i++ {
  15. strChan <- "hello" + strconv.Itoa(i)
  16. }
  17. // 传统方法遍历管道,如果不关闭会阻塞而导致 deadlock
  18. // 不确定什么时候关闭管道,可以使用 select 语法解决
  19. for {
  20. select {
  21. case v := <-intChan:
  22. fmt.Printf("从 intChan 中取到数据%d \n", v)
  23. case v := <-strChan:
  24. fmt.Printf("从 strChan 中取到数据%v \n", v)
  25. default:
  26. fmt.Println("都取不到,不玩了")
  27. return
  28. }
  29. }
  30. /*
  31. 从 strChan 中取到数据hello0
  32. 从 strChan 中取到数据hello1
  33. 从 intChan 中取到数据0
  34. 从 strChan 中取到数据hello2
  35. 从 intChan 中取到数据1
  36. 从 strChan 中取到数据hello3
  37. 从 intChan 中取到数据2
  38. 从 strChan 中取到数据hello4
  39. 从 strChan 中取到数据hello5
  40. 从 intChan 中取到数据3
  41. 从 strChan 中取到数据hello6
  42. 从 intChan 中取到数据4
  43. 从 strChan 中取到数据hello7
  44. 从 strChan 中取到数据hello8
  45. 从 strChan 中取到数据hello9
  46. 都取不到,不玩了
  47. */
  48. }

goroutine + recover(错误捕获)

goroutine 中使用 recover ,解决协程中出现 panic 导致程序崩溃问题

  1. // recover
  2. package main
  3. import (
  4. "fmt"
  5. "sync"
  6. )
  7. var wg sync.WaitGroup
  8. func sayHello() {
  9. defer wg.Done()
  10. for i := 0; i < 10; i++ {
  11. fmt.Println("hello")
  12. }
  13. }
  14. func test() {
  15. // defer + recover 捕获处理异常
  16. defer func() {
  17. wg.Done()
  18. if err := recover(); err != nil {
  19. // 有异常
  20. fmt.Println("test() err = ", err)
  21. // test() err = assignment to entry in nil map
  22. }
  23. }()
  24. var testmap map[int]string
  25. // var testmap = make(map[int]string)
  26. testmap[0] = "北京" // 没有分配空间 (make) error
  27. }
  28. func main() {
  29. fmt.Println("程序开始了")
  30. wg.Add(2)
  31. // recover
  32. go sayHello()
  33. go test()
  34. wg.Wait()
  35. fmt.Println("程序结束了")
  36. }