为了账号安全,请及时绑定邮箱和手机立即绑定

通道中缺少数据

通道中缺少数据

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 关注
  • 102 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信