简体   繁体   中英

not sure why this is deadlock in golang?

i'm new to Go not sure why this is deadlock ? i want to constantly be reading results from doSomething and storing it in the function read without using a for loop

func doSomething(c chan<- string){ // recursive function does something
    c <- result 
    return dosomething(c)  }

func reads(c <-chan string){
    results := ""   
    temp := <-c         
    results = results + "\n" + temp      
    return results
}

func main(){     
    go reads(c)
    doSomething(c)
}

Main gorouting is trying to write multiple times to a channel in doSomething function. The read function is reading the channel only once. Therefore the write operation will wait until some other party reads from the channel. This will deadlock as the main goroutine is blocked.

If the blocking operations were not in main goroutine, the program would finish as the Go program ends whenever main goroutine ends. There would be no deadlock if main function could come to an end.

You are trying to read from an empty channel because reads executed concurrently and doSomething didn't. It is possible to solve the problem in several ways. Note, it is not about correct architecture or efficient approaches. An examples below solve "deadlock" issue of the original snippet, not more.

Read and write concurrently:

package main

func doSomething(c chan<- string) { // recursive function does something
    c <- "result"
    doSomething(c)
}

func reads(c <-chan string) {
    results := <-c
    fmt.Println("Boo", results)
}

func main() {
    c := make(chan string)
    go reads(c)
    go doSomething(c) // Write concurrentely
}

Use select to handle channels read operation:

func reads(c <-chan string) {
    // Use select
    select {
    case res := <-c:
        fmt.Println("received message", res)
    default:
        fmt.Println("no results received")
    }
}

I'd rather prefer combination of the first and second approaches.

Read after write (it is far from correct design as hell):

func main() {
    c := make(chan string)

    go doSomething(c)
    reads(c) // Read after write
}

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