github.com/Ethan-netizen-oss/dhuam


Install
go get github.com/Ethan-netizen-oss/dhuam

Documentation

dhuam

GitHub Stars Go Report Card Go Reference License: MIT CI Go Version

一个高性能 Go Web 框架,内置 AI 多模型接入模块、插件系统、国际化支持。

🌟 如果这个项目对你有帮助,请给个 GitHub Star

特性

🚀 Web 框架核心

  • 高性能路由 — 基数树(Radix Tree)路由,支持参数路由 :param 和通配符 *
  • 路由组 — 支持嵌套路由组和组级别中间件
  • 中间件链 — Recovery、Logger、CORS、Auth、CSRF、RateLimit、Compress、Cache 等
  • 请求绑定 — JSON / XML / Form / Query / Header / URI 自动绑定
  • 结构体验证validate 标签验证(required、min、max、email、正则等)
  • 可插拔日志 — 支持 slog、zap、内置 logrus 风格日志
  • 对象池 — Context 复用,零分配优化
  • 错误处理 — HTTPError 错误链,支持 errors.Is/As
  • 渲染器 — JSON / XML / HTML / Data / Stream / JSONP / SecureJSON / PureJSON
  • ResponseWriter — 包装 http.ResponseWriter,自动追踪状态码和响应大小
  • 模板引擎 — LoadHTMLGlob / LoadHTMLFiles / SetHTMLTemplate
  • 静态文件 — 目录列表、SPA fallback、ETag、缓存头、禁止访问规则
  • 插件机制 — 全功能 Plugin 接口,支持中间件/路由/生命周期钩子
  • 多种监听 — TCP / TLS / Unix Socket / Fd / 自定义 Listener

🤖 AI 模块

  • 多 Provider — OpenAI、Anthropic、智谱、DeepSeek、通义千问、百度文心、豆包、Moonshot
  • 本地模型 — Ollama(动态发现)、vLLM、llama.cpp、LM Studio
  • 流式输出 — SSE 流式对话,支持所有 Provider
  • Function Calling — 工具注册、自动调用循环
  • 多轮对话 — 对话管理器,上下文窗口限制
  • 模型降级 — Fallback 链,自动切换备用模型
  • Token 计费 — 用量统计、限额控制、API Key 轮换

快速开始

安装

go get github.com/yourcompany/dhuam

Hello World

package main

import (
    dhuam "github.com/yourcompany/dhuam"
    "github.com/yourcompany/dhuam/middleware"
)

func main() {
    e := dhuam.Default()
    e.Use(middleware.CORS())

    e.GET("/hello/:name", func(c *dhuam.Context) {
        c.String(200, "Hello, %s!", c.Param("name"))
    })

    e.Run(":8080")
}

路由

e := dhuam.Default()

// 基础路由
e.GET("/users", listUsers)
e.POST("/users", createUser)
e.PUT("/users/:id", updateUser)
e.DELETE("/users/:id", deleteUser)

// 路由组
api := e.Group("/api/v1")
api.Use(authMiddleware)
api.GET("/users", listUsers)

// 嵌套路由组
admin := api.Group("/admin")
admin.GET("/dashboard", dashboard)

中间件

// 全局中间件
e.Use(middleware.RequestID())
e.Use(middleware.Logger())
e.Use(middleware.Recovery())
e.Use(middleware.CORS())
e.Use(middleware.Secure())
e.Use(middleware.Compress())
e.Use(middleware.RateLimit(100, 200))

// 认证
e.Use(middleware.Auth(func(token string) (bool, error) {
    return validateToken(token), nil
}))

// 路由组中间件
api := e.Group("/api")
api.Use(middleware.RateLimit(50, 100))

内置中间件

中间件 说明
Logger() 请求日志(text/json 格式)
Recovery() panic 恢复
CORS() 跨域资源共享
Auth() Bearer Token 认证
BasicAuth() HTTP Basic 认证
APIKeyAuth() API Key 认证
RateLimit() 令牌桶限流
PerIPRateLimit() 按 IP 限流
Compress() gzip 压缩
Cache() 内存缓存
Secure() 安全 Headers
CSRF() CSRF 防护
RequestID() 请求 ID
Timeout() 请求超时
Metrics() 指标收集
Pprof() pprof 性能分析

请求处理

参数获取

// 路径参数
id := c.Param("id")           // /users/:id

// 查询参数
page := c.Query("page")
page := c.DefaultQuery("page", "1")
vals := c.QueryArray("tag")   // ?tag=a&tag=b
val, ok := c.GetQuery("page") // (value, exists)

// 表单
name := c.PostForm("name")
name := c.DefaultPostForm("name", "")
vals := c.PostFormArray("tag")

// 文件上传
file, _ := c.FormFile("upload")
c.SaveUploadedFile(file, "/path/to/save")

// Header
auth := c.GetHeader("Authorization")

// Cookie
val, err := c.Cookie("session")

绑定

type CreateUser struct {
    Name  string `json:"name" validate:"required,min=2"`
    Email string `json:"email" validate:"required,email"`
}

// 自动绑定(根据 Content-Type)
var req CreateUser
if err := c.Bind(&req); err != nil {
    return
}

// 指定绑定方式
c.BindJSON(&req)
c.BindXML(&req)
c.BindQuery(&req)    // ?name=xxx&email=xxx
c.BindHeader(&req)   // X-Name: xxx
c.BindUri(&req)      // /users/:id → uri:"id"

// ShouldBind 系列(不自动 Abort)
c.ShouldBindJSON(&req)
c.ShouldBindXML(&req)
c.ShouldBindQuery(&req)
c.ShouldBindHeader(&req)
c.ShouldBindUri(&req)

// 自定义绑定器
c.ShouldBindWith(&req, binding.JSON{})

响应

// 常用响应
dhuam.OK(c, data)              // 200
dhuam.Created(c, data)         // 201
dhuam.NoContent(c)             // 204
dhuam.BadRequest(c, "msg")    // 400
dhuam.Unauthorized(c, "msg")  // 401
dhuam.NotFoundError(c, "msg") // 404

// Context 方法
c.JSON(200, data)              // JSON
c.XML(200, data)               // XML
c.String(200, "hello %s", n)  // 纯文本
c.HTML(200, "<h1>Hi</h1>")    // HTML 字符串
c.Data(200, "image/png", b)   // 原始数据

// 高级 JSON
c.SecureJSON(200, data)        // 防 JSON 劫持
c.AsciiJSON(200, data)         // ASCII JSON
c.PureJSON(200, data)          // 不转义 HTML
c.JSONP(200, "cb", data)       // JSONP

// 文件
c.File("/path/to/file")
c.FileAttachment("/path", "download.pdf")  // 带下载文件名
c.FileFromFS("file.txt", fs)

// 流式
c.SSEvent("message", data)     // Server-Sent Event
c.Stream(func(w io.Writer) bool { ... })

// 其他
c.Redirect(302, "/new")
c.DataFromReader(200, size, "video/mp4", reader, headers)

Context 工具方法

// 键值存取
c.Set("user", user)
val, _ := c.Get("user")
c.GetString("key")
c.GetInt("key")
c.GetBool("key")
c.GetFloat64("key")
c.GetStringSlice("key")
c.GetStringMap("key")

// 请求信息
c.ClientIP()                    // 客户端 IP
c.ContentType()                 // Content-Type
c.IsAjax()                      // 是否 AJAX
c.IsWebsocket()                 // 是否 WebSocket
c.FullPath()                    // 路由完整路径 /users/:id

// 中间件控制
c.Next()                        // 下一个处理器
c.Abort()                       // 中止
c.AbortWithStatus(403)
c.AbortWithStatusJSON(403, H{"error": "forbidden"})
c.AbortWithError(500, err)

// Context 实现了 context.Context 接口
c.Done()
c.Deadline()
c.Err()
c.Value("key")

模板引擎

e := dhuam.New()

// 加载模板
e.LoadHTMLGlob("templates/*")
e.LoadHTMLFiles("templates/index.html", "templates/about.html")

// 自定义模板函数
e.FuncMap["upper"] = strings.ToUpper
e.LoadHTMLGlob("templates/*")

// 使用模板
e.GET("/", func(c *dhuam.Context) {
    c.HTMLTemplate(200, "index.html", H{"title": "Home"})
})

// 设置自定义 template.Template
tmpl := template.Must(template.New("").ParseGlob("views/*"))
e.SetHTMLTemplate(tmpl)

静态文件

// 基础用法
e.Static("/assets", "./public")
e.StaticFile("/favicon.ico", "./favicon.ico")
e.StaticFS("/files", http.Dir("./uploads"))

// 高级配置
e.StaticWithConfig(dhuam.StaticConfig{
    Root:                   "./public",
    Prefix:                 "/static",
    EnableDirectoryListing: true,   // 目录列表
    EnableETag:             true,   // ETag 缓存
    EnableCache:            true,   // Cache-Control
    MaxAge:                 3600,   // 缓存 1 小时
    SPAFallback:            true,   // SPA 模式
    DenyPatterns:           []string{".env", ".git"},  // 禁止访问
})

// SPA 模式(快捷方式)
e.StaticSPA("./dist")  // 未匹配路由 → dist/index.html

静态文件功能

功能 说明
目录列表 自动生成 HTML 目录浏览页面
SPA Fallback 未找到文件时返回 index.html
ETag 基于 SHA256 的 Etag,支持 304 Not Modified
Last-Modified 文件修改时间,支持 If-Modified-Since
Cache-Control 可配置 max-age 缓存时间
安全防护 防目录穿越、禁止访问敏感文件
MIME 类型 自动识别 30+ 常见文件类型

日志

// 内置日志
e.SetLogger(log.NewDefaultLogger())

// slog
e.SetLogger(log.NewSlogLogger())

// zap
zapLogger, _ := log.NewZapLogger()
e.SetLogger(zapLogger)

// 全局日志
log.Info("Server started on :%d", 8080)
log.Error("Failed: %v", err)

插件机制

插件接口

// 实现 Plugin 接口
type Plugin interface {
    Name() string
    Init(e *Engine) error
    Register(e *Engine) error
}

// 可选接口
type PluginWithShutdown interface { Shutdown() error }
type PluginWithMiddleware interface { Middlewares() []HandlerFunc }
type PluginWithRoutes interface { RegisterRoutes(group *RouterGroup) error }

使用插件

e := dhuam.New()

// 安装内置插件
e.Install(&dhuam.HealthCheckPlugin{
    Path: "/health",
    CheckFunc: func() map[string]interface{} {
        return map[string]interface{}{"db": "ok"}
    },
})

e.Install(&dhuam.CORSPlugin{
    AllowOrigins: []string{"https://example.com"},
})

e.Install(&dhuam.MetricsPlugin{Path: "/metrics"})
e.Install(&dhuam.InfoPlugin{Path: "/info"})

// 自定义插件
type MyPlugin struct{ dhuam.BasePlugin }

func (p *MyPlugin) Name() string { return "my-plugin" }
func (p *MyPlugin) Init(e *dhuam.Engine) error { return nil }
func (p *MyPlugin) Register(e *dhuam.Engine) error { return nil }

// 带中间件的插件
func (p *MyPlugin) Middlewares() []dhuam.HandlerFunc {
    return []dhuam.HandlerFunc{myMiddleware}
}

// 带路由的插件
func (p *MyPlugin) RegisterRoutes(g *dhuam.RouterGroup) error {
    g.GET("/hello", func(c *dhuam.Context) { c.String(200, "hi") })
    return nil
}

// 带关闭钩子的插件
func (p *MyPlugin) Shutdown() error {
    // 清理资源
    return nil
}

e.Install(&MyPlugin{})

// 自定义前缀安装
e.InstallGroup(&MyPlugin{}, "/api/my-plugin")

// 查看已安装插件
plugins := e.Plugins()

// 关闭所有插件
e.ShutdownPlugins()

内置插件

插件 说明
HealthCheckPlugin 健康检查端点,支持自定义检查函数
MetricsPlugin 框架指标(路由数、插件数、模式)
CORSPlugin CORS 中间件插件化
InfoPlugin 框架版本和运行信息

运行方式

e := dhuam.New()

// TCP
e.Run(":8080")

// TLS
e.RunTLS(":443", "cert.pem", "key.pem")

// Unix Socket
e.RunUnix("/tmp/dhuam.sock")

// 文件描述符
e.RunFd(3)

// 自定义 Listener
ln, _ := net.Listen("tcp", ":8080")
e.RunListener(ln)

// 优雅关闭
dhuam.RunWithGracefulShutdown(":8080", func(e *dhuam.Engine) {
    e.GET("/", handler)
}, 5*time.Second)

AI 模块

连接云服务

config := &ai.AIConfig{
    DeepSeekKey:  "sk-xxx",
    AnthropicKey: "sk-xxx",
    ZhipuKey:     "xxx.xxx",
    DefaultModel: "deepseek-chat",
}
client := ai.NewClient(config)

连接本地模型

config := &ai.AIConfig{
    OllamaBaseURL:  "http://localhost:11434",
    VLLMBaseURL:    "http://localhost:8000",
    LLamaCppBaseURL: "http://localhost:8080",
}

对话

// 非流式
resp, _ := client.Chat(ctx, &ai.ChatRequest{
    Model:    "deepseek-chat",
    Messages: []ai.Message{{Role: "user", Content: "Hello!"}},
})

// 流式
stream, _ := client.ChatStream(ctx, req)
for chunk := range stream { ... }

// 快速对话
answer, _ := client.QuickChat(ctx, "deepseek-chat", "你好")

Function Calling / 多轮对话 / 模型降级

详见 AI 模块文档本地模型指南

项目结构

dhuam/
├── dhuam.go            # 入口、全局函数
├── engine.go           # Engine 核心(http.Server)
├── router.go           # 基数树路由器
├── context.go          # 请求上下文(参数、绑定、响应)
├── response_writer.go  # ResponseWriter 包装器
├── group.go            # 路由组
├── config.go           # 框架配置
├── errors.go           # HTTP 错误
├── static.go           # 增强静态文件服务
├── plugin.go           # 插件机制
├── dhuam_helpers.go    # 便捷函数
├── ai/                 # AI 多模型接入
│   ├── provider/       # Provider 实现
│   └── types/          # 类型定义
├── middleware/          # 中间件(14 个内置)
├── binding/            # 请求绑定(JSON/XML/Form/Query/Header/URI)
├── validate/           # 结构体验证
├── render/             # 渲染器(JSON/XML/HTML/Stream/JSONP)
├── log/                # 日志适配(slog/zap/内置)
├── pool/               # 对象池
├── errors/             # 扩展错误(链式 API)
└── internal/utils/     # 工具函数

示例

示例 说明
examples/web/ Web 框架基础(路由、绑定、验证)
examples/middleware/ 中间件使用
examples/ai/ AI 模块完整示例
examples/local/ 本地模型接入
examples/tools/ Function Calling
examples/conversation/ 多轮对话

国际化 i18n

import "github.com/yourcompany/dhuam/i18n"

// 初始化(默认英文)
i18n.Init(i18n.En)

// 切换为中文
i18n.Init(i18n.Zh)

// 翻译
msg := i18n.T(i18n.MsgNotFound)              // "资源未找到"
msgEN := i18n.Tl(i18n.En, i18n.MsgNotFound)  // "resource not found"

// 注册自定义消息
i18n.RegisterMessages(i18n.Zh, map[i18n.MessageKey]string{
    "welcome": "欢迎",
    "goodbye": "再见",
})

// 支持的语言:en, zh, ja, ko, fr, de, es, ru, ar, pt

第三方中间件适配

// 适配标准 http.Handler 中间件
e.Use(dhuam.WrapMiddleware(cors.Handler(cors.Options{
    AllowedOrigins: []string{"*"},
})))

// 适配标准 http.HandlerFunc
e.Use(dhuam.WrapF(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-Custom", "value")
}))

// 适配 gorilla/negroni 风格
e.Use(dhuam.FromNegroni(func(w, r, next) {
    // ...
    next(w, r)
}))

// 适配 alice 链
chain := alice.New(mw1, mw2)
e.Use(dhuam.FromAlice(chain))

// 集成第三方路由器
e.GET("/metrics", dhuam.WrapHTTPHandler(promhttp.Handler()))

文档

文档 说明
README.md 完整使用文档
KNOWN_BUGS.md 已知问题和限制
DESIGN_DEVICE.md Device 模块设计
docs/ai_guide.md AI 模块文档
docs/local_models.md 本地模型指南

License

MIT