diff --git a/CLAUDE.md b/CLAUDE.md index fc4e453..8040b3b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,28 +4,34 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -AnKao is a Go web application built using the standard library's `net/http` package. The project follows a clean architecture pattern with clear separation of concerns. +AnKao is a Go web application built using the **Gin framework**. The project follows a clean architecture pattern with clear separation of concerns and is designed to support database integration. ## Architecture ### Request Flow -1. HTTP requests arrive at the server running on port 8080 -2. Requests pass through the `Logger` middleware (in `internal/middleware/`) -3. The router (`http.NewServeMux`) directs requests to appropriate handlers -4. Handlers (in `internal/handlers/`) process requests and return JSON responses +1. HTTP requests arrive at the Gin server running on port 8080 +2. Requests pass through Gin's default middleware (Logger, Recovery) and custom middleware +3. The Gin router matches routes and directs requests to appropriate handlers +4. Handlers (in `internal/handlers/`) process requests using `*gin.Context` and return JSON responses ### Middleware Pattern -Middleware functions wrap the main handler using the standard middleware pattern: +Middleware in Gin uses the `gin.HandlerFunc` pattern: ```go -func Middleware(next http.Handler) http.Handler +func MiddlewareName() gin.HandlerFunc { + return func(c *gin.Context) { + // Pre-processing + c.Next() + // Post-processing + } +} ``` -Middleware is applied in [cmd/server/main.go:20](cmd/server/main.go#L20) before starting the server. +Middleware is registered in [main.go:15](main.go#L15) using `r.Use()`. ### Module Structure -- **cmd/server/** - Application entry point, server configuration and routing setup -- **internal/handlers/** - HTTP request handlers, all return JSON responses -- **internal/middleware/** - HTTP middleware chain (currently: logging) -- **internal/models/** - Data models (directory exists but not yet populated) +- **main.go** - Application entry point, server configuration and routing setup +- **internal/handlers/** - HTTP request handlers, all use `*gin.Context` and return JSON responses +- **internal/middleware/** - Gin middleware chain (currently: custom logger) +- **internal/models/** - Data models (directory exists, ready for database models) - **pkg/config/** - Configuration management (directory exists but not yet populated) ## Common Commands @@ -33,7 +39,7 @@ Middleware is applied in [cmd/server/main.go:20](cmd/server/main.go#L20) before ### Development ```bash # Run the server -go run cmd/server/main.go +go run main.go # Install/update dependencies go mod tidy @@ -48,7 +54,7 @@ go vet ./... ### Building ```bash # Build binary to bin/server -go build -o bin/server cmd/server/main.go +go build -o bin/server.exe main.go # Run built binary (Windows) .\bin\server.exe @@ -67,12 +73,34 @@ go test -cover ./... # Run tests in a specific package go test ./internal/handlers/ + +# Run tests with verbose output +go test -v ./... ``` ## Key Implementation Details -- The server listens on port **:8080** (hardcoded in main.go:23) -- All responses are JSON with appropriate Content-Type headers -- Import paths use the module name `ankao` (defined in go.mod) -- When adding new handlers, register them in [cmd/server/main.go](cmd/server/main.go) using `mux.HandleFunc()` -- Middleware wraps the entire mux, so it applies to all routes +- **Framework**: Using Gin v1.11.0 +- **Server Port**: :8080 (configured in [main.go:22](main.go#L22)) +- **Handler Signature**: All handlers use `func(c *gin.Context)` pattern +- **JSON Response**: Use `c.JSON()` method with `gin.H{}` or structs +- **Import Paths**: Use module name `ankao` (defined in go.mod) +- **Route Registration**: Routes are registered in [main.go](main.go) using `r.GET()`, `r.POST()`, etc. +- **Middleware**: Applied globally with `r.Use()` or per-route with route grouping + +## Adding New Features + +### Adding a New Handler +1. Create handler function in `internal/handlers/` with signature `func(c *gin.Context)` +2. Use `c.JSON()` to return responses +3. Register route in [main.go](main.go) (e.g., `r.GET("/path", handlers.YourHandler)`) + +### Adding Middleware +1. Create middleware in `internal/middleware/` returning `gin.HandlerFunc` +2. Apply globally with `r.Use(middleware.YourMiddleware())` or to route groups + +### Database Integration +The project is ready for database integration: +- Add models in `internal/models/` +- Consider using GORM or similar ORM +- Add database initialization in main.go or separate package diff --git a/README.md b/README.md index 4bcc3fc..d654c7a 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,12 @@ # AnKao Web 项目 -这是一个使用Go语言构建的Web应用项目。 +这是一个使用Go语言和Gin框架构建的Web应用项目。 ## 项目结构 ``` AnKao/ -├── cmd/ -│ └── server/ # 主程序入口 -│ └── main.go +├── main.go # 主程序入口 ├── internal/ # 私有应用代码 │ ├── handlers/ # HTTP请求处理器 │ ├── middleware/ # 中间件 @@ -24,7 +22,7 @@ AnKao/ ### 运行服务器 ```bash -go run cmd/server/main.go +go run main.go ``` 服务器将在 `http://localhost:8080` 启动 @@ -45,18 +43,29 @@ go mod tidy ### 构建 ```bash -go build -o bin/server cmd/server/main.go +go build -o bin/server.exe main.go ``` ### 运行编译后的程序 ```bash +# Windows +.\bin\server.exe + +# Linux/Mac ./bin/server ``` ## 特性 -- 基于标准库的HTTP服务器 -- 日志中间件 -- RESTful API结构 +- 基于 Gin 框架的高性能 HTTP 服务器 +- 自定义日志中间件 +- RESTful API 结构 - 健康检查端点 +- 支持数据库集成(预留结构) + +## 技术栈 + +- **Go** 1.25.1 +- **Gin** v1.11.0 - Web 框架 +- 清晰的项目架构,易于扩展 diff --git a/go.mod b/go.mod index 18449b1..47eb98d 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,39 @@ module ankao go 1.25.1 + +require ( + github.com/bytedance/gopkg v0.1.3 // indirect + github.com/bytedance/sonic v1.14.2 // indirect + github.com/bytedance/sonic/loader v0.4.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/gabriel-vasile/mimetype v1.4.11 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect + github.com/gin-gonic/gin v1.11.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.28.0 // indirect + github.com/goccy/go-json v0.10.5 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.55.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.1 // indirect + go.uber.org/mock v0.6.0 // indirect + golang.org/x/arch v0.22.0 // indirect + golang.org/x/crypto v0.43.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/net v0.46.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/text v0.30.0 // indirect + golang.org/x/tools v0.38.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..4c559da --- /dev/null +++ b/go.sum @@ -0,0 +1,84 @@ +github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= +github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= +github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE= +github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980= +github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o= +github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik= +github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= +github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688= +github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk= +github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= +github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= +golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI= +golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go index e78c370..984a1e0 100644 --- a/internal/handlers/handlers.go +++ b/internal/handlers/handlers.go @@ -1,26 +1,22 @@ package handlers import ( - "encoding/json" "net/http" + + "github.com/gin-gonic/gin" ) // HomeHandler 首页处理器 -func HomeHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - response := map[string]string{ +func HomeHandler(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ "message": "欢迎使用AnKao Web服务", "version": "1.0.0", - } - json.NewEncoder(w).Encode(response) + }) } // HealthCheckHandler 健康检查处理器 -func HealthCheckHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - response := map[string]string{ +func HealthCheckHandler(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ "status": "healthy", - } - json.NewEncoder(w).Encode(response) + }) } diff --git a/internal/middleware/logger.go b/internal/middleware/logger.go index 6a784ec..0b0d895 100644 --- a/internal/middleware/logger.go +++ b/internal/middleware/logger.go @@ -2,25 +2,29 @@ package middleware import ( "log" - "net/http" "time" + + "github.com/gin-gonic/gin" ) // Logger 日志中间件 -func Logger(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +func Logger() gin.HandlerFunc { + return func(c *gin.Context) { start := time.Now() - // 调用下一个处理器 - next.ServeHTTP(w, r) + // 处理请求 + c.Next() // 记录请求信息 + duration := time.Since(start) log.Printf( - "%s %s %s %v", - r.Method, - r.RequestURI, - r.RemoteAddr, - time.Since(start), + "[%s] %s %s | %d | %v | %s", + c.Request.Method, + c.Request.RequestURI, + c.ClientIP(), + c.Writer.Status(), + duration, + c.Errors.String(), ) - }) + } } diff --git a/main.go b/main.go index a5f62a9..46a031b 100644 --- a/main.go +++ b/main.go @@ -1,28 +1,26 @@ package main import ( - "log" - "net/http" - "ankao/internal/handlers" "ankao/internal/middleware" + + "github.com/gin-gonic/gin" ) func main() { - // 创建路由 - mux := http.NewServeMux() + // 创建Gin路由器 + r := gin.Default() + + // 应用自定义中间件 + r.Use(middleware.Logger()) // 注册路由 - mux.HandleFunc("/", handlers.HomeHandler) - mux.HandleFunc("/api/health", handlers.HealthCheckHandler) - - // 应用中间件 - handler := middleware.Logger(mux) + r.GET("/", handlers.HomeHandler) + r.GET("/api/health", handlers.HealthCheckHandler) // 启动服务器 port := ":8080" - log.Printf("服务器启动在端口 %s", port) - if err := http.ListenAndServe(port, handler); err != nil { - log.Fatal("服务器启动失败:", err) + if err := r.Run(port); err != nil { + panic("服务器启动失败: " + err.Error()) } }