---
title: 提早返回的管線
aliases: [阻塞的 producer]
type: note
status: draft
domain: go
topics: [channel, goroutine, 取消]
based_on: ["可以取消的管線"]
created: 2026-09-22
lang: zh-Hant
---

producer 計算三個平方，消費者只取第一個。剩下的 send 會怎樣？

```go
package main

import (
    "fmt"
    "time"
)

func squares() (<-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} {
            out <- n * n
        }
    }()
    return out, done
}

func main() {
    values, done := squares()
    fmt.Println(<-values)
    select {
    case <-done:
        fmt.Println("stopped")
    case <-time.After(50 * time.Millisecond):
        fmt.Println("still blocked")
    }
}
```

儲存為 `main.go`，執行 `go run main.go`。Go 1.27.0 的輸出：

```text
1
still blocked
```

## 卡在第二次 send

無緩衝的 `out` 需要接收方。第一個值交出後，沒有人接第二個值；producer 無法返回，兩個 `defer` 也尚未執行。

50 ms 只讓範例顯示結果，並沒有修復阻塞。這個短程式會隨 `main` 結束；若相同模式用在持續運行的服務中，工作就會一直留著。

~~加一格 buffer 就能取消工作。~~ 它只能暫存一個值，第三次 send 仍會阻塞。

[[可以取消的管線]] 加入取消訊號，並等待 producer 收尾。兩份程式的差別在 send 的出口。
