尽管关闭,频道永远不会死

时间:2017-06-05 12:24:49

标签: go goroutine channels

在以下代码中,我尝试编写发送到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 } 
}

这会在出现错误的情况下引发死锁,即使我在完成这两个频道时关闭了两个频道吗?

1 个答案:

答案 0 :(得分:1)

您只能从operationOutcomes读取最多writeOpCount次,即使在writeWorker中每次执行都会导致最多3封邮件被写入该频道(您的错误案例都不会导致返回的功能,继续处理)。因为它是无缓冲的并且它不再被读取,所以在某些时候写入它的工作人员不能再添加消息,因此永远锁定。

此外,由于您只调用WriteC一次并且它不循环,因此它只会从inputs读取并处理一条消息。如果writeOpCount是&gt; 1,当它试图排队第二条消息时,它会永久锁定在第一个循环中。