3 回答

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超8個(gè)贊
你需要從輸出通道中取出一些東西,因?yàn)樗蛔枞钡接袞|西移除你放在它上面的東西。
不是唯一/最好的方法,但是:我移到printOutput()其他函數(shù)之上并將其作為 go 例程運(yùn)行,它可以防止死鎖。
package main
import (
"fmt"
"os"
"sync"
)
var wg sync.WaitGroup
var output = make(chan string)
func concurrent(n uint64) {
output <- fmt.Sprint(n)
defer wg.Done()
}
func printOutput() {
f, err := os.OpenFile("output.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer f.Close()
for msg := range output {
f.WriteString(msg + "\n")
}
}
func main() {
go printOutput()
wg.Add(2)
go concurrent(1)
go concurrent(2)
wg.Wait()
close(output)
}

TA貢獻(xiàn)1860條經(jīng)驗(yàn) 獲得超9個(gè)贊
一,為什么你會(huì)得到一個(gè)空的原因output是因?yàn)榍朗莃locking兩個(gè)發(fā)送/接收。
根據(jù)您的流程,下面的代碼片段永遠(yuǎn)不會(huì)到達(dá)wg.Done(),因?yàn)榘l(fā)送通道期望接收端將數(shù)據(jù)拉出。這是一個(gè)典型的死鎖例子。
func concurrent(n uint64) {
output <- fmt.Sprint(n) // go routine is blocked until data in channel is fetched.
defer wg.Done()
}
讓我們檢查一下主要功能:
func main() {
wg.Add(2)
go concurrent(1)
go concurrent(2)
wg.Wait() // the main thread will be waiting indefinitely here.
close(output)
printOutput()
}

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超8個(gè)贊
我對(duì)這個(gè)問(wèn)題的看法:
package main
import (
"fmt"
"os"
"sync"
)
var wg sync.WaitGroup
var output = make(chan string)
var donePrinting = make(chan struct{})
func concurrent(n uint) {
defer wg.Done() // It only makes sense to defer
// wg.Done() before you do something.
// (like sending a string to the output channel)
output <- fmt.Sprint(n)
}
func printOutput() {
f, err := os.OpenFile("output.txt", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer f.Close()
for msg := range output {
f.WriteString(msg + "\n")
}
donePrinting <- struct{}{}
}
func main() {
wg.Add(2)
go printOutput()
go concurrent(1)
go concurrent(2)
wg.Wait()
close(output)
<-donePrinting
}
每個(gè)concurrent函數(shù)將從等待組中扣除。
兩個(gè)concurrentgoroutine 完成后,wg.Wait()將解除阻塞,并執(zhí)行下一條指令 ( close(output))。在關(guān)閉通道之前,您必須等待兩個(gè) goroutine 完成。相反,如果您嘗試以下操作:
go printOutput()
go concurrent(1)
go concurrent(2)
close(output)
wg.Wait()
您可能會(huì)close(output)在任何一個(gè)concurrentgoroutine 結(jié)束之前執(zhí)行指令。如果通道在并發(fā) goroutine 運(yùn)行之前關(guān)閉,它們將在運(yùn)行時(shí)崩潰(在嘗試寫(xiě)入關(guān)閉的通道時(shí))。
那么,如果您不等待printOutput()goroutine 完成,您實(shí)際上可以main()在printOutput()有機(jī)會(huì)完成對(duì)其文件的寫(xiě)入之前退出。
因?yàn)槲蚁雙rintOutput()在退出程序之前等待goroutine 完成,所以我還創(chuàng)建了一個(gè)單獨(dú)的通道來(lái)表示printOutput()已經(jīng)完成。
的<-donePrinting指令塊,直到main接收的東西在donePrinting信道。一旦main收到任何東西(甚至是printOutput()發(fā)送的空結(jié)構(gòu)),它就會(huì)解除阻塞并運(yùn)行到結(jié)論。
https://play.golang.org/p/nXJoYLI758m
- 3 回答
- 0 關(guān)注
- 145 瀏覽
添加回答
舉報(bào)