如何安全关闭channel

我现在有N个goroutine和一个channel,一个读channel,其它的都是写,我想安全的关闭这个channel请问怎么做?

共 5 个回复


stevewang

先把写的goroutine停下来就可以安全关闭channel了。 例如:

package main
import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    ch := make(chan int, 1)
    send := func(m, n int) {
        for i := m; i <= n; i++ {
            ch <- i
        }
        wg.Done()
    }
    wg.Add(3)
    go send(1, 10)
    go send(11, 20)
    go send(21, 30)
    go func() {
        for {
            n, ok := <-ch
            if !ok {
                return
            }
            fmt.Println(n)
        }
    }()
    wg.Wait()
    close(ch)
}
# 0

xiaolongren25

关键是不知道会有多少个goroutine去写channel,goroutine的数目是动态的

# 1

stevewang

用一个channel做控制就可以,写的goroutine在这个channel上收到信号就退出。

package main
import (
    "fmt"
    "sync"
    "time"
)
func main() {
    var wg sync.WaitGroup
    exit := make(chan struct{})
    ch := make(chan int, 1)
    send := func(n int) {
        defer wg.Done()
        for {
            select {
            case ch <- n:
                time.Sleep(time.Second)
            case <-exit:
                return
            }
        }
    }
    wg.Add(10)
    // 10个goroutine写
    for i := 0; i < 10; i++ {
        go send(i)      
    }
    // 一个goroutine读
    go func() {
        for {
            n, ok := <-ch
            if !ok {
                return
            }
            fmt.Println(n)
        }
    }()
    time.Sleep(time.Second*10)
    close(exit)
    wg.Wait()
    close(ch)
}
# 2

bigbear

把一个channel作为关闭信号, 传入到所有channel中, 当处理的channel不再处理消息时, 发出信号. 其他的channel收到信号后, 停止发送信号.

# 3

zweite

使用sync/atomic包对channel管理

# 4