You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Go程序中midd()启动时执行而非访问/p3时执行?

Go中间件执行时机问题解答

问题现象

程序启动时终端立刻打印hello,访问localhost:5000/p1打印called 1、访问/p2打印called 2,但访问/p3时仅打印called 3,不会打印hello。疑惑为何midd()会在程序启动时被调用,而非访问/p3时才执行。

原代码

package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    runserver()
}

func runserver() {
    err := http.ListenAndServe(":5000", mux())
    if err != nil {
        log.Fatal(err)
    }
}

func mux() *http.ServeMux {
    mux := http.NewServeMux()

    mux.HandleFunc("/p1", func1)
    mux.HandleFunc("/p2", func2)
    mux.HandleFunc("/p3", midd("hello", func3))

    return mux
}

func func1(w http.ResponseWriter, r *http.Request) {
    fmt.Println("called 1")
    w.Write([]byte("hello from 1"))
}

func func2(w http.ResponseWriter, r *http.Request) {
    fmt.Println("called 2")
    w.Write([]byte("hello from 2"))
}

func func3(w http.ResponseWriter, r *http.Request) {
    fmt.Println("called 3") 
    w.Write([]byte("hello from 3"))
}

func midd(random string, hfunc http.HandlerFunc) http.HandlerFunc {
    fmt.Println(random)

    return hfunc
}

原因分析

在mux()函数初始化路由时,midd("hello", func3)是直接执行函数调用,不是把midd作为参数传递。程序启动时mux()会被执行,此时midd()就会立刻运行,打印hello,然后将返回的func3注册给/p3路由。当后续访问/p3时,实际执行的是func3,midd()早已在启动阶段执行完毕,所以不会再打印hello。

正确的中间件写法

中间件需要返回一个新的匿名HandlerFunc,将中间件逻辑放在这个匿名函数内部,这样每次请求触发时才会执行中间件代码:

func midd(random string, hfunc http.HandlerFunc) http.HandlerFunc {
    // 这里的代码仍会在启动时执行(如果有需要)
    return func(w http.ResponseWriter, r *http.Request) {
        // 以下代码会在每次请求/p3时执行
        fmt.Println(random)
        // 调用原handler
        hfunc(w, r)
    }
}

修改后,启动时midd()仅返回匿名函数,不会执行中间件的打印逻辑;当访问/p3时,匿名函数被调用,先打印hello,再执行func3,符合预期。

内容的提问来源于stack exchange,提问作者Antubus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:48:23