http.TimeoutHandler returns 但 handlerfunc 保持 运行

http.TimeoutHandler returns but handlerfunc keeps running

我正在我的 go 网络服务器中测试 http.timeoutHandler,我注意到 3 秒后我的客户端调用收到一条“Timeout”消息,但 2 秒后我可以在服务器日志中看到消息 "My func Println"。为什么 TimeoutHandler 没有取消我的 func1

这是我正在使用的代码:

package main

import (
        "fmt"
        "io"
        "net/http"
        "time"
)

func func1(w http.ResponseWriter, req *http.Request) {
        time.Sleep(5 * time.Second)
        fmt.Println("My func Println")
        io.WriteString(w, "My func!\n")
}

func main() {
        srv := http.Server{
                Addr:         ":9000",
                WriteTimeout: 5 * time.Second,
                Handler:      http.TimeoutHandler(http.HandlerFunc(func1), 3*time.Second, "Timeout!\n"),
        }

        if err := srv.ListenAndServe(); err != nil {
                fmt.Printf("Server failed: %s\n", err)
        }
}

是的,这就是它的工作方式。

当超时发生并且您的处理函数仍在运行(尚未返回)时,请求的上下文将被取消。您的处理程序负责监视上下文的完成通道,并在请求取消时中止其工作。每个处理程序都在自己的 goroutine 中运行,并且 goroutines 不能被 "outside".

杀死或中断

操作示例:

func func1(w http.ResponseWriter, req *http.Request) {
    select {
    case <-time.After(5 * time.Second):
        fmt.Println("My func Println")
        io.WriteString(w, "My func!\n")
    case <-req.Context().Done():
        fmt.Println("Cancelled")
    }
}

这将输出:

Cancelled

如果您将处理程序中的延迟更改为 2 秒:

case <-time.After(2 * time.Second):

输出将是:

My func Println

客户端收到发送的数据:

My func!