简体   繁体   中英

golang read and write from same channel

The problem code is:

go func() {
    defer wg.Done()
    for {
        task := <-tasks

        if task.Attemts >= .5 {
            tasks <- task # <- error
        }

        Println(task)
    }
}()

Tasks filling with tasks <- Task{"1", rand.Float64()} in another loop.

And now we've got deadlock...

Full example: https://play.golang.org/p/s1pnb1Mu_Y

The point of my code is - create web scraper , which one will try to parse urls after fails. Take some attempts and then drop url.

Might be in golang we have some more ideomatic way to solve this problem, cuz i don't know.

You are using a nonbuffered channel so when you try to send with tasks <- task execution in that goroutine sits there waiting for something else to read on the channel. Since nothing else is reading on the channel you get a deadlock.

The only way to make this specific code work is to have a fully dedicated consumer or use a buffered channel. Even with a buffered channel here you could get a deadlock if the buffer fills up at the point your single consumer tries to send on it.

If you really need to send from that same goroutine you're going to have to spawn a new goroutine just to send it. Something along the lines of

go func() {
    tasks <- task
}()

Or you could have something like this:

requeue = make(chan Task) // could buffer if you want
go func() {
    for {
        tasks <- requeue
    }
}()
for {
    task := <-tasks

    if task.Attemts >= .5 {
        requeue <- task
    }

    Println(task)
}

Handling the closing of that channel and the like of course.

If this is the only goroutine reading from the channel, it cannot also write to it.

It is possible if you used a buffered channel, it would sort of work for a little bit, but that would only push your problem back. What you really want to do is likely use

go func(){
   tasks <- task
}()

instead of the simple tasks <- task . That will offload the writing to another goroutine, so this one can go right back to reading.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM