yield 到底是什么yield 翻成 Go(你熟的场景)
这个问题问得非常对位。
一句话先放这:
Go 里没有
yield关键字,但“yield 的能力是 Go 的一等公民”。
只是 实现方式完全不同,而且更偏工程、并发友好。
我按「语义 → 实现 → 对照 → 什么时候用哪个」给你讲。
yield 到底是什么def gen():
for i in range(3):
yield i
本质能力有三点:
channel + goroutine= Pythonyield
但注意:
Go 是 并发 push,Python 是 单线程 pull。
def gen():
for i in range(3):
yield i
for v in gen():
print(v)
func gen() <-chan int {
ch := make(chan int)
go func() {
defer close(ch)
for i := 0; i < 3; i++ {
ch <- i
}
}()
return ch
}
for v := range gen() {
fmt.Println(v)
}
| Python | Go |
|---|---|
yield v | ch <- v |
| generator | goroutine |
| StopIteration | close(ch) |
| for v in gen | for v := range ch |
| 能力 | Python yield | Go channel |
|---|---|---|
| 保存状态 | ✅ | ✅ |
| 惰性 | ✅ | ⚠️(依赖调度) |
| backpressure | ⚠️ | ✅ |
| 并发 | ❌ | ✅ |
| 多消费者 | ❌ | ✅ |
| select / cancel | ❌ | ✅ |
👉 Go 的方案是 工业级 yield。
func gen(yield func(int) bool) {
for i := 0; i < 3; i++ {
if !yield(i) {
return
}
}
}
使用:
gen(func(v int) bool {
fmt.Println(v)
return true
})
这在语义上更接近 Python,但:
Go 官方已经正面承认 yield 的价值。
import "iter"
func gen() iter.Seq[int] {
return func(yield func(int) bool) {
for i := 0; i < 3; i++ {
if !yield(i) {
return
}
}
}
}
使用方式:
for v := range gen() {
fmt.Println(v)
}
这已经是:
“官方 yield”
但目前:
👉 你的项目 100% 该用 channel
yield 翻成 Go(你熟的场景)while running:
frame = q.get()
yield frame
func stream(ctx context.Context, q <-chan []byte) <-chan []byte {
out := make(chan []byte)
go func() {
defer close(out)
for {
select {
case <-ctx.Done():
return
case frame, ok := <-q:
if !ok {
return
}
out <- frame
}
}
}()
return out
}
✔️ cancel
✔️ backpressure
✔️ graceful shutdown
Python 的
yield是“语言级控制流”
Go 的channel是“系统级数据流”
你从 Python 流式代码转 Go,
不是少了 yield,而是升级了模型。
如果你愿意,我可以下一步帮你:
你想从哪个继续?