Vigo 是一个高性能、简洁易用的 Go Web 框架,专为构建现代 RESTful API 而设计。它提供了强大的路由系统、智能参数解析、灵活的中间件机制。
- 高性能路由系统 - 基于 Radix Tree 和零分配(Zero-Allocation)设计,支持有序匹配、回溯和优先级控制
- 灵活的路由语法 - 支持
{param}、{path:*}、**、正则约束{id:[0-9]+}以及复合匹配{file}.{ext} - 智能参数解析 - 自动从 Path、Query、Header、JSON、Form 等多种来源解析参数到结构体
- 类型安全 - 强类型的参数解析和验证,减少运行时错误
- 中间件机制 - 支持全局、路由组和单个路由级别的中间件(Use/After)
- 生产就绪 - 支持 SSE、文件服务、优雅关闭等特性
go mod init your-project
go get github.com/veypi/vigopackage main
import (
"github.com/veypi/vigo"
"github.com/veypi/vigo/logv"
)
func main() {
// 创建应用
app, err := vigo.New()
if err != nil {
logv.Fatal().Err(err).Msg("Failed to create app")
}
// 注册路由
router := app.Router()
// 基础路由
router.Get("/hello", hello)
// 带参数的路由
router.Get("/user/{id}", getUser)
// 正则约束路由
router.Get("/files/{file:[a-z]+}.{ext}", getFile)
// 启动服务
logv.Info().Msg("Starting server on :8000")
if err := app.Run(); err != nil {
logv.Fatal().Err(err).Msg("Server failed")
}
}
func hello(x *vigo.X) (any, error) {
return map[string]string{"message": "Hello, Vigo!"}, nil
}
type getUserOpts struct {
ID string `json:"id" src:"path"`
}
func getUser(x *vigo.X) (any, error) {
args := &getUserOpts{}
if err := x.Parse(args); err != nil {
return nil, err
}
return map[string]any{
"id": args.ID,
"name": "User " + args.ID,
}, nil
}
func getFile(x *vigo.X) {
file := x.PathParams.Get("file")
ext := x.PathParams.Get("ext")
x.String(200, "File: %s, Ext: %s", file, ext)
}Vigo 采用了全新的路由引擎,支持丰富且直观的匹配规则:
最普通的路径匹配。
router.Get("/users/list", handler)匹配单个路径段,参数值可以通过 x.PathParams.Get("id") 获取,或通过结构体 src:"path" 标签自动解析。
router.Get("/users/{id}", handler)Vigo 支持将 HTTP 请求参数自动解析到 Go 结构体中。
标签语法: src:"source[@alias]"
src:"path": 路径参数 (默认匹配同名字段,可指定@alias)src:"query": URL 查询参数src:"header": 请求头src:"form": 表单数据 (支持application/x-www-form-urlencoded和multipart/form-data)src:"json": JSON 请求体 (默认)
其他标签:
default: 设置默认值 (仅限非指针/非JSON字段)json: 指定 JSON 字段名
示例:
src:"query@page_size": 映射 URL 参数?page_size=10到结构体字段src:"header@X-User-ID": 映射请求头X-User-ID到结构体字段
必填项规则:
- 非指针类型(如
string,int)默认为必填。如果请求中缺少该参数,解析会失败并返回409 Invalid Arg错误。(注:空值如?name=被视为参数存在,是合法的) - 指针类型(如
*string,*int)为可选。如果请求中缺少该参数,字段值为nil。 - 使用
default标签可以为必填参数提供默认值。
type UserReq struct {
ID string `src:"path"` // 必填,路径参数
Name string `src:"query"` // 必填,缺少则报错(空字符串合法)
Age *int `src:"query"` // 可选,缺少则为 nil
Role string `src:"query" default:"user"` // 必填但有默认值
Token string `src:"header@X-Auth-Token"` // 从 Header 中获取 X-Auth-Token
Page int `src:"query@p"` // 从 Query 中获取 p 参数 (如 ?p=1)
}匹配当前段及其之后的所有内容(非贪婪,除非是最后一个节点)。
router.Get("/static/{filepath:*}", handler)
// 或简写
router.Get("/static/*", handler)匹配剩余所有路径,通常用于 SPA 前端路由兜底或文件服务。
router.Get("/assets/**", handler)只有当路径段满足正则表达式时才匹配。
// 仅匹配数字 ID
router.Get("/users/{id:[0-9]+}", handler)在一个路径段内匹配多个参数,支持前缀、后缀和中缀匹配。
// 匹配如 "style.css", "script.js"
router.Get("/static/{name}.{ext}", handler)
// 匹配如 "v1-api", "v2-api"
router.Get("/{version}-api", handler)Vigo 的请求处理采用洋葱模型(Onion Model)构建的流水线。
对于一个特定路由,处理链由以下部分组成,并按顺序执行:
- 父路由 Before 中间件 (从根路由向下)
- 当前路由 Before 中间件
- 路由处理函数 (Set/Get/Post 等注册的 handler)
- 当前路由 After 中间件
- 父路由 After 中间件 (从当前路由向上)
Vigo 支持极其灵活的 Handler 函数签名,你可以根据需要选择最适合的形式:
- 标准形式:
func(*vigo.X) - 带错误返回:
func(*vigo.X) error(返回 error 会中断流水线并触发错误处理) - 标准 HTTP:
func(http.ResponseWriter, *http.Request) - 管道模式:
func(*vigo.X, any)(接收x.PipeValue,可用于在中间件间传递数据) - 错误处理:
func(*vigo.X, error) error(仅在发生错误时执行)
所有支持的签名:
func(*X)func(*X) errorfunc(*X) anyfunc(*X) (any, error)func(*X, any)func(*X, any) anyfunc(*X, any) errorfunc(*X, any) (any, error)func(http.ResponseWriter, *http.Request)func(http.ResponseWriter, *http.Request) error
使用 vigo.SkipBefore 可以让当前路由跳过所有父级路由定义的 Before 中间件(但保留 After 中间件)。这在某些无需鉴权或需要特殊处理的接口(如登录、公开资源)非常有用。
// 登录接口跳过鉴权中间件
router.Get("/login", vigo.SkipBefore, loginHandler)Vigo 支持直接注册强类型的 Handler,框架会自动解析请求参数并处理响应,无需手动调用辅助函数。
// 定义请求结构体
type UserReq struct {
Name string `json:"name"`
}
// 定义响应结构体
type UserResp struct {
ID string `json:"id"`
Name string `json:"name"`
}
// 强类型 Handler
func CreateUser(x *vigo.X, req *UserReq) (*UserResp, error) {
// req 已经被自动解析填充
return &UserResp{ID: "1", Name: req.Name}, nil
}
// 注册路由
router.Post("/users", CreateUser)- 自动执行: 默认情况下,流水线中的 Handler 会自动顺序执行。
- x.Next(): 在中间件中调用
x.Next()可以显式执行后续 Handler,并在其返回后继续执行当前中间件的剩余逻辑(用于后置处理,如计算耗时)。 - x.Stop(): 停止流水线,后续 Handler 不再执行。
- 返回 error: 停止流水线,并将 error 传递给后续的
FuncErr类型的 Handler 进行处理。
- 框架: vigo (github.com/veypi/vigo)
- 语言: Golang 1.24+