use*_*204 6 struct http go query-parameters
嗨我想将查询参数转换为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"`
}
Run Code Online (Sandbox Code Playgroud)
我有一个发送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)
Run Code Online (Sandbox Code Playgroud)
但是我无法在GET
请求中发送正文,那么解决方案是什么,而不是单独获取每个参数然后将它们放入结构中?
schema
包该github.com/gorilla/schema
包装是为此而发明的.
您可以使用struct标签来告诉如何将URL参数映射到struct字段,该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)
}
Run Code Online (Sandbox Code Playgroud)
json
请注意,该schema
包还将尝试将参数值转换为字段的类型.
如果结构只包含[]string
类型的字段(或者你愿意做出妥协),那么你可以在没有schema
包的情况下做到这一点.
Request.Form
是一个map
映射string
到[]string
(作为一个参数可能在URL中多次列出:
Form url.Values
Run Code Online (Sandbox Code Playgroud)
而且url.Values
:
type Values map[string][]string
Run Code Online (Sandbox Code Playgroud)
例如,如果你的Filter
结构看起来像这样:
type Filter struct {
Offset []string `json:"offset"`
Limit []string `json:"limit"`
SortBy []string `json:"sortby"`
// ..other fields
}
Run Code Online (Sandbox Code Playgroud)
您可以简单地使用该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)
}
Run Code Online (Sandbox Code Playgroud)
此解决方案处理是否为同一参数名称提供了多个值.如果你不关心多个值而你只想要一个,那么首先必须"转换" r.Form
为map
单个string
值而不是[]string
.
这是它的样子:
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]
}
Run Code Online (Sandbox Code Playgroud)
然后你可以用同样的方式m
编组和解组到Filter
结构中.