Skip to content

chan / 通道

go
// 定义通道
messages := make(chan string)

// 发
go func() { messages <- "ping" }()

// 接收
msg := <-messages

缓冲通道

go
messages := make(chan string, 2)

只写 && 只写

https://gobyexample-cn.github.io/channel-directions

chan int        // 双向
<-chan int      // 只读
chan<- int      // 只写

主要是通过“变量类型”实现的,但不只是

go
ch := make(chan int)

var readOnly <-chan int = ch
var writeOnly chan<- int = ch

遍历通道

go
    queue := make(chan string, 2)
    queue <- "one"
    queue <- "two"
    close(queue) // 没有 close 会一直卡住

    for elem := range queue {
        fmt.Println(elem)
    }

channel 关闭且缓冲已空,会直接结束

超时

time.After

触发超时

go
    c1 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c1 <- "result 1"
    }()

    select {
    case res := <-c1:
        fmt.Println(res)
    case <-time.After(1 * time.Second):
        fmt.Println("timeout 1")
    }

未触发超时

go

    c2 := make(chan string, 1)
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "result 2"
    }()
    select {
    case res := <-c2:
        fmt.Println(res)
    case <-time.After(3 * time.Second):
        fmt.Println("timeout 2")
    }

关闭通道

close 的含义是 “不会再有新的数据发送了”

go
jobs := make(chan int, 5)

close(jobs)

close 只是标记 channel 为“已关闭”, 不是销毁,不是清空,也不是立刻释放内存。

close 做了三件事:

  1. 标记 channel 状态为 closed
  2. 唤醒所有正在等待接收的 goroutine
  3. 后续再写入会 panic
go
v, ok := <-jobs
// ok == false 已经关闭 且 无数据

已经关闭,且无值,读空后得到零值

通道同步

https://gobyexample-cn.github.io/channel-synchronization

本质是利用通道的堵塞功能

go

func worker(done chan bool) {
    fmt.Print("working...")
    time.Sleep(time.Second)
    fmt.Println("done")

    done <- true
}

func main() {

    done := make(chan bool, 1)
    go worker(done)

    <-done
}