gpt4 book ai didi

go - 在 Go 中,如何关闭长时间运行的读取?

转载 作者:IT王子 更新时间:2023-10-29 01:19:58 25 4
gpt4 key购买 nike

似乎不可能通过 channel 与执行文件操作的 goroutine 进行双向通信,除非您在文件操作上阻止 channel 通信。我该如何解决这带来的限制?

表达这个问题的另一种方式......

如果我在 goroutine 中运行类似于以下的循环,我如何告诉它关闭连接并退出而不阻塞下一次读取?

func readLines(response *http.Response, outgoing chan string) error {
defer response.Body.Close()
reader := bufio.NewReader(response.Body)

for {
line, err := reader.ReadString('\n')
if err != nil {
return err
}
outgoing <- line
}
}

它不可能从告诉它何时关闭的 channel 中读取,因为它会阻止网络读取(在我的情况下,这可能需要数小时)。

从 goroutine 外部简单地调用 Close() 似乎并不安全,因为 Read/Close 方法似乎不是完全线程安全的。

我可以简单地锁定对在例程内部/外部使用的 response.Body 的引用,但会导致外部代码阻塞,直到挂起的读取完成,我特别希望能够中断正在进行的读取阅读。

最佳答案

为了解决这种情况,几个 io.ReadCloser标准库中的实现支持并发调用 ReadClose其中 Close 中断事件读取。

由 net/http 创建的响应主体阅读器 Transport是这些实现之一。在响应主体上同时调用 Read 和 Close 是安全的。

您还可以通过调用 Transport CancelRequest method 中断对响应主体的事件读取.

下面是如何在 body 上使用 close 实现取消:

func readLines(response *http.Response, outgoing chan string, done chan struct{}) error {
cancel := make(chan struct{})
go func() {
select {
case <-done:
response.Body.Close()
case <-cancel:
return
}()

defer response.Body.Close()
defer close(cancel) // ensure that goroutine exits

reader := bufio.NewReader(response.Body)
for {
line, err := reader.ReadString('\n')
if err != nil {
return err
}
outgoing <- line
}
}

从另一个 goroutine 调用 close(done) 将取消对 body 的读取。

关于go - 在 Go 中,如何关闭长时间运行的读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26437536/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com