在 Go 中,我们可以直接使用 Go 自带的 net/http 包对 HTTP 请求参数进行解析。比如看下面一个简单的用例:
// GET /v1/users?page=1&per_page=20&is_member=true
func ListUsers(rw http.ResponseWriter, r *http.Request) {
page, err := strconv.ParseInt(r.FormValue("page"), 10, 64)
if err != nil {
// 处理参数错误: page.
return
}
perPage, err := strconv.ParseInt(r.FormValue("per_page"), 10, 64)
if err != nil {
// 处理参数错误: per_page.
return
}
isMember, err := strconv.ParseBool(r.FormValue("is_member"))
if err != nil {
// 处理参数错误: is_member.
return
}
// 读取数据库并返回给客户端
}
对于这种请求,如果 URL/Query 里面带了超过 3 个参数,那么一个一个去读取/解析,再处理错误,代码就会变得很冗余。代码库也会变得不好维护,又臭又长。不仅能搞死自己,还会搞死后面接盘的小宝贝!所以说,最好就是能把一个接口的请求参数统一存放在一个结构体中。这样不仅能减少接口代码中的局部变量,也能使代码变得易读,方便维护。
比如把上面的参数可以统一定义在一个结构体中,如下:
type ListUsersInput struct {
Page int
PerPage int
IsMember bool
}
// GET /v1/users?page=1&per_page=20&is_member=true
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := &ListUsersInput{}
input.Page = // ...
}
但是问题也就来了,虽然参数全存放在一个结构体了,参数不还是得一个一个去解析吗?这样还是得写一堆解析代码,也能把人活活累死。有没有一个库能一行代码搞定参数解析?
答案是:当然能啦!
这里推荐一个自动解析 HTTP 请求到 Go 结构体中的库:ggicci/httpin。
废话不多说,咱先看看用 httpin 怎么来实现上面的解析参数代码:
// 1. 定义一个结构体存放所有需要解析参数,并在相应字段后面用结构体标签定义参数从哪里解析
type ListUsersInput struct {
Page int `in:"form=page"`
PerPage int `in:"form=per_page"`
IsMember bool `in:"form=is_member"`
}
// 2. 把这个结构体和你的接口 handler 绑定
func init() {
http.Handle("/users", alice.New(
httpin.NewInput(ListUsersInput{}),
).ThenFunc(ListUsers))
}
// 3. 在接口 handler 里面,直接读取参数,一行解析代码都不用写,httpin 帮你解析完了
func ListUsers(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListUsersInput)
}
这样来看,是不是超级简单,干脆面。
广告植入:不要 998,不要 188,只要给个星星(不要脸求 star ),httpin 免费使用100年!
httpin 不仅能从 URL 提取参数,还能从 HTTP 请求的很多其它地方提取参数,反正有以下这些:
httpin 是个不错的库,真的良心:
好啦,谢谢大家阅读!祝大家生活愉快。