{"id":13412886,"url":"https://github.com/bdjimmy/gbind","last_synced_at":"2026-01-17T15:37:11.976Z","repository":{"id":40342000,"uuid":"494701408","full_name":"bdjimmy/gbind","owner":"bdjimmy","description":"Bind data to any Go value. Can use built-in and custom expression binding capabilities; supports data validation logic for Go values. // 将数据绑定到任何 Go 值。可使用内置和自定义表达式绑定能力；支持对Go值的数据校验逻辑.","archived":false,"fork":false,"pushed_at":"2022-06-14T09:01:28.000Z","size":77,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-07-31T20:51:37.924Z","etag":null,"topics":["bind","cache","expression","form","gbind","http","reflect","validate"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bdjimmy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-21T06:34:24.000Z","updated_at":"2022-09-26T10:29:47.000Z","dependencies_parsed_at":"2022-08-09T17:41:09.728Z","dependency_job_id":null,"html_url":"https://github.com/bdjimmy/gbind","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/bdjimmy/gbind","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdjimmy%2Fgbind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdjimmy%2Fgbind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdjimmy%2Fgbind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdjimmy%2Fgbind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bdjimmy","download_url":"https://codeload.github.com/bdjimmy/gbind/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bdjimmy%2Fgbind/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28511734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bind","cache","expression","form","gbind","http","reflect","validate"],"created_at":"2024-07-30T20:01:30.617Z","updated_at":"2026-01-17T15:37:11.904Z","avatar_url":"https://github.com/bdjimmy.png","language":"Go","readme":"English | [🇨🇳中文](README_ZH.md)\n\n[![Go Report Card](https://goreportcard.com/badge/github.com/bdjimmy/gbind)](https://goreportcard.com/report/github.com/bdjimmy/gbind)\n\u003ca title=\"Doc for ants\" target=\"_blank\" href=\"https://pkg.go.dev/github.com/bdjimmy/gbind?tab=doc\"\u003e\u003cimg src=\"https://img.shields.io/badge/go.dev-doc-007d9c?style=flat-square\u0026logo=read-the-docs\" /\u003e\u003c/a\u003e\n\u003ca title=\"Codecov\" target=\"_blank\" href=\"https://codecov.io/gh/bdjimmy/gbind\"\u003e\u003cimg src=\"https://img.shields.io/codecov/c/github/bdjimmy/gbind?style=flat-square\u0026logo=codecov\" /\u003e\u003c/a\u003e\n# gbind\n\tEncapsulate general parameter parsing and parameter verification logic, \n\tminimize repetitive code in daily development, and solve parameter binding \n\tand verification in a few lines of code\n\n\n## Features\n+ Bind data to the specified structure based on tag information\n\t- Built-in HTTP request path, query, form, header, cookie binding ability\n\t\t- Binding for http uri parameters  `gbind:\"http.path\"`\n\t\t- Binding for http query parameters `gbind:\"http.query.varname\"`\n\t\t- Binding for http header parameters  `gbind:\"http.header.varname\"`\n\t\t- Binding for http form parameters `gbind:\"http.form.varname\"`\n\t\t- Binding for http cookie parameters `gbind:\"http.cookie.varname\"`\n\t- Built-in json binding capability, implemented with encoding/json\n\t\t- For HTTP body in json format, follow golang json parsing format uniformly `json:\"varname\"`\n\t- Support for setting default values of bound fields\n\t\t- Supports setting default values of bound fields when no data is passed in `gbind:\"http.query.varname,default=123\"`\n\t- Support custom binding parsing logic (not limited to HTTP requests, using gbind can do bindings similar to database tags and other scenarios)\n\t\t- You can register custom binding logic by calling the `RegisterBindFunc` function, such as implementing a binding of the form `gbind:\"simple.key\"`\n\n- Validate the field value according to the tag information, [parameter validation logic refer to the validate package](https://pkg.go.dev/gopkg.in/go-playground/validator.v9\t)\n\t- Data validation of bound fields is performed according to the defined `validate`tag, which depends on github.com/go-playground/validator implementation, `validate=\"required,lt=100\"`\n\t- Support custom validation logic, you can customize the data validation logic by calling the `RegisterCustomValidation` function\n\t- Support custom error message for validation failure\n\t- By defining the tag of err_msg, it supports custom error message when parameter validation fails, demo `gbind:\"http.cookie.Token\" validate=\"required,lt=100\" err_msg=\"Please complete the login\"`\n## Usage example\n- Use gbind's web API request parameters for binding and verification\n\n```golang\npackage gbind\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"net/url\"\n)\n\ntype Params struct {\n\tAPI    string `gbind:\"http.path,default=/api/test\"`\n\tAppkey string `gbind:\"http.query.appkey,default=appkey-default\"`\n\tPage   int    `gbind:\"http.query.page,default=1\"`\n\tSize   int    `gbind:\"http.query.size,default=10\"`\n\tToken  string `gbind:\"http.cookie.Token\" validate:\"required\" err_msg:\"please login\"`\n\tHost   string `gbind:\"http.header.host,default=www.baidu.com\"`\n\tUids   []int  `gbind:\"http.form.uids\"`\n}\n\nfunc Controller(w http.ResponseWriter, r *http.Request) {\n\tvar requestParams = \u0026Params{}\n\tif _, err := BindWithValidate(context.Background(), requestParams, r); err != nil {\n\t\tw.WriteHeader(http.StatusBadRequest)\n\t\treturn\n\t}\n\tbs, _ := json.MarshalIndent(requestParams, \"\", \"\\t\")\n\tw.Write(bs)\n}\n\nfunc ExampleGbind() {\n\tw := httptest.NewRecorder()\n\tu, _ := url.Parse(\"http://gbind.baidu.com/api/test?appkey=abc\u0026page=2\")\n\tr := \u0026http.Request{\n\t\tMethod: http.MethodPost,\n\t\tHeader: map[string][]string{\n\t\t\t\"Host\": {\"gbind.baidu.com\"},\n\t\t},\n\t\tPostForm: url.Values{\n\t\t\t\"uids\": {\"1\", \"2\", \"3\"},\n\t\t},\n\t\tURL: u,\n\t}\n\tr.AddCookie(\u0026http.Cookie{\n\t\tName:  \"Token\",\n\t\tValue: \"foo-bar-andsoon\",\n\t})\n\n\tController(w, r)\n\n\tfmt.Println(w.Result().Status)\n\tfmt.Println(w.Body.String())\n\n\t// Output:\n\t// 200 OK\n\t//{\n\t//\t\"API\": \"/api/test\",\n\t//\t\"Appkey\": \"abc\",\n\t//\t\"Page\": 2,\n\t//\t\"Size\": 10,\n\t//\t\"Token\": \"foo-bar-andsoon\",\n\t//\t\"Host\": \"gbind.baidu.com\",\n\t//\t\"Uids\": [\n\t//\t\t1,\n\t//\t\t2,\n\t//\t\t3\n\t//\t]\n\t//}\n}\n```\n- Customize the binding logic, you can realize the binding of different scenarios, demo `gbind:\"simple.key\"`\n```golang\npackage gbind\n\nfunc TestRegisterBindFunc(t *testing.T) {\n\tg := NewGbind()\n\tg.RegisterBindFunc(\"simple\", NewSimpleExecer)\n\n\ttype Foo struct {\n\t\tKey string `gbind:\"simple.key\"`\n\t}\n\tf := \u0026Foo{}\n\t_, err := g.Bind(context.WithValue(context.Background(), exprKey{}, \"simple-k-d\"), f, nil)\n\tassert.Nil(t, err)\n\tassert.Equal(t, \"simple-k-d\", f.Key)\t\n}\n\ntype exprKey struct{}\n\nfunc NewSimpleExecer(values [][]byte) (Execer, error) {\n\tn := len(values)\n\tif n != 2 {\n\t\treturn nil, errors.New(\"syntax error: simple error\")\n\t}\n\tswitch {\n\tcase bytes.Equal(values[1], []byte(\"key\")):\n\t\treturn \u0026simpleKeyExecer{}, nil\n\t}\n\treturn nil, fmt.Errorf(\"syntax error: not support simple %s\", values[1])\n}\n\ntype simpleKeyExecer struct{}\n\n// Exec\nfunc (s *simpleKeyExecer) Exec(ctx context.Context, value reflect.Value, data interface{}, opt *DefaultOption) (context.Context, error) {\n\terr := TrySet(value, []string{ctx.Value(exprKey{}).(string)}, opt)\n\treturn ctx, err\n}\n\n// Name\nfunc (s *simpleKeyExecer) Name() string {\n\treturn \"simple.key\"\n}\n\n```\n- Custom data verification logic, can realize verification in different scenarios, demo `validate:\"is-awesome\"`\n```golang\nfunc TestRegisterCustomValidation(t *testing.T) {\n\tg := NewGbind()\n\n\tg.RegisterCustomValidation(\"is-awesome\", func(fl validator.FieldLevel) bool {\n\t\treturn fl.Field().String() == \"awesome\"\n\t})\n\n\t{\n\t\ttype Foo struct {\n\t\t\tAppkey string `gbind:\"http.query.appkey\" validate:\"is-awesome\"`\n\t\t}\n\t\tf := \u0026Foo{}\n\t\treq := NewReq().AddQueryParam(\"appkey\", \"awesome\").R()\n\t\t_, err := g.BindWithValidate(context.Background(), f, req)\n\t\tassert.Nil(t, err)\n\t}\n}\n```\n\n## benchmark\n+ Stressed the binding capabilities of the gin framework and the gbind package. The simple binding capabilities of query+form, gbind has a performance improvement of more than **10 times**, and the complex binding capabilities of query+form+header, gbind has **30 times or more** performance improvement, the specific data are as follows\n\t- HTTP query+form parameter binding, gin, gbind package comparison\n```\t\nBenchmarkBind/gin-query-form-8         \t  612357\t      1937 ns/op\t     304 B/op\t      20 allocs/op\nBenchmarkBind/gbind-query-form-8       \t 6981271\t      171.3 ns/op\t     200 B/op\t       5 allocs/op\n```\n\n\t- HTTP query+form+cookie parameter binding, gin, gbind package comparison\n```\nBenchmarkBind/gin-query-form-header-8  \t  232152\t      5143 ns/op\t     736 B/op\t      53 allocs/op\nBenchmarkBind/gbind-query-form-header-8   6673236\t      180.0 ns/op\t     232 B/op\t       5 allocs/op\t\n```\n\n## Binding supported underlying data types\n+ basic data type\n\t- int、int8、int16、int32、int64\n\t- uint、uint8、uint16、uint32、uint64\n\t- float32、float64\n\t- bool\n\t- string\n+ other data types\t\n\t- ptr\n\t\t- *int、*uint、*float32、*string\n\t\t- **int、**uint、**float32、**string\n\t\t- Multilevel pointer to any underlying data type\n\t- slice\n\t\t- []int, []uint, []bool, []string, etc.\n\t\t- []*int, []*uint, []*bool, []*string, etc.\n\t\t- a slice of any underlying data type (including pointers)\n\t- array\n\t\t- [1]int, [2]uint, [3]bool, [4]string, etc.\n\t\t- [5]*int, [6]*uint, [7]*bool, [8]*string, etc.\n\t\t- Arrays of any underlying data type (including pointers)\n\t\t- time.Duration\n\n","funding_links":[],"categories":["Forms","表单"],"sub_categories":["Search and Analytic Databases","Advanced Console UIs","检索及分析资料库"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdjimmy%2Fgbind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbdjimmy%2Fgbind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbdjimmy%2Fgbind/lists"}