網頁

2023/10/31

Golang uber Fx + Gin

Go語言依賴套件uber-go/fx搭配web框架Gin。


範例環境:

  • Go 1.19


事前要求

參考「Golang Gin Web Framework hello world範例」使用Gin建立Web server。

參考「Golang uber Fx 依賴注入套件 http Web範例」了解Fx如何和原生http Server搭配使用。


範例

main.go

package main

import (
    "context"
    "log"
    "net/http"

    "github.com/gin-gonic/gin"
    "go.uber.org/fx"
)

func main() {
    fx.New(
        fx.Provide(
            AnnotateAsHandler(NewHelloHandler),
            fx.Annotate(
                NewRouter,
                fx.ParamTags(``, `group:"handlers"`),
            ),
        ),
        fx.Invoke(func(router *Router) {
            router.Route()
        }),
    ).Run()
}

func AnnotateAsHandler(f any) any {
    return fx.Annotate(
        f,
        fx.As(new(Hander)),
        fx.ResultTags(`group:"handlers"`),
    )
}

type Router struct {
    router   *gin.Engine
    handlers []Hander
}

func NewRouter(lc fx.Lifecycle, handlers []Hander) *Router {
    router := gin.Default()
    srv := &http.Server{
        Addr:    ":8080",
        Handler: router,
    }
    lc.Append(fx.Hook{
        OnStart: func(ctx context.Context) error {
            go func() {
                if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
                    log.Fatalf("listen: %s\n", err)
                }
            }()
            return nil
        },
        OnStop: func(ctx context.Context) error {
            if err := srv.Shutdown(ctx); err != nil {
                log.Fatal("Server forced to shutdown: ", err)
            }

            log.Println("Server exiting")
            return nil
        },
    })

    return &Router{
        router:   router,
        handlers: handlers,
    }
}

func (r Router) Route() {
    for _, h := range r.handlers {
        r.router.Handle(h.HttpMethod(), h.Pattern(), h.HandlerFunc)
    }
}

type Hander interface {
    HandlerFunc(c *gin.Context)
    HttpMethod() string
    Pattern() string
}

type HelloHandler struct{}

func NewHelloHandler() *HelloHandler {
    return &HelloHandler{}
}
func (h *HelloHandler) HandlerFunc(c *gin.Context) {
    c.JSON(200, gin.H{
        "message": "hello world",
    })
}

func (h *HelloHandler) HttpMethod() string {
    return "GET"
}

func (h *HelloHandler) Pattern() string {
    return "/hello"
}

github


沒有留言:

張貼留言