不确定为什么在Golang中会出现死锁?

huangapple go评论76阅读模式
英文:

not sure why this is deadlock in golang?

问题

我是你的中文翻译助手,以下是翻译好的内容:

我对Go语言还不熟悉,不确定为什么会出现死锁的情况?我想要不使用for循环,不断地从doSomething函数中读取结果并将其存储在read函数中。

func doSomething(c chan<- string) { // 递归函数做一些事情
    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)
}

请注意,这是你提供的代码,我只是将其翻译成了中文。

英文:

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&lt;- string){ // recursive function does something
    c &lt;- result 
    return dosomething(c)  }

func reads(c &lt;-chan string){
    results := &quot;&quot; 	
    temp := &lt;-c 	 	
    results = results + &quot;\n&quot; + temp 	 
    return results
}

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

答案1

得分: 1

主要的goroutine在doSomething函数中尝试多次向一个通道写入数据。read函数只读取一次通道。因此,写操作将等待直到其他方从通道中读取数据。由于主要的goroutine被阻塞,这将导致死锁。

如果阻塞操作不在主要的goroutine中,那么当主要的goroutine结束时,程序将结束。如果主函数能够结束,就不会发生死锁。

英文:

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.

答案2

得分: 1

你正在尝试从一个空通道中读取数据,因为readsdoSomething函数是并发执行的。有几种方法可以解决这个问题。请注意,这并不涉及正确的架构或高效的方法。下面的示例解决了原始代码片段中的"死锁"问题,没有更多的内容。

并发读写:

package main

func doSomething(c chan<- string) { // 递归函数做一些事情
    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) // 并发写入
}

使用select处理通道的读操作:

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

*我更喜欢第一种和第二种方法的结合*

**写后读这远非正确的设计):**

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

    go doSomething(c)
    reads(c) // 写后读
}
英文:

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&lt;- string) { // recursive function does something
    c &lt;- &quot;result&quot;
	doSomething(c)
}

func reads(c &lt;-chan string) {
    results := &lt;-c
	fmt.Println(&quot;Boo&quot;, 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 &lt;-chan string) {
    // Use select
    select {
	case res := &lt;-c:
    	fmt.Println(&quot;received message&quot;, res)
	default:
    	fmt.Println(&quot;no results received&quot;)
	}
}

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
}

huangapple
  • 本文由 发表于 2017年2月7日 18:33:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/42087504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定