使用通信来共享内存,而不是使用共享内存在通信

  1. 基础

    channel 只能使用 make 生成
    make(chan type, n int)创建一个缓冲区大小为n的channel,超过n才会阻塞

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var c chan int //c == nil
    var c chan int = make(chan int)
    c := make(chan int)

    func channel() {
    c := make(chan int)

    go func() {
    for {
    n := <-c
    fmt.Println(n)
    }
    }()
    c <- 1
    c <- 2
    }
    /*
    1
    2
    */

    不指明方向默认是双向的,可以指定方向

    1
    2
    chan<- int //只能发送
    <-chan int //只能接收
  2. channel 是可以close的
    永远是发送方close

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    func channel() {
    c := make(chan int)

    go func() {
    for {
    if n, ok := <-c; ok {
    fmt.Println(n)
    } else {
    break
    }
    }
    }()
    c <- 1
    c <- 2
    close(c)
    }

    除了用ok判断是否关闭还可以

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    func channel() {
    c := make(chan int)
    go func() {
    for n := range c {
    fmt.Println(n)
    }
    }()
    c <- 1
    c <- 2
    close(c)
    }
  3. select

    每个case都必须是一个通信

    所有channel表达式都会被求值

    所有被发送的表达式都会被求值

    如果任意某个通信可以进行,它就执行;其他被忽略。

    如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。

    否则:

    如果有default子句,则执行该语句。
    如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。

    1. 基础

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      func main() {
      c1 := make(chan int)
      c2 := make(chan int)
      go func() {
      for {
      c1 <- 1
      c2 <- 2
      time.Sleep(time.Duration(rand.Intn(1500)) * time.Millisecond)
      }
      }()
      tick := time.Tick(time.Second)
      end := time.After(3 * time.Second)
      for {
      select {
      case n := <-c1:
      fmt.Println("c1:", n)
      case n := <-c2:
      fmt.Println("c2:", n)
      case t := <-tick:
      fmt.Println("tick: ", t)
      case <-end:
      fmt.Println("bye")
      return
      }
      }
      }
      /*
      c1 -> 1
      c2 -> 2
      c1 -> 1
      c2 -> 2
      c1 -> 1
      c2 -> 2
      tick
      c1 -> 1
      c2 -> 2
      c1 -> 1
      c2 -> 2
      tick
      c1 -> 1
      c2 -> 2
      c1 -> 1
      c2 -> 2
      tick
      bye
      */
    2. time 库

      1
      2
      time.After(d Duration) <-chan Time //d时间后发送一个channel
      time.Tick(d Duration) <-chan Time //每d时间发送一个channel
    3. 传统同步机制

      使用共享内存来通信

      WaitGroup

      Mutex

      Cond

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      type atomicInt struct {
      value int
      mutex sync.Mutex
      }

      func (i *atomicInt) increment() {
      i.mutex.Lock()
      defer i.mutex.Unlock()
      i.value++
      }

      func (i *atomicInt) get() int {
      i.mutex.Lock()
      defer i.mutex.Unlock()
      return i.value
      }
      func main() {
      i := atomicInt{}
      fmt.Println(i.get())
      go func() {
      for ii := 0; ii < 10; ii++ {
      i.increment()
      }
      }()
      for ii := 0; ii < 10; ii++ {
      i.increment()
      }
      time.Sleep(time.Second)
      fmt.Println(i.get())
      }