Channel:Goroutine和Goroutine之间的双向通道。
    Channel是一等公民,可以作为参数,也可以作为返回值。

    示例一:
    在这段代码中,c是主程序和worker()这两个Goroutine之间的双向通道。

    1. package main
    2. import "fmt"
    3. func worker(c chan int) {
    4. for {
    5. // 从channel收数据
    6. n := <-c
    7. fmt.Println(n)
    8. }
    9. }
    10. func chanDemo() {
    11. // var c chan int // 定义channel,此时c == nil
    12. c := make(chan int) // 创建channel
    13. go worker(c)
    14. // 向channel发数据
    15. c <- 1
    16. c <- 2
    17. time.Sleep(time.Millisecond)
    18. }
    19. func main() {
    20. chanDemo()
    21. // 1
    22. // 2
    23. }

    示例二:
    在这段代码中,通道channels[i]是主程序和worker(i, channels[i])这两个Goroutine之间的双向通道。

    1. package main
    2. import "fmt"
    3. func worker(id int, c chan int) {
    4. for {
    5. fmt.Printf("Worker %d received %c\n", id, <-c)
    6. }
    7. }
    8. func chanDemo() {
    9. var channels [10]chan int
    10. for i := 0; i < 10; i++ {
    11. channels[i] = make(chan int)
    12. go worker(i, channels[i])
    13. }
    14. for i := 0; i < 10; i++ {
    15. channels[i] <- 'a' + i
    16. }
    17. for i := 0; i < 10; i++ {
    18. channels[i] <- 'A' + i
    19. }
    20. time.Sleep(time.Millisecond)
    21. }
    22. func main() {
    23. chanDemo()
    24. // Worker 0 received a
    25. // Worker 0 received A
    26. // Worker 4 received e
    27. // Worker 5 received f
    28. // Worker 6 received g
    29. // Worker 7 received h
    30. // Worker 8 received i
    31. // Worker 1 received b
    32. // Worker 1 received B
    33. // Worker 9 received j
    34. // Worker 3 received d
    35. // Worker 2 received c
    36. // Worker 2 received C
    37. // Worker 5 received F
    38. // Worker 3 received D
    39. // Worker 4 received E
    40. // Worker 7 received H
    41. // Worker 6 received G
    42. // Worker 8 received I
    43. // Worker 9 received J
    44. }

    示例三:

    package main
    
    import "fmt"
    
    func createWorker(id int) chan int {
        c := make(chan int)
        go func() {
            for {
                fmt.Printf("Worker %d received %c\n", id, <-c)
            }
        }()
        return c
    }
    
    func chanDemo() {
        var channels [10]chan int
        for i := 0; i < 10; i++ {
            channels[i] = createWorker(i)
        }
        for i := 0; i < 10; i++ {
            channels[i] <- 'a' + i
        }
        for i := 0; i < 10; i++ {
            channels[i] <- 'A' + i
        }
        time.Sleep(time.Millisecond)
    }
    
    func main() {
        chanDemo() 
        // Worker 0 received a
        // Worker 0 received A
        // Worker 4 received e
        // Worker 5 received f
        // Worker 6 received g
        // Worker 7 received h
        // Worker 8 received i
        // Worker 1 received b
        // Worker 1 received B
        // Worker 9 received j
        // Worker 3 received d
        // Worker 2 received c
        // Worker 2 received C
        // Worker 5 received F
        // Worker 3 received D
        // Worker 4 received E
        // Worker 7 received H
        // Worker 6 received G
        // Worker 8 received I
        // Worker 9 received J
    }
    

    示例四:
    还可以对channel进行修饰,告诉别人channel应该怎么使用:
    chan<- int 表示 channel是用来送数据的,只能给该channel发数据
    <-chan int 表示 channel是用来收数据的,只能从该channel收数据

    package main
    
    import "fmt"
    
    func createWorker(id int) chan<- int {
        c := make(chan int)
        go func() {
            for {
                fmt.Printf("Worker %d received %c\n", id, <-c)
            }
        }()
        return c
    }
    
    func chanDemo() {
        var channels [10]chan<- int
        for i := 0; i < 10; i++ {
            channels[i] = createWorker(i)
        }
        for i := 0; i < 10; i++ {
            channels[i] <- 'a' + i
        }
        for i := 0; i < 10; i++ {
            channels[i] <- 'A' + i
        }
        time.Sleep(time.Millisecond)
    }
    
    func main() {
        chanDemo() 
        // Worker 0 received a
        // Worker 0 received A
        // Worker 4 received e
        // Worker 5 received f
        // Worker 6 received g
        // Worker 7 received h
        // Worker 8 received i
        // Worker 1 received b
        // Worker 1 received B
        // Worker 9 received j
        // Worker 3 received d
        // Worker 2 received c
        // Worker 2 received C
        // Worker 5 received F
        // Worker 3 received D
        // Worker 4 received E
        // Worker 7 received H
        // Worker 6 received G
        // Worker 8 received I
        // Worker 9 received J
    }
    

    Buffered channel:
    channel还可以设置缓冲区

    package main
    
    import "fmt"
    
    func worker(id int, c chan int) {
        for {
            fmt.Printf("Worker %d received %c\n", id, <-c)
        }
    }
    
    func createWorker(id int) chan<- int {
        c := make(chan int)
        go worker(id, c)
        return c
    }
    
    func bufferedChannel() {
        c := make(chan int, 3)
        // 缓冲区大小为3,可以往里面发三个数而不需要人收,提升性能
        go worker(0, c)
        c <- 'a'
        c <- 'b'
        c <- 'c'
        c <- 'd'
        time.Sleep(time.Millisecond)
    }
    
    func main() {
        bufferedChannel()
        // Worker 0 received a
        // Worker 0 received b
        // Worker 0 received c
        // Worker 0 received d
    }
    

    Channel close:
    发送方可以close channel,以通知接收方没有新数据要发送了

    package main
    
    import "fmt"
    
    func worker(id int, c chan int) {
        // 当发送方close channel时,接收方仍然能接收到数据,接收的是channel里数据类型的零值,
        // 如int类型为0,string类型为空串
    
        // 当发送方close channel时,接收方有两种应对策略
        // 方法1:用ok变量来判断channel是否close
        for {
            n, ok := <- c
            if !ok {
                break
            }
            fmt.Printf("Worker %d received %d\n", id, n)
        }
        // 方法2:使用range
        for n := range c {
            fmt.Printf("Worker %d received %d\n", id, n)
        }
    }
    
    func createWorker(id int) chan<- int {
        c := make(chan int)
        go worker(id, c)
        return c
    }
    
    func channelClose() {
        c := make(chan int)
        go worker(0, c)
        c <- 'a'
        c <- 'b'
        c <- 'c'
        c <- 'd'
        close(c)
        time.Sleep(time.Millisecond)
    }
    
    func main() {
        channelClose()
        // Worker 0 received 97
        // Worker 0 received 98
        // Worker 0 received 99
        // Worker 0 received 100
    }
    

    channel的设计理念:
    不要通过共享内存来通信;通过通信来共享内存。