golang数据绑定与验证插件库gbind的使用
golang数据绑定与验证插件库gbind的使用
gbind是一个封装通用参数解析和参数验证逻辑的Go库,可以最小化日常开发中的重复代码,用几行代码解决参数绑定和验证问题。
特性
-
基于tag信息将数据绑定到指定结构体
- 内置HTTP请求路径、查询参数、表单、header、cookie绑定能力
- 内置json绑定能力,使用encoding/json实现
- 支持设置绑定字段的默认值
- 支持自定义绑定解析逻辑
-
根据tag信息验证字段值
- 依赖github.com/go-playground/validator实现验证
- 支持自定义验证逻辑
- 支持验证失败的自定义错误消息
使用示例
HTTP API请求参数绑定与验证
package main
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"github.com/bdjimmy/gbind"
)
type Params struct {
API string `gbind:"http.path,default=/api/test"`
Appkey string `gbind:"http.query.appkey,default=appkey-default"`
Page int `gbind:"http.query.page,default=1"`
Size int `gbind:"http.query.size,default=10"`
Token string `gbind:"http.cookie.Token" validate:"required" err_msg:"please login"`
Host string `gbind:"http.header.host,default=www.baidu.com"`
Uids []int `gbind:"http.form.uids"`
}
func Controller(w http.ResponseWriter, r *http.Request) {
var requestParams = &Params{}
if _, err := gbind.BindWithValidate(context.Background(), requestParams, r); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
bs, _ := json.MarshalIndent(requestParams, "", "\t")
w.Write(bs)
}
func main() {
w := httptest.NewRecorder()
u, _ := url.Parse("http://gbind.baidu.com/api/test?appkey=abc&page=2")
r := &http.Request{
Method: http.MethodPost,
Header: map[string][]string{
"Host": {"gbind.baidu.com"},
},
PostForm: url.Values{
"uids": {"1", "2", "3"},
},
URL: u,
}
r.AddCookie(&http.Cookie{
Name: "Token",
Value: "foo-bar-andsoon",
})
Controller(w, r)
fmt.Println(w.Result().Status)
fmt.Println(w.Body.String())
}
自定义绑定逻辑
package main
import (
"bytes"
"context"
"errors"
"fmt"
"reflect"
"testing"
"github.com/bdjimmy/gbind"
)
func TestRegisterBindFunc(t *testing.T) {
g := gbind.NewGbind()
g.RegisterBindFunc("simple", NewSimpleExecer)
type Foo struct {
Key string `gbind:"simple.key"`
}
f := &Foo{}
_, err := g.Bind(context.WithValue(context.Background(), exprKey{}, "simple-k-d"), f, nil)
if err != nil {
t.Fatal(err)
}
fmt.Println(f.Key) // 输出: simple-k-d
}
type exprKey struct{}
func NewSimpleExecer(values [][]byte) (gbind.Execer, error) {
n := len(values)
if n != 2 {
return nil, errors.New("syntax error: simple error")
}
switch {
case bytes.Equal(values[1], []byte("key")):
return &simpleKeyExecer{}, nil
}
return nil, fmt.Errorf("syntax error: not support simple %s", values[1])
}
type simpleKeyExecer struct{}
func (s *simpleKeyExecer) Exec(ctx context.Context, value reflect.Value, data interface{}, opt *gbind.DefaultOption) (context.Context, error) {
err := gbind.TrySet(value, []string{ctx.Value(exprKey{}).(string)}, opt)
return ctx, err
}
func (s *simpleKeyExecer) Name() string {
return "simple.key"
}
自定义验证逻辑
package main
import (
"testing"
"github.com/bdjimmy/gbind"
"github.com/go-playground/validator/v10"
)
func TestRegisterCustomValidation(t *testing.T) {
g := gbind.NewGbind()
g.RegisterCustomValidation("is-awesome", func(fl validator.FieldLevel) bool {
return fl.Field().String() == "awesome"
})
type Foo struct {
Appkey string `gbind:"http.query.appkey" validate:"is-awesome"`
}
f := &Foo{}
req := NewReq().AddQueryParam("appkey", "awesome").R()
_, err := g.BindWithValidate(context.Background(), f, req)
if err != nil {
t.Fatal(err)
}
}
性能基准测试
- HTTP query+form参数绑定性能比较:
BenchmarkBind/gin-query-form-8 612357 1937 ns/op 304 B/op 20 allocs/op
BenchmarkBind/gbind-query-form-8 6981271 171.3 ns/op 200 B/op 5 allocs/op
- HTTP query+form+header参数绑定性能比较:
BenchmarkBind/gin-query-form-header-8 232152 5143 ns/op 736 B/op 53 allocs/op
BenchmarkBind/gbind-query-form-header-8 6673236 180.0 ns/op 232 B/op 5 allocs/op
支持的底层数据类型
-
基本数据类型:
- int、int8、int16、int32、int64
- uint、uint8、uint16、uint32、uint64
- float32、float64
- bool
- string
-
其他数据类型:
- 指针类型(包括多级指针)
- 切片类型
- 数组类型
- time.Duration
更多关于golang数据绑定与验证插件库gbind的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang数据绑定与验证插件库gbind的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang数据绑定与验证插件库gbind使用指南
gbind是一个用于Golang的数据绑定和验证的轻量级库,它可以帮助开发者将请求数据(如JSON、表单等)绑定到结构体,并进行数据验证。
安装
go get github.com/gobind/gbind
基本使用
1. 数据绑定
首先定义一个结构体用于接收数据:
type User struct {
Name string `json:"name" form:"name"`
Age int `json:"age" form:"age"`
Email string `json:"email" form:"email"`
Password string `json:"password" form:"password"`
}
在HTTP处理器中使用gbind进行数据绑定:
import "github.com/gobind/gbind"
func CreateUser(w http.ResponseWriter, r *http.Request) {
var user User
// 绑定数据
if err := gbind.Bind(r, &user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 处理用户数据...
fmt.Fprintf(w, "User created: %+v", user)
}
2. 数据验证
gbind支持使用标签进行数据验证:
type User struct {
Name string `json:"name" form:"name" validate:"required,min=3,max=50"`
Age int `json:"age" form:"age" validate:"required,min=18,max=120"`
Email string `json:"email" form:"email" validate:"required,email"`
Password string `json:"password" form:"password" validate:"required,min=8"`
}
在绑定后执行验证:
func CreateUser(w http.ResponseWriter, r *http.Request) {
var user User
// 绑定并验证数据
if err := gbind.BindAndValidate(r, &user); err != nil {
// 处理验证错误
if verr, ok := err.(gbind.ValidationErrors); ok {
for _, e := range verr {
fmt.Printf("Field %s failed validation: %s\n", e.Field, e.Message)
}
}
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// 处理用户数据...
fmt.Fprintf(w, "User created: %+v", user)
}
支持的验证规则
gbind支持以下常用验证规则:
required
- 字段必须存在且不为零值min=n
- 最小长度/数值max=n
- 最大长度/数值email
- 必须是有效的电子邮件格式eqfield=OtherField
- 必须等于另一个字段的值oneof=a b c
- 值必须是给定列表中的一个len=n
- 长度必须等于nnumeric
- 必须是数字alpha
- 只能包含字母字符alphanum
- 只能包含字母和数字字符
自定义验证器
你可以注册自定义验证器:
// 自定义验证函数
func isAdmin(field gbind.FieldLevel) bool {
value := field.Field().String()
return value == "admin"
}
func init() {
// 注册自定义验证器
gbind.RegisterValidation("isadmin", isAdmin)
}
// 在结构体中使用
type User struct {
Username string `json:"username" validate:"isadmin"`
// ...
}
处理不同内容类型
gbind自动根据Content-Type处理不同格式的数据:
application/json
- 解析JSON数据application/x-www-form-urlencoded
- 解析表单数据multipart/form-data
- 解析多部分表单数据(包括文件上传)
高级用法
1. 仅绑定特定内容
// 只绑定JSON数据
if err := gbind.BindJSON(r, &user); err != nil {
// 处理错误
}
// 只绑定表单数据
if err := gbind.BindForm(r, &user); err != nil {
// 处理错误
}
2. 自定义错误消息
type User struct {
Name string `json:"name" validate:"required" message:"Name is required"`
Age int `json:"age" validate:"required,min=18" message:"Age must be at least 18"`
}
3. 嵌套结构体验证
type Address struct {
Street string `json:"street" validate:"required"`
City string `json:"city" validate:"required"`
}
type User struct {
Name string `json:"name" validate:"required"`
Address Address `json:"address"`
}
性能考虑
gbind在设计时考虑了性能因素:
- 使用反射但缓存了反射结果
- 验证规则在第一次使用时编译并缓存
- 尽量减少内存分配
与其他库的比较
相比于其他验证库如go-playground/validator,gbind提供了:
- 更简洁的API
- 内置数据绑定功能
- 更友好的错误消息处理
- 更轻量的实现
总结
gbind是一个简单而强大的Golang数据绑定和验证库,它可以帮助开发者:
- 轻松地将请求数据绑定到结构体
- 使用声明式标签验证数据
- 自定义验证规则和错误消息
- 处理多种内容类型的数据
通过合理使用gbind,可以显著减少数据绑定和验证的样板代码,提高开发效率。
更多详细用法请参考官方文档:https://github.com/gobind/gbind