这个问题问得非常对位。一句话先放这:
Go 里没有 yield 关键字,但“yield 的能力 是 Go 的一等公民”。
yield
yield 的能力
只是 实现方式完全不同,而且更偏工程、并发友好。
我按「语义 → 实现 → 对照 → 什么时候用哪个」给你讲。
def gen(): for i in range(3): yield i
本质能力有三点:
channel + goroutine = Python yield
channel + goroutine
但注意: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) }
yield v
ch <- v
close(ch)
for v := range ch
👉 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
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 是“系统级数据流”
channel
你从 Python 流式代码转 Go,不是少了 yield,而是升级了模型。
如果你愿意,我可以下一步帮你:
你想从哪个继续?
Github开源生信云平台 DEMO