golang自动生成HTTP输入输出处理样板代码插件库VarHandler的使用

Golang自动生成HTTP输入输出处理样板代码插件库VarHandler的使用

VarHandler是一个用于简化Golang HTTP开发过程的工具,它可以自动生成HTTP输入输出处理的样板代码,同时保持HTTP兼容性。

核心功能

VarHandler能够自动生成以下HTTP处理步骤:

  1. 从HTTP请求获取参数并验证
  2. 处理验证错误
  3. 调用业务函数
  4. 处理业务函数返回的错误
  5. 生成HTTP响应

响应类型

业务函数可以有以下几种返回形式:

func F(x X, y Y) (err error)                                   // 默认成功状态码200
                                                               // 未知错误返回500

func F(x X, y Y) (status int, err error)                       // 设置返回状态码

func F(x X, y Y) (response interface{}, err error)             // 特定响应

func F(x X, y Y) (response interface{}, status int, err error) // 设置状态码和响应

参数处理

函数可以接受一个或多个参数,这些参数需要定义对应的HTTP实例化器:

HTTPX(r *http.Request) (x X, err error)

错误处理

如果实例化过程中发生错误:

HandleHttpErrorWithDefaultStatus(w, r, http.StatusBadRequest, err) // 会被调用

如果业务函数返回错误:

HandleHttpErrorWithDefaultStatus(w, r, http.StatusInternalServerError, err) // 会被调用

完整示例

传统方式

myHttpHandler(w http.ResponseWriter, r *http.Request) {
    var x X
    err := json.NewDecoder(r.Body).Decode(x)
    if err != nil {
       // 错误处理
       return
    }
    err := validate(x)
    if err != nil {
       // 错误处理
       return
    }
    // 重复处理y和z
    // 从zz包获取zz
    response, status, err := F(x, y, z, zz)
    if err != nil {
        // 返回500错误
    }
    w.WriteHeader(status)
    json.NewEncoder(w).Encode(response)
}

使用VarHandler的方式

//go:generate varhandler -func F
package server

import "github.com/azr/generators/varhandler/examples/z"

func F(x X, y Y, z *Z, zz z.Z) (resp interface{}, status int, err error) {...}

// HTTP实例化器:

func HTTPX(r *http.Request) (x X, err error)   { err = json.NewDecoder(r.Body).Decode(&x) }
func HTTPY(r *http.Request) (Y, error)         {...}
func HTTPZ(r *http.Request) (*Z, error)        {...}
func z.HTTPZ(r *http.Request) (z.Z, error)     {...}

VarHandler会生成以下代码:

  1. 调用HTTPX、HTTPY、HTTPX和z.HTTPZ及其错误检查
  2. 调用F(x, y, z, zz)
  3. 根据F的返回参数生成HTTP响应代码

生成的代码示例

func FHandler(w http.ResponseWriter, r *http.Request) {
    var err error
    x, err := HTTPX(r)
    if err != nil {
       HandleHttpErrorWithDefaultStatus(w, r, http.StatusBadRequest, err)
       return
    }
    y, err := HTTPY(r)
    if err != nil {
       HandleHttpErrorWithDefaultStatus(w, r, http.StatusBadRequest, err)
       return
    }
    z, err := HTTPZ(r)
    if err != nil {
       HandleHttpErrorWithDefaultStatus(w, r, http.StatusBadRequest, err)
       return
    }
    zz, err := z.HTTPZ(r)
    if err != nil {
       HandleHttpErrorWithDefaultStatus(w, r, http.StatusBadRequest, err)
       return
    }
    resp, status, err := F(x, y, z, zz)
    if err != nil {
       HandleHttpErrorWithDefaultStatus(w, r, http.StatusInternalServerError, err)
       return
    }
    if status != 0 { // 如果F返回了状态码
       w.WriteHeader(status)
    }
    if resp != nil { // 如果F返回了响应对象
       HandleHttpResponse(w, r, resp)
    }
}

// 辅助函数

func HandleHttpErrorWithDefaultStatus(w http.ResponseWriter, r *http.Request, status int, err error) {
    type HttpError interface {
       HttpError() (error string, code int)
    }
    type SelfHttpError interface {
       HttpError(w http.ResponseWriter)
    }
    switch t := err.(type) {
    default:
       w.WriteHeader(status)
    case HttpError:
       err, code := t.HttpError()
       http.Error(w, err, code)
    case http.Handler:
       t.ServeHTTP(w, r)
    case SelfHttpError:
       t.HttpError(w)
    }
}

func HandleHttpResponse(w http.ResponseWriter, r *http.Request, resp interface{}) {
    type Byter interface {
       Bytes() []byte
    }
    type Stringer interface {
       String() string
    }
    switch t := resp.(type) {
    default:
       // 未知类型
    case http.Handler:
       t.ServeHTTP(w, r) // 响应对象知道如何处理自己
    case Byter:
       w.Write(t.Bytes())
    case Stringer:
       w.Write([]byte(t.String()))
    case []byte:
       w.Write(t)
    }
}

更多关于golang自动生成HTTP输入输出处理样板代码插件库VarHandler的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang自动生成HTTP输入输出处理样板代码插件库VarHandler的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang HTTP 处理样板代码生成工具 VarHandler 使用指南

VarHandler 是一个用于自动生成 Golang HTTP 输入输出处理样板代码的工具,它可以显著减少编写 HTTP API 时的重复代码工作。

安装 VarHandler

首先安装 VarHandler 工具:

go install github.com/stoewer/go-varhandler@latest

基本使用

1. 定义处理函数

首先定义一个普通的 Go 函数,VarHandler 会根据这个函数的签名自动生成 HTTP 处理器:

//go:generate varhandler -func GetUser
func GetUser(id int64) (*User, error) {
    // 业务逻辑
    if id <= 0 {
        return nil, errors.New("invalid user id")
    }
    
    return &User{
        ID:   id,
        Name: "John Doe",
    }, nil
}

2. 生成处理器代码

在包含上述代码的文件中运行:

go generate

这将生成一个 GetUserHandler 函数,可以直接用于 HTTP 路由。

3. 使用生成的处理器

package main

import (
    "net/http"
)

func main() {
    http.HandleFunc("/user", GetUserHandler)
    http.ListenAndServe(":8080", nil)
}

功能特性

参数绑定

VarHandler 支持从以下位置自动绑定参数:

  • URL 路径参数
  • 查询字符串
  • JSON 请求体
  • 表单数据
  • HTTP 头
//go:generate varhandler -func CreateUser
func CreateUser(req *http.Request, user *User) (*User, error) {
    // 业务逻辑
    return user, nil
}

响应处理

VarHandler 自动处理响应:

  • 如果返回 error 不为 nil,生成 400 或 500 错误响应
  • 如果返回值为非 nil,生成 200 成功响应
  • 支持自定义状态码
//go:generate varhandler -func UpdateUser -status 204
func UpdateUser(id int64, user *User) error {
    // 业务逻辑
    return nil
}

自定义选项

VarHandler 提供多种选项来自定义行为:

//go:generate varhandler -func SearchUsers -query -response 200:[]User -response 404:ErrorResponse
func SearchUsers(query string, limit int) ([]User, error) {
    // 业务逻辑
    return []User{}, nil
}

高级用法

中间件支持

生成的处理器兼容标准 http.Handler 接口,可以轻松添加中间件:

func loggingMiddleware(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)
    })
}

func main() {
    handler := loggingMiddleware(http.HandlerFunc(GetUserHandler))
    http.Handle("/user", handler)
    http.ListenAndServe(":8080", nil)
}

自定义错误处理

//go:generate varhandler -func GetUser -error ErrorResponse
func GetUser(id int64) (*User, error) {
    if id <= 0 {
        return nil, &ErrorResponse{
            Code:    400,
            Message: "Invalid user ID",
        }
    }
    return &User{ID: id, Name: "John Doe"}, nil
}

实际示例

完整的 API 示例

package main

import (
    "errors"
    "net/http"
)

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

type ErrorResponse struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
}

//go:generate varhandler -func GetUser -error ErrorResponse
func GetUser(id int64) (*User, error) {
    if id <= 0 {
        return nil, &ErrorResponse{
            Code:    400,
            Message: "Invalid user ID",
        }
    }
    return &User{ID: id, Name: "John Doe"}, nil
}

//go:generate varhandler -func CreateUser -status 201
func CreateUser(user *User) (*User, error) {
    if user.Name == "" {
        return nil, errors.New("name is required")
    }
    user.ID = 1 // 模拟数据库ID分配
    return user, nil
}

func main() {
    http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet:
            GetUserHandler(w, r)
        case http.MethodPost:
            CreateUserHandler(w, r)
        default:
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        }
    })
    
    http.ListenAndServe(":8080", nil)
}

总结

VarHandler 的主要优点:

  1. 减少样板代码,专注于业务逻辑
  2. 自动处理参数绑定和响应编码
  3. 支持多种输入输出格式
  4. 与标准库无缝集成
  5. 通过 go generate 轻松生成代码

通过使用 VarHandler,你可以显著提高开发 HTTP API 的效率,同时保持代码的整洁和一致性。

回到顶部