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

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

通道中缺少數據

通道中缺少數據

Go
料青山看我應如是 2023-05-15 10:35:40
我寫了一個小程序來練習go channel。package mainimport (    "log"    "strconv")var MaxOutstanding int = 1var channelSize int = 10var sem = make(chan int, MaxOutstanding)type Request struct {    command string    data    string}func process(req *Request) {    log.Println(req)}func serve(reqs chan *Request) {    for req := range reqs {        sem <- 1        go func() {            process(req)            <-sem        }()    }}func main() {    reqs := make(chan *Request, channelSize)    for i := 0; i < channelSize; i++ {        req := &Request{"start", strconv.Itoa(i)}        reqs <- req    }    close(reqs)    serve(reqs)}這打印2018/12/02 16:52:30 &{start 1}2018/12/02 16:52:30 &{start 2}2018/12/02 16:52:30 &{start 3}2018/12/02 16:52:30 &{start 4}2018/12/02 16:52:30 &{start 5}2018/12/02 16:52:30 &{start 6}2018/12/02 16:52:30 &{start 7}2018/12/02 16:52:30 &{start 8}2018/12/02 16:52:30 &{start 9}因此,不會打印 &{start 0}。為什么這個不見了?
查看完整描述

2 回答

?
斯蒂芬大帝

TA貢獻1827條經驗 獲得超8個贊

因為在serve()你的循環變量中使用了你在一個單獨的 goroutine 上執行的函數文字,它被運行循環的 goroutine 同時修改:數據競爭。如果您有數據競爭,則行為是未定義的。


如果您復制變量,它將起作用:


for req := range reqs {

? ? sem <- 1

? ? req2 := req

? ? go func() {

? ? ? ? process(req2)

? ? ? ? <-sem

? ? }()

}

在Go Playground上嘗試一下。


另一種可能性是將其作為參數傳遞給匿名函數:


for req := range reqs {

? ? sem <- 1

? ? go func(req *Request) {

? ? ? ? process(req)

? ? ? ? <-sem

? ? }(req)

}

在Go Playground試試這個。

查看完整回答
反對 回復 2023-05-15
?
拉丁的傳說

TA貢獻1789條經驗 獲得超8個贊

這是因為當匿名執行時,請求已經從移動Request{0}到Request{1},所以你打印從{start 1}。


// method 1: add a parameter, pass it to anonymous function

func serve(reqs chan *Request) {

    for req := range reqs {

        sem <- 1


        // You should make the req as parameter of this function

        // or, when the function execute, the req point to Request{1}

        go func(dup *Request) {

            process(dup)

            <-sem

        }(req)

    }


    // And you should wait for the Request{9} to be processed

    time.Sleep(time.Second)

}


// method 2: make for wait anonymous function

func serve(reqs chan *Request) {

    for req := range reqs {

        go func() {

            process(req)

            sem <- 1

        }()


        // Or wait here

        <-sem

    }

}


查看完整回答
反對 回復 2023-05-15
  • 2 回答
  • 0 關注
  • 145 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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