跳至主要內容
yomihon 書庫
整體狀況設定

鍵盤快捷鍵

⌘K / Ctrl K
搜尋
Esc
關閉搜尋或篩選
/
跳到導覽篩選(單鍵開啟時)
[
收合或展開側欄(單鍵開啟時)

關掉之後,/ 和 [ 都只會照瀏覽器原本的方式輸入;⌘K 與 Esc 不受影響。

設定
esc

↑↓ 選擇 ↵ 搜尋 esc 關閉

可以取消的管線

note檔案變更於
檔案變更於
類型
note
語言
zh-Hant
在 Obsidian 開啟留下自己的想法
檔案變更於
類型
note
語言
zh-Hant
在 Obsidian 開啟留下自己的想法
本頁內容 以這篇為來源的筆記 2 正文連到這篇 5

消費者只需要第一個平方。取到後,它通知 producer 停止,並等待收尾。

package main

import (
    "context"
    "fmt"
)

func squares(ctx context.Context) (<-chan int, <-chan struct{}) {
    out := make(chan int)
    done := make(chan struct{})
    go func() {
        defer close(done)
        defer close(out)
        for _, n := range []int{1, 2, 3} {
            select {
            case out <- n * n:
            case <-ctx.Done():
                return
            }
        }
    }()
    return out, done
}

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    values, done := squares(ctx)
    fmt.Println(<-values)
    cancel()
    <-done
    fmt.Println("stopped")
}

儲存為 main.go,執行 go run main.go。Go 1.27.0 的輸出:

1
stopped

兩個訊號,各管一件事

ctx.Done() 通知 producer 取消;done 關閉則表示 producer 已完成收尾。cancel() 本身不等待工作結束。

消費者不再接收時,send 無法繼續。取消訊號讓 select 走到 return,接著執行 defer:先關閉 out,再關閉 done。

誰關閉 channel

producer 是 out 的唯一發送者,由它關閉最容易確認不會再有 send。消費者直接關閉 out,反而可能讓 producer 向已關閉的 channel 發送而 panic。 ^owner

取消沒有優先權

若接收與取消同時可行,select 可能選中 send。本例取走第一個值後就不再接收,因此取消能解除後續 send 的阻塞。

這個模式只涵蓋 channel 等待;計算或 I/O 也必須提供自己的取消方式。1


  1. context.CancelFunc(另開分頁) 說明取消不等待工作停止;Go pipelines(另開分頁) 討論下游提早離開時,上游的退出責任。 ↩︎

作者標記的狀態 ready
設為 archived

設為 archived 之後,這裡不再有回到目前狀態的路。