V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
howellz
V2EX  ›  Go 编程语言

golang 就没有提供一个可以被 cancel 的 read 接口?

  •  
  •   howellz · 2020-11-20 15:25:15 +08:00 · 2152 次点击
    这是一个创建于 1500 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

    17 条回复    2021-02-24 15:30:52 +08:00
    sujin190
        1
    sujin190  
       2020-11-20 15:32:29 +08:00
    为啥要取消?是你理解有问题吧,除非连接关闭,否则确实无需返回啊,如果你有其他事情要干,那么再开个携程就是了啊,如果需要读超时啥的,这个超时本来就需要新开协程来干的啊
    lwch
        2
    lwch  
       2020-11-20 15:33:13 +08:00
    可以设 timeout
    nuk
        3
    nuk  
       2020-11-20 15:33:40 +08:00
    不是有 setdeadline 啥的么。。
    howellz
        4
    howellz  
    OP
       2020-11-20 15:35:57 +08:00
    @lwch @nuk setdeadline
    timeout 毕竟是一种轮询机制,太长响应变差,太短开销变大。
    lwch
        5
    lwch  
       2020-11-20 15:38:09 +08:00
    io.Read 的阻塞操作本来就是为了让出时间片给别的协程做调度用的,所以 go 里面不存在 noblock 的 io 操作
    howellz
        6
    howellz  
    OP
       2020-11-20 15:38:51 +08:00
    @sujin190 取消是一个太常见的场景了,最极端的就我想中止这个携程,但是我现在不能关闭这个 conn 。当然您也许会继续质疑我为什么要关闭这个携程。。。
    nuk
        7
    nuk  
       2020-11-20 15:43:10 +08:00
    @howellz syscall 可以 select 也可以 epoll,中断协程的话直接 close 掉 read 就会退出啊。。
    mepwang
        8
    mepwang  
       2020-11-20 15:53:54 +08:00 via iPhone
    给它的 socket 发点东西😅
    icexin
        9
    icexin  
       2020-11-20 15:55:00 +08:00
    在另外一个地方调用 conn. SetReadDeadline,参数设置一个距离很短的 deadline 就可以立马让 Read 返回错误。
    比如 conn.SetReadDeadline(time.Now())
    howellz
        10
    howellz  
    OP
       2020-11-20 15:57:18 +08:00
    @icexin 这听起来不错,我看下错误是否会有 confuse 的地方。
    jokefun
        11
    jokefun  
       2020-11-20 15:59:12 +08:00
    读了一半 cancel 了之后这个 net.Conn 怎么办呢?没读完的 bytes 下次接着读吗?
    lxz6597863
        12
    lxz6597863  
       2020-11-20 16:50:35 +08:00
    把 chan 和 net.Conn 封装个 Reader
    sujin190
        13
    sujin190  
       2020-11-20 17:42:43 +08:00
    @howellz #6 这个场景确实有,但是不是这么用的,按你这么说其实就是数据处理逻辑和读写逻辑被分离了,按 go 的设计和习惯用法,那么应该是 read 连接这个协程只负责处理读,读处理的数据通过 channl 传给另外逻辑处理协程来完成,那么这个协程才应该依据是否超时等其他情况觉得是否取消处理,读写本来就应该和连接绑定,而数据逻辑处理才应该考虑中途退出,这才是符合 go 的习惯处理方式
    wellsc
        14
    wellsc  
       2020-11-20 17:49:55 +08:00
    gmp 这玩意儿就是把协程 schedulder 封装进了一个框架里面,给协程封装框架的语言除了 golang 还有 erlang 系,反正框架有框架的好处,也有框架的坏处,坏处就是自己调度起来有点麻烦吧
    reus
        15
    reus  
       2020-11-20 18:45:00 +08:00
    conn.SetReadDeadline(time.Now().Add(-time.Hour))
    howellz
        16
    howellz  
    OP
       2020-11-20 19:20:57 +08:00
    @sujin190 您设计的场景不是没有考虑过.但这种异步传递消息的方式,需要多次分配`buf []byte`。如果是同步处理,在`read`后处理完了,`buf`可以让下一次`read`重用。在负荷非常大的场景,尽量少拷贝、少分配、少传递是我需要考虑的一个重要问题。
    lesismal
        17
    lesismal  
       2021-02-24 15:30:52 +08:00
    试试我的异步网络库:

    https://github.com/lesismal/nbio
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2847 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 13:55 · PVG 21:55 · LAX 05:55 · JFK 08:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.