Golang Go语言中就没有提供一个可以被 cancel 的 read 接口?

发布于 1周前 作者 vueper 来自 Go语言

Golang Go语言中就没有提供一个可以被 cancel 的 read 接口?

正在使用net.Conn.Read(),发现这货除了net.close(),似乎没有其他办法把read()函数给主动返回。

这样也太扯淡了吧,至少提供个select readset或者epoll readset,这样类似的操作吧。

18 回复

为啥要取消?是你理解有问题吧,除非连接关闭,否则确实无需返回啊,如果你有其他事情要干,那么再开个携程就是了啊,如果需要读超时啥的,这个超时本来就需要新开协程来干的啊

更多关于Golang Go语言中就没有提供一个可以被 cancel 的 read 接口?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


可以设 timeout

不是有 setdeadline 啥的么。。

setdeadline
timeout 毕竟是一种轮询机制,太长响应变差,太短开销变大。

io.Read 的阻塞操作本来就是为了让出时间片给别的协程做调度用的,所以 go 里面不存在 noblock 的 io 操作

取消是一个太常见的场景了,最极端的就我想中止这个携程,但是我现在不能关闭这个 conn 。当然您也许会继续质疑我为什么要关闭这个携程。。。

syscall 可以 select 也可以 epoll,中断协程的话直接 close 掉 read 就会退出啊。。

给它的 socket 发点东西😅

在另外一个地方调用 conn. SetReadDeadline,参数设置一个距离很短的 deadline 就可以立马让 Read 返回错误。
比如 conn.SetReadDeadline(time.Now())

这听起来不错,我看下错误是否会有 confuse 的地方。

读了一半 cancel 了之后这个 net.Conn 怎么办呢?没读完的 bytes 下次接着读吗?

把 chan 和 net.Conn 封装个 Reader

#6 这个场景确实有,但是不是这么用的,按你这么说其实就是数据处理逻辑和读写逻辑被分离了,按 go 的设计和习惯用法,那么应该是 read 连接这个协程只负责处理读,读处理的数据通过 channl 传给另外逻辑处理协程来完成,那么这个协程才应该依据是否超时等其他情况觉得是否取消处理,读写本来就应该和连接绑定,而数据逻辑处理才应该考虑中途退出,这才是符合 go 的习惯处理方式

gmp 这玩意儿就是把协程 schedulder 封装进了一个框架里面,给协程封装框架的语言除了 golang 还有 erlang 系,反正框架有框架的好处,也有框架的坏处,坏处就是自己调度起来有点麻烦吧

conn.SetReadDeadline(time.Now().Add(-time.Hour))

您设计的场景不是没有考虑过.但这种异步传递消息的方式,需要多次分配buf []byte。如果是同步处理,在read后处理完了,buf可以让下一次read重用。在负荷非常大的场景,尽量少拷贝、少分配、少传递是我需要考虑的一个重要问题。

在Golang(Go语言)的标准库中,确实没有直接提供一个原生支持取消操作的 read 接口。然而,Go语言的设计哲学鼓励通过组合和通道(channels)等机制来实现并发控制和取消操作。

要实现一个可取消的读取操作,你可以使用以下方法:

  1. 使用通道和上下文(context):你可以创建一个上下文(context.Context),并将其传递给读取操作。同时,启动一个goroutine来监听上下文的取消信号。如果上下文被取消,goroutine可以关闭一个通道,通知读取操作停止。

  2. 使用 select 语句:在读取操作中,你可以使用 select 语句来同时监听文件或网络连接上的数据到达和通道上的取消信号。这样,当取消信号到达时,读取操作可以立即返回。

  3. 第三方库:虽然标准库没有直接支持,但一些第三方库可能已经实现了可取消的读取操作。你可以搜索这些库,看它们是否满足你的需求。

  4. 手动实现:如果上述方法都不适用,你也可以手动实现一个可取消的读取操作。这通常涉及到在读取循环中定期检查一个取消标志,并在需要时退出循环。

总之,虽然Go语言的标准库没有直接提供一个可取消的 read 接口,但你可以通过组合使用上下文、通道和 select 语句等机制来实现类似的功能。这种方法不仅灵活,而且符合Go语言的并发设计哲学。

回到顶部