go语言channle使用总结

前言:

channel 提供了一种通信机制,通过它,一个 goroutine 可以想另一 goroutine 发送消息。channel 本身还需关联了一个类型,也就是 channel 可以发送数据的类型。例如: 发送 int 类型消息的 channel 写作 chan int 。channel 很强大,但是还是有点坑,下面是我个人的总结。

1.使用两个值接收 channel:

<- channel 能够返回一个值或者 两个值,当返回两个值的时候 ,第二个是一个bool 变量,如果为 false ,就说明这个 channel 被关闭了。被关闭了的 channel ,会不断的 返回 该 channle 类型的 零值 和false,应该在代码 层面做好预防。

unc main () {
    can := make(chan int ,8)
    can <- 1
    can <- 1
    can <- 1

    close(can)
    for {
        select {
        case tem := <- can:
            fmt.Println(tem)
            time.Sleep(time.Second)
        }
    }
}

就比如 这段代码,当can 被读取完管道里面的数据同时是关闭状态的时候,并不会像我们预期的想法那样阻塞住,反而不断的 返回零值。。

func main () {
    can := make(chan int ,8)
    can <- 1
    can <- 1
    can <- 1

    close(can)
    for {
        select {
        case tem ,fla:= <- can:
            if fla == false {
                //can = nil 如果这样的 select 就不会一直返回了,
                // select 的 一个 nil的 channle就会阻塞住
                return
            } else {
                fmt.Println(tem)
            }
            time.Sleep(time.Second)
        }
    }
}

改成 这样我们就能完美 解决该问题了。

2.使用for range 代替 select:

select 能够同时监听 多个channle的 返回值,但是很多时候我们只是一个协程 监听一个 channle,这个时候我们不如 用for range。

func main () {
    can := make(chan int ,8)
    can <- 1
    can <- 1
    can <- 1

    close(can)
/*  for {
        select {
        case tem ,fla:= <- can:
            if fla == false {
                //can = nil 如果这样的 select 就不会一直返回了,
                //select 的 一个 nil的 channle就会阻塞住
                return
            } else {
                fmt.Println(tem)
            }
            time.Sleep(time.Second)
        }
    }
*/
    for i := range can {
        fmt.Println(i)
    }
}

当 for range 一个 channle ,如果 该 channle没有被关闭,会一直阻塞,如果 关闭了,会自动退出循环,很方便。代码简洁了很多!

3.channle不仅仅是队列:

channle 分为有缓存 和无缓存类型。

  1. 有缓存 channle 是一个消费队列。
  2. 无缓冲的channle 也可以当用。
  3. channle 因为能够 缓冲数据,所以还很适合 当连接池来用。

具体怎么实现,大家自己可以网上找找资料。

总结:

以上就是我对channle的认识了,有啥不对的,欢迎留言

你可能感兴趣的:(go语言channle使用总结)