最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Go語言簡單模擬Python的生成器

 更新時(shí)間:2015年08月12日 12:06:07   作者:taowen  
這篇文章主要介紹了使用Go語言簡單模擬Python的生成器,Python的generator是非??岬墓δ?用Go實(shí)現(xiàn)的代碼也較為簡潔,需要的朋友可以參考下
def demo_input_and_output():
  input = yield 'what is the input?'
  yield 'input is: %s' % input

gen = demo_input_and_output()
print(gen.next())
print(gen.send(42))

這段代碼演示了 python generator 的功能??梢钥吹?yield 同時(shí)做了兩個(gè)操作,一個(gè)是往外發(fā)數(shù)據(jù) "waht is the input",同時(shí)做的操作是往里收數(shù)據(jù) input。而且這個(gè)接收數(shù)據(jù)的操作是一個(gè)阻塞的操作,如果外部沒有調(diào)用 next() (也就是往里傳遞None),或者調(diào)用send(42)(也就是往里傳遞42這個(gè)值),那么這個(gè)阻塞的操作就會(huì)一直等待下去。

也就是說 python 的 generator 自帶了一個(gè)對(duì)外通信的 channel,用于收發(fā)消息。用 go 模擬 python 的 generator 的話寫起來就是這樣的

復(fù)制代碼 代碼如下:
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 版本基本上等價(jià)。隱含的 channel 在 go 版本里變成顯式的了。yield 變成了 channel <- 操作,同時(shí)立馬做了一個(gè) <- channel 的阻塞讀操作。這也就是 yield 的本質(zhì)吧。

go 的 channel 也可以當(dāng)成 iterator 被 for 循環(huán)使用:

復(fù)制代碼 代碼如下:
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 <- 不等價(jià)于 yield,它會(huì)往下執(zhí)行直到阻塞。效果是

復(fù)制代碼 代碼如下:
after a
a
c
after c
after b
b

這和預(yù)期的順序不一樣。這里沒有把 after a after c after b 都打印出來是因?yàn)?channel 默認(rèn)只有一個(gè)元素的buffer,所以寫入了一個(gè)就阻塞了。如果增大 buffer,那么就有效果了

復(fù)制代碼 代碼如下:
make(chan string, 10)

輸出變成了:

after a
after c
after b
a
c
b

可見 goroutine 就好象一個(gè)獨(dú)立的線程一樣自己和自己玩去了,不用等待被執(zhí)行。如果要模擬 yield 就要加上顯示的同步操作(從 channel 里阻塞讀取信號(hào)):

復(fù)制代碼 代碼如下:
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 <- ""
    }
}

輸出的結(jié)果就是

a
after a
c
after c
b
after b

到這里我們可以看到,python 的 generator 就好象是 golang 的 goroutine 帶了一個(gè)無buffer的channel。這樣導(dǎo)致每次yield一個(gè)值,都會(huì)產(chǎn)生一次協(xié)程上下文切換。雖然協(xié)程上下文切換很廉價(jià),但是也不是沒有成本。像 goroutine 的 buffered channel 這樣的設(shè)計(jì),可以讓一個(gè) goroutine 一次性多產(chǎn)生一些輸出再阻塞等待,而不是產(chǎn)生一個(gè)輸出就阻塞等待一下,再產(chǎn)生另外一個(gè)輸出。golang rocks!

相關(guān)文章

  • Go常用標(biāo)準(zhǔn)庫之fmt的簡介與使用詳解

    Go常用標(biāo)準(zhǔn)庫之fmt的簡介與使用詳解

    fmt 是 Go 語言中的一個(gè)常用標(biāo)準(zhǔn)庫,它用于格式化輸入和輸出數(shù)據(jù),這篇文章主要為大家介紹了fmt的基本使用,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-10-10
  • GO語言文件的創(chuàng)建與打開實(shí)例分析

    GO語言文件的創(chuàng)建與打開實(shí)例分析

    這篇文章主要介紹了GO語言文件的創(chuàng)建與打開的具體用法,實(shí)例分析了GO語言文件創(chuàng)建與打開操作中所涉及的函數(shù)具體用法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12
  • Go語言指針訪問結(jié)構(gòu)體的方法

    Go語言指針訪問結(jié)構(gòu)體的方法

    這篇文章主要介紹了Go語言指針訪問結(jié)構(gòu)體的方法,涉及Go語言指針及結(jié)構(gòu)體的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • Go語言常用的打log方式詳解

    Go語言常用的打log方式詳解

    Golang的log包短小精悍,可以非常輕松的實(shí)現(xiàn)日志打印轉(zhuǎn)存功能,下面這篇文章主要給大家介紹了關(guān)于Go語言常用的打log方式的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • Golang Printf,Sprintf,Fprintf 格式化詳解

    Golang Printf,Sprintf,Fprintf 格式化詳解

    這篇文章主要介紹了Golang Printf,Sprintf,Fprintf 格式化詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Golang中的四個(gè)括號(hào)示例詳解

    Golang中的四個(gè)括號(hào)示例詳解

    這篇文章主要介紹了Golang中的四個(gè)括號(hào),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),通過實(shí)例代碼補(bǔ)充介紹了有效的括號(hào)golang實(shí)現(xiàn),需要的朋友可以參考下
    2024-03-03
  • 一文詳解Go中方法接收器的選擇

    一文詳解Go中方法接收器的選擇

    許多 Go 初學(xué)者在方法接收器的選擇上可能會(huì)感到困惑,不知道該選擇值接收器還是指針接收器。本文將會(huì)對(duì)方法接收器進(jìn)行介紹,并給出如何選擇正確方法接收器的指導(dǎo)建議,希望對(duì)大家有所幫助
    2023-04-04
  • 如何控制Go編碼JSON數(shù)據(jù)時(shí)的行為(問題及解決方案)

    如何控制Go編碼JSON數(shù)據(jù)時(shí)的行為(問題及解決方案)

    今天來聊一下我在Go中對(duì)數(shù)據(jù)進(jìn)行 JSON 編碼時(shí)遇到次數(shù)最多的三個(gè)問題以及解決方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-02-02
  • 詳解如何在Go項(xiàng)目中輸出版本信息

    詳解如何在Go項(xiàng)目中輸出版本信息

    這篇文章主要介紹了詳解如何在Go項(xiàng)目中輸出版本信息,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Golang發(fā)送http GET請(qǐng)求的示例代碼

    Golang發(fā)送http GET請(qǐng)求的示例代碼

    這篇文章主要介紹了Golang發(fā)送http GET請(qǐng)求的示例代碼,幫助大家更好的理解和使用golang,感興趣的朋友可以了解下
    2020-12-12

最新評(píng)論

皮山县| 都江堰市| 杨浦区| 任丘市| 揭西县| 贡嘎县| 田东县| 准格尔旗| 尼勒克县| 佛冈县| 民县| 当雄县| 布尔津县| 布拖县| 夹江县| 寻乌县| 诸城市| 嵊泗县| 鹤壁市| 天峨县| 凤阳县| 和硕县| 迁西县| 垦利县| 宜阳县| 门头沟区| 高要市| 新津县| 邢台县| 泸州市| 根河市| 赤壁市| 嵊州市| 平泉县| 白沙| 郯城县| 海盐县| 乐业县| 两当县| 徐汇区| 卫辉市|