如何将所有GET请求查询参数放入Go中的结构中?
How to get all GET request query parameters into a structure in Go?
嗨,我想将 get 查询参数转换为 Go 中的结构,例如我有这样的结构:
type Filter struct {
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
SortBy string `json:"sortby"`
Asc bool `json:"asc"`
//User specific filters
Username string `json:"username"`
First_Name string `json:"first_name"`
Last_Name string `json:"last_name"`
Status string `json:"status"`
}
并且我有用户在发送 get 请求时可以指定的可选参数,它们是 Offset
、Limit
、SortBy
、Asc
、Username
, First_Name
, Last_Name
, Status
.
如果这些参数在正文中发送,那么我会这样做:
b, err := ioutil.ReadAll(r.Body)
if err != nil {
log.WithFields(logFields).Errorf("Reading Body Message:failed:%v", err)
return
}
var filter Filter
err = json.Unmarshal(b, &filter)
但我无法在 GET
请求中发送正文,那么解决方案是什么,而不是单独获取每个参数,然后将它们放入结构中?
使用大猩猩的schema
包
github.com/gorilla/schema
包就是为此发明的。
您可以使用 struct tags 告诉如何将 URL 参数映射到结构字段,schema
包查找 "schema"
标签键。
使用它:
import "github.com/gorilla/schema"
type Filter struct {
Offset int64 `schema:"offset"`
Limit int64 `schema:"limit"`
SortBy string `schema:"sortby"`
Asc bool `schema:"asc"`
//User specific filters
Username string `schema:"username"`
First_Name string `schema:"first_name"`
Last_Name string `schema:"last_name"`
Status string `schema:"status"`
}
func MyHandler(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
// Handle error
}
filter := new(Filter)
if err := schema.NewDecoder().Decode(filter, r.Form); err != nil {
// Handle error
}
// Do something with filter
fmt.Printf("%+v", filter)
}
使用 json
编组和解组
请注意,schema
包也会尝试将参数值转换为字段类型。
如果结构只包含 []string
类型的字段(或者您愿意做出这种妥协),您可以在没有 schema
包的情况下做到这一点。
Request.Form
是一个 map
,从 string
映射到 []string
(因为一个参数可能在 URL 中多次列出:
Form url.Values
type Values map[string][]string
例如,如果您的 Filter
结构如下所示:
type Filter struct {
Offset []string `json:"offset"`
Limit []string `json:"limit"`
SortBy []string `json:"sortby"`
// ..other fields
}
您可以简单地使用 json
包编组 r.Form
,然后将其解组到您的结构中:
func MyHandler(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
// Handle error
}
data, err := json.Marshal(r.Form)
if err != nil {
// Handle error
}
filter := new(Fiter)
if err = json.Unmarshal(data, filter); err != nil {
// Handle error
}
fmt.Printf("%+v", filter)
}
如果为同一参数名称提供了多个值,此解决方案会处理。如果您不关心多个值而只想要一个,则首先必须 "transform" r.Form
到具有单个 string
值而不是 [=22= 的 map
].
它可能是这样的:
type Filter struct {
Offset string `json:"offset"`
Limit string `json:"limit"`
SortBy string `json:"sortby"`
// ..other fields
}
// Transformation from map[string][]string to map[string]string:
m := map[string]string{}
for k, v := range r.Form {
m[k] = v[0]
}
然后您可以将 m
编组并以相同的方式将其解组到 Filter
结构中。
对于 Echo
框架,您可以将查询字符串绑定到类似此示例代码的结构。
type Filter struct {
Offset int64 `query:"offset"`
Limit int64 `query:"limit"`
SortBy string `query:"sortby"`
Asc bool `query:"asc"`
//User specific filters
Username string `query:"username"`
First_Name string `query:"first_name"`
Last_Name string `query:"last_name"`
Status string `query:"status"`
}
query := new(Filter)
if err := c.Bind(query); err != nil {
// handle error here
}
使用ggicci/httpin
免责声明:我是这个包的创建者和维护者。
httpin帮你轻松解码来自
的HTTP请求数据
- 查询参数,例如
?name=john&is_member=true
- Headers,例如
Authorization: xxx
- 表单数据,例如
username=john&password=******
- JSON/XML Body,例如
POST {"name":"john"}
- 路径变量,例如
/users/{username}
- 文件上传
如何使用?
type ListUsersInput struct {
Page int `in:"query=page"`
PerPage int `in:"query=per_page"`
IsMember bool `in:"query=is_member"`
}
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListUsersInput)
if input.IsMember {
// Do sth.
}
// Do sth.
}
httpin 是:
- 有据可查:在https://ggicci.github.io/httpin/
- 测试良好:覆盖率超过98%
- 开集成:与net/http, go-chi/chi, gorilla/mux, gin-gonic/gin等
- 可扩展(高级功能):通过添加自定义指令。阅读 httpin - custom directives 了解更多详情。
- 提到很棒:https://github.com/avelino/awesome-go#forms
嗨,我想将 get 查询参数转换为 Go 中的结构,例如我有这样的结构:
type Filter struct {
Offset int64 `json:"offset"`
Limit int64 `json:"limit"`
SortBy string `json:"sortby"`
Asc bool `json:"asc"`
//User specific filters
Username string `json:"username"`
First_Name string `json:"first_name"`
Last_Name string `json:"last_name"`
Status string `json:"status"`
}
并且我有用户在发送 get 请求时可以指定的可选参数,它们是 Offset
、Limit
、SortBy
、Asc
、Username
, First_Name
, Last_Name
, Status
.
如果这些参数在正文中发送,那么我会这样做:
b, err := ioutil.ReadAll(r.Body)
if err != nil {
log.WithFields(logFields).Errorf("Reading Body Message:failed:%v", err)
return
}
var filter Filter
err = json.Unmarshal(b, &filter)
但我无法在 GET
请求中发送正文,那么解决方案是什么,而不是单独获取每个参数,然后将它们放入结构中?
使用大猩猩的schema
包
github.com/gorilla/schema
包就是为此发明的。
您可以使用 struct tags 告诉如何将 URL 参数映射到结构字段,schema
包查找 "schema"
标签键。
使用它:
import "github.com/gorilla/schema"
type Filter struct {
Offset int64 `schema:"offset"`
Limit int64 `schema:"limit"`
SortBy string `schema:"sortby"`
Asc bool `schema:"asc"`
//User specific filters
Username string `schema:"username"`
First_Name string `schema:"first_name"`
Last_Name string `schema:"last_name"`
Status string `schema:"status"`
}
func MyHandler(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
// Handle error
}
filter := new(Filter)
if err := schema.NewDecoder().Decode(filter, r.Form); err != nil {
// Handle error
}
// Do something with filter
fmt.Printf("%+v", filter)
}
使用 json
编组和解组
请注意,schema
包也会尝试将参数值转换为字段类型。
如果结构只包含 []string
类型的字段(或者您愿意做出这种妥协),您可以在没有 schema
包的情况下做到这一点。
Request.Form
是一个 map
,从 string
映射到 []string
(因为一个参数可能在 URL 中多次列出:
Form url.Values
type Values map[string][]string
例如,如果您的 Filter
结构如下所示:
type Filter struct {
Offset []string `json:"offset"`
Limit []string `json:"limit"`
SortBy []string `json:"sortby"`
// ..other fields
}
您可以简单地使用 json
包编组 r.Form
,然后将其解组到您的结构中:
func MyHandler(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
// Handle error
}
data, err := json.Marshal(r.Form)
if err != nil {
// Handle error
}
filter := new(Fiter)
if err = json.Unmarshal(data, filter); err != nil {
// Handle error
}
fmt.Printf("%+v", filter)
}
如果为同一参数名称提供了多个值,此解决方案会处理。如果您不关心多个值而只想要一个,则首先必须 "transform" r.Form
到具有单个 string
值而不是 [=22= 的 map
].
它可能是这样的:
type Filter struct {
Offset string `json:"offset"`
Limit string `json:"limit"`
SortBy string `json:"sortby"`
// ..other fields
}
// Transformation from map[string][]string to map[string]string:
m := map[string]string{}
for k, v := range r.Form {
m[k] = v[0]
}
然后您可以将 m
编组并以相同的方式将其解组到 Filter
结构中。
对于 Echo
框架,您可以将查询字符串绑定到类似此示例代码的结构。
type Filter struct {
Offset int64 `query:"offset"`
Limit int64 `query:"limit"`
SortBy string `query:"sortby"`
Asc bool `query:"asc"`
//User specific filters
Username string `query:"username"`
First_Name string `query:"first_name"`
Last_Name string `query:"last_name"`
Status string `query:"status"`
}
query := new(Filter)
if err := c.Bind(query); err != nil {
// handle error here
}
使用ggicci/httpin
免责声明:我是这个包的创建者和维护者。
httpin帮你轻松解码来自
的HTTP请求数据- 查询参数,例如
?name=john&is_member=true
- Headers,例如
Authorization: xxx
- 表单数据,例如
username=john&password=******
- JSON/XML Body,例如
POST {"name":"john"}
- 路径变量,例如
/users/{username}
- 文件上传
如何使用?
type ListUsersInput struct {
Page int `in:"query=page"`
PerPage int `in:"query=per_page"`
IsMember bool `in:"query=is_member"`
}
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListUsersInput)
if input.IsMember {
// Do sth.
}
// Do sth.
}
httpin 是:
- 有据可查:在https://ggicci.github.io/httpin/
- 测试良好:覆盖率超过98%
- 开集成:与net/http, go-chi/chi, gorilla/mux, gin-gonic/gin等
- 可扩展(高级功能):通过添加自定义指令。阅读 httpin - custom directives 了解更多详情。
- 提到很棒:https://github.com/avelino/awesome-go#forms