Help us shape the future of Go! Take the 2026 Go Developer Survey

serve

package module
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2026 License: MIT Imports: 4 Imported by: 0

README

serve | 完全基于 Go net/http 的 Web 框架

轻量, 原生, 贴近标准库

其实就是封装了标准库的功能, 仅此而已

开始使用

go get -u github.com/UnknownMp391/serve

要求 Go 1.22+ (使用增强路由特性)

特性

分组路由, 方法路由, 路由参数, 中间件

使用 Go 1.22+ 的增强路由特性

配合 BetterMux 的分组, 中间件语法糖包装

实现对基础路由需求的支持

s := serve.NewServe()

s.Get("/{$}", func(ctx *serve.ServeContext) {
    ctx.WriteText("Hello World!")
})

s.Get("/greet/{name}", func(ctx *serve.ServeContext) {
    ctx.WriteText("Hello " + ctx.Request.PathValue("name"))
})

s.With(func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println(">> Request")
        next.ServeHTTP(w, r)
    })
}).Get("/logged", func(ctx *serve.ServeContext) {
    ctx.WriteText("Hello with log")
})

http.ListenAndServe(":8080", s)
自动 JSON 解码, 编码

在自定义请求中封装 json.{NewDecoder,NewEncoder} 为 ReadJson(any), WriteJson(any) 实现快捷 JSON 解码和编码

type CreateUserReq struct {
    Name string `json:"name"`
}

type CreateUserResp struct {
    Name string `json:"name"`
    Id   int    `json:"id"`
}

s.Post("/user", func(ctx *serve.ServeContext) {
    req := CreateUserReq{}
    ctx.ReadJson(&req)

    ctx.WriteJson(&CreateUserResp{
        Id:   1,
        Name: req.Name,
    })
})
依赖注入 (全局单例, 请求单例)

通过 github.com/UnknownMp391/betterdep 提供

使用 Go 1.18+ 的泛型

基于 map 实现的简单 DI

使用 betterdep.Dependency 创建一个依赖

通过 betterdep.Provide(ctx.SingletonDeps, OneProvider) 获得全局单例, 或 betterdep.Provide(ctx.ScopedDeps, OneProvider) 获得请求级单例 (请求结束后自动 Dispose)

var OtherProvider betterdep.Dependency[DB] = betterdep.Dependency[DB]{
    Identifier: "otherid",
    Resolver: func(s *betterdep.DependencyManager) (DB, func(), error) {
        db, _ := sql.Open("sqlite", "app.db")
        return db, func() { db.Close() }, nil
    },
}

var OneProvider betterdep.Dependency[Service] = betterdep.Dependency[Service]{
    Identifier: "id",
    Resolver: func(s *betterdep.DependencyManager) (Service, func(), error) {

        otherDep, err := betterdep.Provide(s, &OtherProvider)
        if err != nil {
            return Service{}, nil, err
        }

        // some logic...

        return Service{DB: otherDep}, nil, nil
    },
}

s.Get("/users", func(ctx *serve.ServeContext) {
    svc, _ := betterdep.Provide(ctx.SingletonDeps, &OneProvider)
    // ...
})
内置中间件
s := serve.NewServe().With(serve.Recover()) // panic 自动返回 500

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Recover added in v0.3.0

func Recover() func(http.Handler) http.Handler

Recover 返回一个捕获 panic 并响应 500 的中间件, 避免 handler panic 时连接被标准库直接断开

Example

对应 README「内置中间件」示例

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/UnknownMp391/betterdep"
	"github.com/UnknownMp391/serve"
)

func main() {
	s := serve.NewServe().With(func(_ *betterdep.DependencyManager) func(http.Handler) http.Handler {
		return serve.Recover()
	})

	s.Get("/boom", func(ctx *serve.ServeContext) {
		panic("boom")
	})

	req := httptest.NewRequest(http.MethodGet, "/boom", nil)
	rr := httptest.NewRecorder()
	s.ServeHTTP(rr, req)

	fmt.Println(rr.Code)
}
Output:
500

Types

type Serve

type Serve struct {
	// Mux 底层路由器
	Mux *bettermux.BetterMux
	// SingletonDeps 全局单例依赖管理器, 进程生命周期内复用
	SingletonDeps *betterdep.DependencyManager
	// ServeFunc 用于代表包装中间件的 Serve 的 Handler
	ServeFunc http.Handler
}

Serve 是 serve 框架的核心: 包装了基于 net/http 增强路由的路由器, 并持有进程级全局单例依赖管理器

直接作为 http.Handler 使用 (例如传给 http.ListenAndServe)

func NewServe

func NewServe() *Serve

NewServe 创建一个新的 Serve 实例

func (*Serve) Delete

func (s *Serve) Delete(pattern string, handler ServeHandlerFunc)

Delete 注册 DELETE 方法路由, pattern 支持 Go 1.22+ 路由参数

func (*Serve) Get

func (s *Serve) Get(pattern string, handler ServeHandlerFunc)

Get 注册 GET 方法路由, pattern 支持 Go 1.22+ 路由参数(如 "/greet/{name}")

Example

对应 README「分组路由, 方法路由, 路由参数」示例

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/UnknownMp391/serve"
)

func main() {
	s := serve.NewServe()

	s.Get("/greet/{name}", func(ctx *serve.ServeContext) {
		ctx.WriteText("Hello " + ctx.Request.PathValue("name"))
	})

	req := httptest.NewRequest(http.MethodGet, "/greet/kai", nil)
	rr := httptest.NewRecorder()
	s.ServeHTTP(rr, req)

	fmt.Print(rr.Body.String())
}
Output:
Hello kai

func (*Serve) HandleFunc

func (s *Serve) HandleFunc(pattern string, handler ServeHandlerFunc)

HandleFunc 注册 pattern 的 handler,

func (*Serve) Options

func (s *Serve) Options(pattern string, handler ServeHandlerFunc)

Options 注册 OPTIONS 方法路由, pattern 支持 Go 1.22+ 路由参数

func (*Serve) Patch

func (s *Serve) Patch(pattern string, handler ServeHandlerFunc)

Patch 注册 PATCH 方法路由, pattern 支持 Go 1.22+ 路由参数

func (*Serve) Post

func (s *Serve) Post(pattern string, handler ServeHandlerFunc)

Post 注册 POST 方法路由, pattern 支持 Go 1.22+ 路由参数

func (*Serve) Put

func (s *Serve) Put(pattern string, handler ServeHandlerFunc)

Put 注册 PUT 方法路由, pattern 支持 Go 1.22+ 路由参数

func (*Serve) Route

func (s *Serve) Route(pattern string, h func(*Serve)) *Serve

Route 创建分组路由:回调 h 中注册的所有路由统一挂在 pattern 前缀之下, 返回的子 Serve 与当前 Serve 共享全局单例依赖管理器

func (*Serve) ServeHTTP

func (s *Serve) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP 实现 http.Handler 接口, 将请求交给底层路由器处理

func (*Serve) Use added in v0.4.0

func (s *Serve) Use(mw ...func(sdm *betterdep.DependencyManager) func(http.Handler) http.Handler) *Serve

Use 派生一个 **路由之前** 会执行中间件的 Serve, 支持多个中间件, 后声明的先执行 本方法仅适用于在构建完成, 传递给 net/http 的最后调用 需要路由后应用则应该使用 With 需要访问依赖的中间件可直接通过闭包捕获 s.SingletonDeps

func (*Serve) With

func (s *Serve) With(mw ...func(sdm *betterdep.DependencyManager) func(http.Handler) http.Handler) *Serve

With 派生一个在 **路由之后** 会应用中间件的新 Serve, 支持多个中间件, 先声明的先执行 需要路由前应用则应该使用 Use 需要访问依赖的中间件可直接通过闭包捕获 s.SingletonDeps

Example

对应 README「中间件」示例

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/UnknownMp391/betterdep"
	"github.com/UnknownMp391/serve"
)

func main() {
	s := serve.NewServe().With(func(_ *betterdep.DependencyManager) func(http.Handler) http.Handler {
		return func(next http.Handler) http.Handler {
			return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				w.Header().Set("X-Logged", "true")
				next.ServeHTTP(w, r)
			})
		}
	})

	s.Get("/logged", func(ctx *serve.ServeContext) {
		ctx.WriteText("Hello with log")
	})

	req := httptest.NewRequest(http.MethodGet, "/logged", nil)
	rr := httptest.NewRecorder()
	s.ServeHTTP(rr, req)

	fmt.Println(rr.Header().Get("X-Logged"), rr.Body.String())
}
Output:
true Hello with log

type ServeContext

type ServeContext struct {
	betterwr.BetterWR
	// SingletonDeps 全局单例依赖管理器(与 Serve 共享同一实例)
	SingletonDeps *betterdep.DependencyManager
	// ScopedDeps 请求级依赖管理器, 每个请求新建, 请求处理结束后自动 Dispose
	ScopedDeps *betterdep.DependencyManager
}

ServeContext 是每个请求的处理上下文: 内嵌了请求 / 响应封装 (betterwr.BetterWR), 并暴露全局单例与请求级作用域的依赖管理器

type ServeHandlerFunc

type ServeHandlerFunc func(ctx *ServeContext)

ServeHandlerFunc 是 serve 的 handler 类型, 接收当前请求的 *ServeContext

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL