Go 第13章 channel Go 第13章 channel

2021-06-09

channel 是 goroutine 之间的通讯桥梁

https://file.lulublog.cn/images/3/2023/09/h4PjsM9Rcs6S9R3s840SNG8CR4s40z.jpg

定义chan 分为五种

  • 可读可取 c:=make(chan int)

  • 可读 var readChan <-chan int = c

  • 可取 var setChan chane<- int = c

  • 有缓冲 c:=make(chan int,5)

  • 无缓冲 c:=make(chan int)

有缓冲 c:=make(chan int,5)

package main

import "fmt"

func main() {
    c := make(chan int, 1)
    c <- 1
    fmt.Println(<-c)
}

无缓冲 c:=make(chan int),可在设置 channel 和 获取 channel 打断点进行调试

c := make(chan int)
go func() {
    c <- 1
}()
fmt.Println(<-c)

有缓冲 c:=make(chan int,5),可在设置 channel 和 获取 channel 打断点进行调试

package main

import "fmt"

func main() {
    c := make(chan int, 5)
    go func() {
       for i := 1; i <= 5; i++ {
          c <- i
       }
    }()
    for i := 1; i <= 5; i++ {
       fmt.Println(<-c)
    }
}

无缓冲 c:=make(chan int),可在设置 channel 和 获取 channel 打断点进行调试

package main

import "fmt"

func main() {
    c := make(chan int)
    go func() {
       for i := 1; i <= 5; i++ {
          c <- i
       }
    }()
    for i := 1; i <= 5; i++ {
       fmt.Println(<-c)
    }
}

可读可写

package main

import "fmt"

func main() {
    c := make(chan int, 5)
    var readC <-chan int = c
    var writeC chan<- int = c
    writeC <- 1
    fmt.Println(<-readC)
}

关闭 channel:channel 开启以后是可以 close 的,当你觉得不再需要并且已经 set 完成的时候,你就需要去 close 它

package main

import "fmt"

func main() {
    c := make(chan int, 3)
    c <- 1
    c <- 2
    c <- 3
    close(c)
    fmt.Println(<-c)
    fmt.Println(<-c)
    fmt.Println(<-c)
}

需要注意,如果用到了 range 则必须在 range 之前就给它关闭

package main

import "fmt"

func main() {
    c := make(chan int, 3)
    c <- 1
    c <- 2
    c <- 3
    close(c)
    for v := range c {
       fmt.Println(v)
    }
}

select:每次执行打印的结果可能不一致

package main

import "fmt"

func main() {
    c1 := make(chan int, 1)
    c2 := make(chan int, 1)
    c3 := make(chan int, 1)
    c1 <- 1
    c2 <- 1
    c3 <- 1
    select {
    case <-c1:
       fmt.Println("c1")
    case <-c2:
       fmt.Println("c2")
    case <-c3:
       fmt.Println("c3")
    default:
       fmt.Println("c0")
    }
}

channel 是 goroutine 之间的通讯桥梁:

package main

import "fmt"

func main() {
    c := make(chan int)
    var readC <-chan int = c
    var writeC chan<- int = c
    go SetChan(writeC)
    GetChan(readC)
}

func SetChan(writeC chan<- int) {
    for i := 1; i <= 5; i++ {
       fmt.Println("writeCBefore")
       writeC <- i
       fmt.Println("writeCAfter")
    }
}

func GetChan(readC <-chan int) {
    for i := 1; i <= 5; i++ {
       fmt.Println(<-readC)
    }
}

执行结果

writeCBefore
writeCAfter
writeCBefore
1
2
writeCAfter
writeCBefore
writeCAfter
writeCBefore
3
4
writeCAfter
writeCBefore
writeCAfter
5

结果解释:因为这个是无缓冲区的。如果设置为 1 缓冲区则会开始交替时执行,这是因为在遇到向 channel 写入值,是否往下执行是交替的,也就是说是随机的,原因是因为协程都是利用同一 cpu 在不同时间片上运行的

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开微信扫一扫,即可进行扫码打赏哦

阅读 815