插件窝 干货文章 Go语言中间件如何优雅地处理多个业务共用同一复杂逻辑?

Go语言中间件如何优雅地处理多个业务共用同一复杂逻辑?

HTTP 中间件 逻辑 Handler 1202    来源:    2025-03-13

在Go语言中,中间件(Middleware)是一种常见的模式,用于在处理HTTP请求时执行一些通用的逻辑,如身份验证、日志记录、错误处理等。当多个业务需要共用同一复杂逻辑时,可以通过以下几种方式优雅地处理:

1. 使用中间件函数

将复杂的逻辑封装成一个中间件函数,然后在需要的地方使用这个中间件。这种方式适用于需要在多个路由或处理函数中共享同一逻辑的场景。

package main

import (
    "fmt"
    "net/http"
)

// 复杂的逻辑封装成中间件
func complexMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 在这里执行复杂的逻辑
        fmt.Println("Executing complex logic...")

        // 调用下一个处理函数
        next.ServeHTTP(w, r)
    })
}

func handler1(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 1")
}

func handler2(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 2")
}

func main() {
    mux := http.NewServeMux()

    // 使用中间件
    mux.Handle("/path1", complexMiddleware(http.HandlerFunc(handler1)))
    mux.Handle("/path2", complexMiddleware(http.HandlerFunc(handler2)))

    http.ListenAndServe(":8080", mux)
}

2. 使用闭包封装复杂逻辑

如果复杂的逻辑需要根据不同的业务场景进行定制,可以使用闭包来封装逻辑,并返回一个中间件函数。

package main

import (
    "fmt"
    "net/http"
)

// 使用闭包封装复杂逻辑
func complexMiddlewareWithParams(param string) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // 在这里执行复杂的逻辑,并使用传入的参数
            fmt.Printf("Executing complex logic with param: %s\n", param)

            // 调用下一个处理函数
            next.ServeHTTP(w, r)
        })
    }
}

func handler1(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 1")
}

func handler2(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 2")
}

func main() {
    mux := http.NewServeMux()

    // 使用带参数的中间件
    mux.Handle("/path1", complexMiddlewareWithParams("param1")(http.HandlerFunc(handler1)))
    mux.Handle("/path2", complexMiddlewareWithParams("param2")(http.HandlerFunc(handler2)))

    http.ListenAndServe(":8080", mux)
}

3. 使用结构体和方法封装复杂逻辑

如果复杂的逻辑涉及到多个步骤或需要维护一些状态,可以将逻辑封装在一个结构体中,并通过方法来实现中间件。

package main

import (
    "fmt"
    "net/http"
)

// 定义结构体封装复杂逻辑
type ComplexLogic struct {
    Param string
}

// 中间件方法
func (cl *ComplexLogic) Middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 在这里执行复杂的逻辑,并使用结构体的字段
        fmt.Printf("Executing complex logic with param: %s\n", cl.Param)

        // 调用下一个处理函数
        next.ServeHTTP(w, r)
    })
}

func handler1(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 1")
}

func handler2(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 2")
}

func main() {
    mux := http.NewServeMux()

    // 创建结构体实例
    cl1 := &ComplexLogic{Param: "param1"}
    cl2 := &ComplexLogic{Param: "param2"}

    // 使用结构体的中间件方法
    mux.Handle("/path1", cl1.Middleware(http.HandlerFunc(handler1)))
    mux.Handle("/path2", cl2.Middleware(http.HandlerFunc(handler2)))

    http.ListenAndServe(":8080", mux)
}

4. 使用第三方中间件库

如果复杂的逻辑涉及到更多的功能,如身份验证、日志记录、限流等,可以考虑使用一些成熟的第三方中间件库,如gorilla/muxnegroni等。这些库提供了丰富的中间件功能,可以帮助你更高效地处理复杂的逻辑。

package main

import (
    "fmt"
    "net/http"

    "github.com/gorilla/mux"
)

func complexMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 在这里执行复杂的逻辑
        fmt.Println("Executing complex logic...")

        // 调用下一个处理函数
        next.ServeHTTP(w, r)
    })
}

func handler1(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 1")
}

func handler2(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Handler 2")
}

func main() {
    r := mux.NewRouter()

    // 使用中间件
    r.Use(complexMiddleware)

    r.HandleFunc("/path1", handler1)
    r.HandleFunc("/path2", handler2)

    http.ListenAndServe(":8080", r)
}

总结

通过将复杂的逻辑封装成中间件函数、使用闭包、结构体或第三方库,可以优雅地在多个业务中共享同一复杂逻辑。选择哪种方式取决于具体的业务需求和代码结构。