即使关闭,通道也不会消亡
Channel never dies although closed
在下面的代码中,我试图写入所有发送到 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 }
}
这在两种情况下都会引发死锁,无论是有错误还是没有错误,即使我在完成处理后关闭了两个通道?
您最多只能从 operationOutcomes
中读取 writeOpCount
次,即使在 writeWorker
中每次执行都会导致最多 3 条消息写入该通道(none 你的错误案例导致函数 return,它继续处理)。因为它是无缓冲的并且它停止被读取,所以在某些时候写入它的工作人员不能再添加消息并因此永远锁定。
此外,由于您只调用 WriteC
一次并且它不会循环,它只会读取和处理来自 inputs
的一条消息。如果 writeOpCount
大于 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 }
}
这在两种情况下都会引发死锁,无论是有错误还是没有错误,即使我在完成处理后关闭了两个通道?
您最多只能从 operationOutcomes
中读取 writeOpCount
次,即使在 writeWorker
中每次执行都会导致最多 3 条消息写入该通道(none 你的错误案例导致函数 return,它继续处理)。因为它是无缓冲的并且它停止被读取,所以在某些时候写入它的工作人员不能再添加消息并因此永远锁定。
此外,由于您只调用 WriteC
一次并且它不会循环,它只会读取和处理来自 inputs
的一条消息。如果 writeOpCount
大于 1,那么当它尝试对第二条消息进行排队时,它将永远锁定在第一个循环中。