go http handle wirte

目前写了这样一份代码

func Handler(w http.ResponseWriter, r *http.Request) {

    w.Header().Set("Content-Type", "text/plain")
    w.WriteHeader(http.StatusOK)

    fmt.Fprintf(w, "ok")
        ------------     
         reqChannel <- req:

}

逻辑就是一个httpserver 调用立即响应200;然后将数据写入到channel;

目前出现一个bug;由于channel阻塞;导致后续httpserver 没有立即将响应发送出去。

也就是fmt.Fprintf(w, "ok") 虽然执行了,但是实际上只是写入到 writer的缓存。没有真正发送出去

可以看之前的文章:https://www.cnblogs.com/codestack/p/17984385

func (b *Writer) Write(p []byte) (nn int, err error) {
    // b.Available() 的值为 len(b.buf) - b.n
    // 只要p的大小大于缓冲区的可用大小,则执行循环
    for len(p) > b.Available() && b.err == nil {
        var n int
        if b.Buffered() == 0 {
            // 如果p的大小大于缓冲区的可用大小,且缓冲区为空
            // 则数据直接写入,无需先拷贝到缓冲区
            n, b.err = b.wr.Write(p)
        } else {
            // 将数据拷贝到缓冲区,然后通过flush操作写入缓冲区数据
            n = copy(b.buf[b.n:], p)
            b.n += n
            b.flush()
        }
        nn += n
        // 剩余待写入数据
        p = p[n:]
    }
    if b.err != nil {
        return nn, b.err
    }
    // 此时p的大小小于等于缓冲区大小,因此将数据拷贝到缓冲区
    n := copy(b.buf[b.n:], p)
    b.n += n
    nn += n
    return nn, nil
}

 

针对上述逻辑修改方式为

1、添加flush ,但是接口不一定实现了

if flusher, ok := w.(http.Flusher); ok {
        flusher.Flush()
    }

2、使用select 实现非阻塞读写

    select {
        case reqChannel <- req:
            ------
        default:
            
}

3、一次性响应超过默认值4096 byte数据,调用flush函数

 

目前建议使用select 实现非阻塞读写

 

posted @ 2025-02-18 17:39  codestacklinuxer  阅读(17)  评论(0)    收藏  举报