1. func main() {
  2. for i := 0; i < 1000; i++ {
  3. go func(i int) {
  4. for {
  5. fmt.Printf("Hello from goroutine %d\n", i)
  6. }
  7. }(i)
  8. }
  9. time.Sleep(time.Millisecond)
  10. }

协程Coroutine

轻量级线程
非抢占式多任务处理,由协程主动交出控制权
编译器/解释器/虚拟机层面的多任务
多个协程可能在一个或多个线程上运行

手动交出控制权

  1. runtime.Gosched()

检测数据访问的冲突
�go run —race xx.go

image.png

goroutine可能的切换点

I/O,select
channel
等待锁
函数调用(有时)
runtime.Gosched()

channel(通道)

不要通过共享内存来通信,通过通信来共享内存

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func worker(id int, c chan int) {
  7. for n := range c { // 也可以使用range来检测是否还有值
  8. //n, ok := <-c // 判断发送方是否已关闭
  9. //if !ok {
  10. // break
  11. //}
  12. fmt.Printf("worker %d received %d \n", id, n)
  13. }
  14. }
  15. // chan<- 发数据
  16. // <-chan 收数据
  17. func createWorker(id int) chan<- int {
  18. c := make(chan int)
  19. go func() {
  20. for {
  21. fmt.Printf("worker %d received %c \n", id, <-c)
  22. }
  23. }()
  24. return c
  25. }
  26. func chanDemo() {
  27. var channels [10]chan<- int
  28. for i := 0; i < 10; i++ {
  29. channels[i] = createWorker(i)
  30. }
  31. for i := 0; i < 10; i++ {
  32. channels[i] <- i
  33. }
  34. time.Sleep(time.Millisecond)
  35. }
  36. func bufferedChannel() {
  37. c := make(chan int, 3) // 第二个参数为缓存区
  38. c <- 1
  39. c <- 2
  40. c <- 3
  41. go worker(0, c)
  42. time.Sleep(time.Millisecond)
  43. }
  44. func channelClose() {
  45. c := make(chan int, 3) // 第二个参数为缓存区
  46. c <- 1
  47. c <- 2
  48. c <- 3
  49. go worker(0, c)
  50. close(c)
  51. time.Sleep(time.Millisecond)
  52. }
  53. func main() {
  54. //chanDemo()
  55. //bufferedChannel()
  56. channelClose()
  57. }