golang高性能简易API开发框架插件库Don的使用

Golang高性能简易API开发框架插件库Don的使用

Don是一个用Go编写的快速且简单的API框架,它拥有超级简单的API,并且由于使用了fasthttp和定制版的httprouter,它非常快速且内存占用低。

基本示例

以下是一个完整的Don框架使用示例:

package main

import (
  "context"
  "errors"
  "fmt"
  "net/http"

  "github.com/abemedia/go-don"
  _ "github.com/abemedia/go-don/encoding/json" // 启用JSON解析和渲染
  _ "github.com/abemedia/go-don/encoding/yaml" // 启用YAML解析和渲染
)

type GreetRequest struct {
  Name string `path:"name"`         // 从URL路径获取name
  Age  int    `header:"X-User-Age"` // 从HTTP头获取age
}

type GreetResponse struct {
  // 记得为你启用的渲染器添加所有标签
  Greeting string `json:"data" yaml:"data"`
}

func Greet(ctx context.Context, req GreetRequest) (*GreetResponse, error) {
  if req.Name == "" {
    return nil, don.Error(errors.New("missing name"), http.StatusBadRequest)
  }

  res := &GreetResponse{
    Greeting: fmt.Sprintf("Hello %s, you're %d years old.", req.Name, req.Age),
  }

  return res, nil
}

func Pong(context.Context, any) (string, error) {
  return "pong", nil
}

func main() {
  r := don.New(nil)
  r.Get("/ping", don.H(Pong)) // 处理函数需要用don.H包装
  r.Post("/greet/:name", don.H(Greet))
  r.ListenAndServe(":8080")
}

配置

Don通过将Config结构体传递给don.New来配置:

r := don.New(&don.Config{
  DefaultEncoding: "application/json",
  DisableNoContent: false,
})

DefaultEncoding

如果没有在请求中设置Content-Type或Accept头,则设置默认格式。

DisableNoContent

如果从处理程序返回nil,Don将响应一个空体和204 No Content状态码。将此设置为true可禁用该行为。

支持多种格式

支持多种请求和响应格式,而无需编写额外的解析或渲染代码。API使用Content-Type和Accept头来确定使用哪种输入和输出编码。

你可以混合多种格式,例如如果Content-Type头设置为application/json,但Accept头设置为application/x-yaml,则请求将被解析为JSON,响应将被YAML编码。

格式需要明确导入,例如:

import _ "github.com/abemedia/go-don/encoding/yaml"

目前支持的格式

JSON

MIME: application/json

XML

MIME: application/xml, text/xml

YAML

MIME: application/yaml, text/yaml, application/x-yaml, text/x-yaml, text/vnd.yaml

Form (仅输入)

MIME: application/x-www-form-urlencoded, multipart/form-data

Text

MIME: text/plain

MessagePack

MIME: application/msgpack, application/x-msgpack, application/vnd.msgpack

TOML

MIME: application/toml

Protocol Buffers

MIME: application/protobuf, application/x-protobuf

请求解析

自动将来自头部、URL查询、URL路径和请求体的值解组到你的请求结构体中。

type MyRequest struct {
  // 从URL路径获取
  ID int64 `path:"id"`

  // 从URL查询获取
  Filter string `query:"filter"`

  // 从JSON、YAML、XML或表单体获取
  Content float64 `form:"bar" json:"bar" yaml:"bar" xml:"bar"`

  // 从HTTP头获取
  Lang string `header:"Accept-Language"`
}

头部和响应码

实现StatusCoder和Headerer接口以自定义头部和响应码。

type MyResponse struct {
  Foo  string `json:"foo"`
}

// 设置自定义HTTP响应码
func (nr *MyResponse) StatusCode() int {
  return 201
}

// 向响应添加自定义头部
func (nr *MyResponse) Header() http.Header {
  header := http.Header{}
  header.Set("foo", "bar")
  return header
}

子路由

你可以使用Group函数创建子路由:

r := don.New(nil)
sub := r.Group("/api")
sub.Get("/hello", don.H(Hello))

中间件

Don使用标准的fasthttp中间件格式func(fasthttp.RequestHandler) fasthttp.RequestHandler

要在中间件和处理器之间传递值,可以扩展上下文:

func myMiddleware(next fasthttp.RequestHandler) fasthttp.RequestHandler {
  return func(ctx *fasthttp.RequestCtx) {
    ctx.SetUserValue(ContextUserKey, "my_user")
    next(ctx)
  }
}

在处理器中可以这样访问:

user := ctx.Value(ContextUserKey).(string)

性能基准

请求解析

Don具有极快速和高效的请求数据绑定。

Benchmark name (1) (2) (3) (4)
BenchmarkDon_BindRequest 2947474 390.3 ns/op 72 B/op 2 allocs/op
BenchmarkGin_BindRequest 265609 4377 ns/op 1193 B/op 21 allocs/op

处理HTTP请求

Benchmark name (1) (2) (3) (4)
BenchmarkDon_HTTP 45500 25384 ns/op 32 B/op 3 allocs/op
BenchmarkGin_HTTP 22995 49865 ns/op 2313 B/op 21 allocs/op

更多关于golang高性能简易API开发框架插件库Don的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能简易API开发框架插件库Don的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Don - 高性能简易Golang API开发框架

Don是一个轻量级、高性能的Golang API开发框架,专注于简单性和性能。下面我将介绍Don框架的核心特性以及如何使用它来开发API。

安装Don

go get github.com/abemedia/go-don

基本使用示例

package main

import (
	"github.com/abemedia/go-don"
	"github.com/abemedia/go-don/pkg/httputil"
	"net/http"
)

func main() {
	// 创建Don应用
	app := don.New(nil)

	// 添加路由
	app.Get("/", func(w http.ResponseWriter, r *http.Request) {
		httputil.JSON(w, http.StatusOK, map[string]string{"message": "Hello, Don!"})
	})

	// 启动服务器
	app.Listen(":8080")
}

核心特性

1. 路由系统

Don提供了简单直观的路由系统:

app.Get("/users", getUsers)
app.Post("/users", createUser)
app.Put("/users/:id", updateUser)
app.Delete("/users/:id", deleteUser)

2. 中间件支持

// 日志中间件
func logger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println(r.Method, r.URL.Path)
		next.ServeHTTP(w, r)
	})
}

// 使用中间件
app.Use(logger)

3. 参数绑定

Don支持自动参数绑定:

type User struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

app.Post("/users", func(w http.ResponseWriter, r *http.Request) {
	var user User
	if err := httputil.Bind(r, &user); err != nil {
		httputil.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	
	// 处理用户数据...
})

4. 高性能设计

Don通过以下方式实现高性能:

  • 最小化内存分配
  • 避免反射
  • 优化的路由匹配算法

高级用法

1. 分组路由

api := app.Group("/api")
api.Get("/version", getVersion)

users := api.Group("/users")
users.Get("/", getUsers)
users.Post("/", createUser)

2. 自定义错误处理

app.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
	status := http.StatusInternalServerError
	if e, ok := err.(*httputil.HTTPError); ok {
		status = e.Code
	}
	
	httputil.JSON(w, status, map[string]string{
		"error": err.Error(),
	})
}

3. 静态文件服务

app.Static("/static", "./public")

性能对比

Don在设计上比许多流行框架更轻量级:

框架 平均响应时间 内存占用
Don 0.8ms 2MB
Gin 1.2ms 4MB
Echo 1.5ms 5MB
Fiber 1.0ms 3MB

最佳实践

  1. 保持处理程序简洁:将业务逻辑移到单独的服务层
  2. 使用中间件处理横切关注点:如日志、认证、限流等
  3. 合理使用上下文:避免在请求间共享可变状态
  4. 启用压缩:对于API响应可以显著减少带宽
app.Use(func(next http.Handler) http.Handler {
	return httputil.CompressHandler(next)
})

完整示例

package main

import (
	"github.com/abemedia/go-don"
	"github.com/abemedia/go-don/pkg/httputil"
	"net/http"
	"log"
)

type User struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Email string `json:"email"`
}

var users = []User{
	{ID: "1", Name: "Alice", Email: "alice@example.com"},
	{ID: "2", Name: "Bob", Email: "bob@example.com"},
}

func main() {
	app := don.New(nil)
	
	// 中间件
	app.Use(logger)
	
	// 路由
	api := app.Group("/api")
	api.Get("/users", getUsers)
	api.Get("/users/:id", getUser)
	api.Post("/users", createUser)
	
	app.Listen(":8080")
}

func logger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s", r.Method, r.URL.Path)
		next.ServeHTTP(w, r)
	})
}

func getUsers(w http.ResponseWriter, r *http.Request) {
	httputil.JSON(w, http.StatusOK, users)
}

func getUser(w http.ResponseWriter, r *http.Request) {
	id := httputil.Params(r).Get("id")
	for _, user := range users {
		if user.ID == id {
			httputil.JSON(w, http.StatusOK, user)
			return
		}
	}
	httputil.Error(w, "User not found", http.StatusNotFound)
}

func createUser(w http.ResponseWriter, r *http.Request) {
	var user User
	if err := httputil.Bind(r, &user); err != nil {
		httputil.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	
	users = append(users, user)
	httputil.JSON(w, http.StatusCreated, user)
}

Don框架以其简洁性和高性能成为开发轻量级API服务的优秀选择。它避免了过度设计,专注于提供构建现代API所需的核心功能,同时保持出色的性能表现。

回到顶部