簡體   English   中英

優雅地停止被阻塞的 goroutine

[英]Stop goroutine that is blocked gracefully

我有一個經常被阻止讀取標准輸入的 goroutine,如下所示:

func routine() {
    for {
        data := make([]byte, 8)
        os.Stdin.Read(data);
        otherChannel <-data
    }
}

該例程等待通過 stdin 讀取 8 個字節並饋送另一個通道。

我想從主線程優雅地停止這個 goroutine。 然而,由於 goroutine 幾乎總是被阻止從 stdin 讀取,我找不到一個好的解決方案來強制它停止。 我想過這樣的事情:

func routine(stopChannel chan struct{}) {
    for {
        select {
        case <-stopChannel:
            return
        default:
            data := make([]byte, 8)
            os.Stdin.Read(data);
            otherChannel <-data
        }
    }
}

但是,問題是,如果在stopChannel關閉時 stdin 中沒有更多輸入,goroutine 將保持阻塞狀態並且不會返回。

有什么好的方法可以讓它在主線程需要時立即返回嗎?

謝謝。

要檢測os.Stdin是否已關閉:檢查os.Stdin.Read()返回的錯誤值。

額外的一點:盡管您聲明在您的情況下您將始終收到 8 個字節的塊,但您仍應檢查您是否確實收到了 8 個字節的數據。

func routine() {
    for {
        data := make([]byte, 8)
        n, err := os.Stdin.Read(data)

        // error handling : the basic thing to do is "on error, return"
        if err != nil {
            // if os.Stdin got closed, .Read() will return 'io.EOF'
            if err == io.EOF {
                log.Printf("stdin closed, exiting")
            } else {
                log.Printf("stdin: %s", err)
            }
            return
        }

        // check that 'n' is big enough :
        if n != 8 {
            log.Printf("short read: only %d byte. exiting", n)
            return  // instead of returning, you may want to keep '.Read()'ing
                    // or you may use 'io.ReadFull(os.Stdin, data)' instead of '.Read()'
        }

        // a habit to have : truncate your read buffers to 'n' after a .Read()
        otherChannel <-data[:n]
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM