亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Go 通道:為什么有兩個不同的輸出?

Go 通道:為什么有兩個不同的輸出?

Go
森林海 2021-11-01 16:02:40
我正在嘗試了解 Go 中的頻道。這是一個代碼示例:package mainimport "fmt"func main() {    m := make(map[int]string)    m[2] = "First Value"    c := make(chan bool)    go func() {        m[2] = "Second Value"        c <- true    }()    fmt.Printf("1-%s\n", m[2])    fmt.Printf("2-%s\n", m[2])    _ = <-c    fmt.Printf("3-%s\n", m[2])    fmt.Printf("4-%s\n", m[2])}有時上述代碼的輸出是(結果 1):1-First Value2-First Value3-Second Value4-Second Value但有時我得到(結果 2):1-First Value2-Second Value3-Second Value4-Second Value更改c := make(chan bool)為 后c := make(chan bool, 1),出現同樣的情況:有時結果 1,有時結果 2。為什么?
查看完整描述

2 回答

?
心有法竹

TA貢獻1866條經驗 獲得超5個贊

你的結果是完全合理的。由于 goroutine 相互獨立運行,您永遠不會知道 goroutine 何時開始執行。只要行


m[2] = "Second Value"

執行后,它將反映在您的主要 go 例程中。


因此,當在程序的第一次和第二次打印之間執行上述行時,您會看到結果為


1-First Value

2-Second Value

3-Second Value

4-Second Value

當它不是你看到另一個。在第三次打印之前,您確保其他 go 例程已完成。


如果你稍微修改你的程序,只是為了更清除它


package main


import "fmt"

import "time"


func main() {

    m := make(map[int]string)

    m[2] = "First Value"

    c := make(chan bool)

    go func() {

        m[2] = "Second Value"

        c <- true

    }()

    time.Sleep(time.Second)

    fmt.Printf("1-%s\n", m[2])

    fmt.Printf("2-%s\n", m[2])

    _ = <-c

    fmt.Printf("3-%s\n", m[2])

    fmt.Printf("4-%s\n", m[2])

}

Playground


您很可能會得到以下輸出


1-Second Value

2-Second Value

3-Second Value

4-Second Value

希望能幫助到你。


查看完整回答
反對 回復 2021-11-01
?
慕慕森

TA貢獻1856條經驗 獲得超17個贊

您的代碼實際上只是確保第三次和第四次打印顯示第二個值。當您將通道更改為緩沖區為 1 時,它并沒有真正改變任何東西。

那么我們來看第一種情況。您有一個無緩沖的頻道。您觸發的 go 例程會更改地圖的內容。但是您不知道調度程序何時會運行它。這就是為什么有時您會看到一個結果,而有時會看到另一個結果。call:_ = <-c將確保 go 例程已經運行。因為這個調用會阻塞,直到 go 例程實際在通道上寫了一些東西。這就是為什么您永遠不會在最后 2 次打印中看到“第一個值”的原因。

當您使用緩沖通道時,唯一會改變的是 go 例程將在寫入通道后立即退出。沒有別的(在Effective Go上閱讀)。


查看完整回答
反對 回復 2021-11-01
  • 2 回答
  • 0 關注
  • 238 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號