def demo_input_and_output(): input = yield 'what is the input"waht is the input",同时做的操作是往里收数据 input。而且这个接收数据的操作是一个阻塞的操作,如果外部没有调用 next() (也就是往里传递None),或者调用send(42)(也就是往里传递42这个值),那么这个阻塞的操作就会一直等待下去。也就是说 python 的 generator 自带了一个对外通信的 channel,用于收发消息。用 go 模拟 python 的 generator 的话写起来就是这样的
复制代码 代码如下:package main
import "fmt"
func demoInputAndOutput(channel chan string) {
channel <- "what is my input"
input := <- channel
channel <- fmt.Sprintf("input is: %s", input)
}func main() {
channel := make(chan string)
go demoInputAndOutput(channel)
fmt.Println(<- channel)
channel <- "42"
fmt.Println(<- channel)
}这段代码和 python 版本基本上等价。隐含的 channel 在 go 版本里变成显式的了。yield 变成了 channel <- 操作,同时立马做了一个 <- channel 的阻塞读操作。这也就是 yield 的本质吧。
go 的 channel 也可以当成 iterator 被 for 循环使用:
复制代码 代码如下:package main
import "fmt"
func someGenerator() <-chan string {
channel := make(chan string)
go func() {
channel <- "a"
fmt.Println("after a")
channel <- "c"
fmt.Println("after c")
channel <- "b"
fmt.Println("after b")
close(channel)
}()
return channel
}func main() {
channel := someGenerator()
for val := range channel {
fmt.Println(val)
}
}和 python 的 yield 不同,这里的 channel <- 不等价于 yield,它会往下执行直到阻塞。效果是
复制代码 代码如下:after a
a
c
after c
after b
b这和预期的顺序不一样。这里没有把 after a after c after b 都打印出来是因为 channel 默认只有一个元素的buffer,所以写入了一个就阻塞了。如果增大 buffer,那么就有效果了
复制代码 代码如下:make(chan string, 10)
输出变成了:
after a after c after b a c b可见 goroutine 就好象一个独立的线程一样自己和自己玩去了,不用等待被执行。如果要模拟 yield 就要加上显示的同步操作(从 channel 里阻塞读取信号):
复制代码 代码如下:package main
import "fmt"
func someGenerator() chan string {
channel := make(chan string)
go func() {
channel <- "a"
<- channel
fmt.Println("after a")
channel <- "c"
<- channel
fmt.Println("after c")
channel <- "b"
<- channel
fmt.Println("after b")
close(channel)
}()
return channel
}func main() {
channel := someGenerator()
for val := range channel {
fmt.Println(val)
channel <- ""
}
}输出的结果就是
a after a c after c b after b到这里我们可以看到,python 的 generator 就好象是 golang 的 goroutine 带了一个无buffer的channel。这样导致每次yield一个值,都会产生一次协程上下文切换。虽然协程上下文切换很廉价,但是也不是没有成本。像 goroutine 的 buffered channel 这样的设计,可以让一个 goroutine 一次性多产生一些输出再阻塞等待,而不是产生一个输出就阻塞等待一下,再产生另外一个输出。golang rocks!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
更新日志
- Parijat-BuddhaGarden《佛陀花园》[WAV+CUE]
- 证声音乐图书馆《巴莎诺瓦 惬意咖啡馆》[320K/MP3][220.56MB]
- 证声音乐图书馆《巴莎诺瓦 惬意咖啡馆》[FLAC/分轨][220.56MB]
- 群星《狂潮》夜店中文爆嗨重低音 黑胶碟2CD[低速原抓WAV+CUE]
- TraditionalMusicEnsembleofTheBNMA-BuddhistMusicoftheMingDynasty(JVC-Japan)[FLAC]
- [中国唱片]中央乐团交响乐队《绝烧HIFI典范》[WAV+CUE]
- 群星《2024好听新歌41》AI调整音效【WAV分轨】
- 张学友《吻别》MQA-UHQCD 日本压碟[原抓WAV+CUE][1G]
- 许嵩《寻宝游戏》[WAV+CUE][951M]
- 李玉刚《刚好遇见你》[WAV+CUE][970M]
- 罗文《国语精选》24K金碟限量版英皇娱乐[WAV+CUE][955M]
- 证声音乐图书馆《摇滚乐 海滩假期》[320K/MP3][50.75MB]
- 证声音乐图书馆《摇滚乐 海滩假期》[FLAC/分轨][273.06MB]
- 群星《情系民歌LP黑胶》2CD[WAV+CUE]
- 串烧歌曲《台语发烧热唱1国语发烧热唱2》2CD日版[WAV+CUE]