2014-09-21 40 views
3

我想知道在退出程序之前等待完成程序的正確方法是什麼。閱讀似乎一個布爾陳會做的伎倆一些其他的答案,如Playground link等待完成程序的正確方法

func do_stuff(done chan bool) { 
    fmt.Println("Doing stuff") 
    done <- true 
} 

func main() { 
    fmt.Println("Main") 
    done := make(chan bool) 
    go do_stuff(done) 
    <-done 
    //<-done 
} 

我這裏有兩個問題:

  • 爲什麼< - 完成的作品呢?

  • 如果我取消註釋最後一行,會發生什麼情況?我有一個死鎖錯誤。這是因爲通道是空的,並且沒有其他函數將值發送給它?

+1

'< - done'工作,因爲這正是渠道做:)(見https://golang.org/ref/spec#Receive_operator和https: //golang.org/ref/spec#Send_statements瞭解詳情)。你對第二行如何取消註釋會導致僵局是正確的。沒有任何發送到「完成」,Go認識到,如果它等待(即沒有任何等待網絡呼叫),甚至沒有*可以*。 – twotwotwo 2014-09-21 00:27:24

回答

5

爲什麼<- done可以工作?

  • 它的工作原理是因爲運行時檢測到您正在將某些內容寫入其他通道。

如果我取消註釋最後一行,會發生什麼情況?

  • 運行時非常聰明,知道沒有別的東西正在寫入,而且它會死鎖。

獎金,如果你非常的內存的限制,您可以使用done := make(chan struct{})done <- struct{}{}struct{}是保證使用0內存。

5

收聽頻道<- done是一項阻止操作,因此您的程序將不會繼續,直到發送真或假,即done <- true

根據情況,你的問題可以有幾個不同的答案。

例如,假設您想並行化一系列需要很長時間的函數調用。

我會用sync軟件包這一

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

func main() { 
    var wg sync.WaitGroup 
    for i := 0; i < 10; i++ { 
     wg.Add(1) 
     go func() { 
      longOp() 
      wg.Done() 
     }() 
    } 
    // will wait until wg.Done is called 10 times 
    // since we made wg.Add(1) call 10 times 
    wg.Wait() 
} 

func longOp() { 
    time.Sleep(time.Second * 2) 
    fmt.Println("long op done") 
}