2017-06-05 76 views
1

在下面的代碼,我試圖寫發送到inputs通道的所有文件和發送過operationOutcomes通道通道永遠不死雖然關閉

main.go

package main 

import(
    lr "github.com/fabulousduck/librarian" 
    "fmt" 
) 

func main() { 
    writeOpCount := 100; 
    operationOutcomes, inputs := make(chan lr.WriteOpResponse), make(chan lr.WriteOp) 
    go lr.WriteC(inputs, operationOutcomes) 

    for i := 0; i < writeOpCount; i++ { 
     inputs <- lr.WriteOp{ Dest: `../exampleFiles/createdFiles/{i}.txt`, Content: `Invoice #{i}` } 
    } 

    close(inputs) 

    for i := 0; i < writeOpCount; i++ { 
     writeResult := <-operationOutcomes 
     fmt.Println("Response from write operation : ", writeResult.Msg, "err ", writeResult.Err, "bytes written : ", writeResult.BytesWritten) 
    } 

    close(operationOutcomes) 
} 
相應的響應

librarian.go 包圖書館管理員

import(
    "os" 
    "fmt" 
) 

type WriteOp struct { 
    Dest, Content string 
} 

type WriteOpResponse struct { 
    Msg error 
    Err bool 
    BytesWritten int 
} 

func WriteC (inputChannel <-chan WriteOp, outputChannel chan<- WriteOpResponse) { 
    workOp := <-inputChannel 
    go writeWorker(workOp, outputChannel) 
} 

func writeWorker (job WriteOp, outGoing chan<- WriteOpResponse) { 
    file, err := os.OpenFile(job.Dest, os.O_RDWR, 0666) 
    if err != nil { 
     fmt.Println("err : ", err) 
     outGoing <- WriteOpResponse{ Msg: err, Err: true, BytesWritten: 0 } 
    } 
    bytesWritten , err := file.WriteString(job.Content) 
    if err != nil { 
     outGoing <- WriteOpResponse{ Msg: err, Err: true, BytesWritten: 0 } 
    } 
    outGoing <- WriteOpResponse{ Msg: nil, Err: false, BytesWritten: bytesWritten } 
} 

這兩種情況下都存在並且不存在錯誤時會引發死鎖,儘管當我完成這些操作時,我正在關閉兩個通道?

+0

作爲註釋,因爲它與q無關 - 因爲WriteC已經被稱爲goroutine,爲什麼它會啓動另一個goroutine來調用'writeWorker'? – Adrian

+0

您可能想要在代碼的其他部分添加多個'writeC'實例,這些實例不相互關聯。 – duck

回答

1

你只從operationOutcomes讀取多達writeOpCount倍,即使在writeWorker每次執行可能導致被寫入該通道上高達3條消息(沒有你的錯誤情況導致函數返回,以繼續進行處理)。因爲它沒有緩衝並且不再被讀取,所以寫入它的工作人員不能再添加消息並永久鎖定。

此外,由於您只呼叫WriteC一次,並且它不循環,它將只會讀取和處理來自inputs的一條消息。如果writeOpCount> 1,那麼當它嘗試排隊第二條消息時,它將永遠鎖定在第一個循環內。

+0

我確實已經注意到了,並且在每次推送到頻道後嘗試添加'return'語句。但是這並不能解決問題。 – duck

+0

更新 - 發現第二個問題。 – Adrian

+0

非常感謝。第二個問題解決了我的問題。 – duck