简介

gorilla/schema 是 gorilla 开发工具包中用于解决表单的库。它提供了一个简略的形式,能够很不便地将表单数据转为构造体对象,或者将构造体对象转为表单数据。

疾速应用

本文代码应用 Go Modules。

创立目录并初始化:

$ mkdir gorilla/schema && cd gorilla/schema$ go mod init github.com/darjun/go-daily-lib/gorilla/schema

装置gorilla/schema库:

$ go get -u github.com/gorilla/schema

咱们还是拿后面登录的例子:

func index(w http.ResponseWriter, r *http.Request) {  fmt.Fprintln(w, "Hello World")}func login(w http.ResponseWriter, r *http.Request) {  fmt.Fprintln(w, `<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Login</title></head><body><form action="/login" method="post">  <label>Username:</label>  <input name="username"><br>  <label>Password:</label>  <input name="password" type="password"><br>  <button type="submit">登录</button></form></body></html>`)}type User struct {  Username string `schema:"username"`  Password string `schema:"password"`}var (  decoder = schema.NewDecoder())func dologin(w http.ResponseWriter, r *http.Request) {  r.ParseForm()  u := User{}  decoder.Decode(&u, r.PostForm)  if u.Username == "dj" && u.Password == "handsome" {    http.Redirect(w, r, "/", 301)    return  }  http.Redirect(w, r, "/login", 301)}func main() {  r := mux.NewRouter()  r.HandleFunc("/", index)  r.Handle("/login", handlers.MethodHandler{    "GET":  http.HandlerFunc(login),    "POST": http.HandlerFunc(dologin),  })  log.Fatal(http.ListenAndServe(":8080", r))}

首先调用schema.NewDecoder()办法创立一个解码器decoder。在处理器中,先调用r.ParseForm()解析表单数据,而后创立用户对象u,调用decoder.Decode(&u, r.PostForm)通过表单数据填充该对象。

schema应用反射来对应表单和构造体字段,咱们能够通过构造体标签来指定表单数据和字段的对应关系。

下面咱们将解码器作为一个包内的全局变量,因为decoder中会缓存一些构造体的元数据,并且它是并发平安的

main函数中,咱们创立了gorilla/mux路由,注册/根处理函数,应用中间件handlers.MethodHandler别离注册门路/login的 GET 和 POST 办法的处理器。而后调用http.Handle("/", r)将所有申请交由gorilla/mux路由解决。最初启动 Web 服务器承受申请。

编码

除了用于服务器解码表单数据外,schema还可用于客户端,将构造体对象编码到表单数据中发送给服务器。咱们编写一个程序登录下面的服务器:

var (  encoder = schema.NewEncoder())func main() {  client := &http.Client{}  form := url.Values{}  u := &User{    Username: "dj",    Password: "handsome",  }  encoder.Encode(u, form)  res, _ := client.PostForm("http://localhost:8080/login", form)  data, _ := ioutil.ReadAll(res.Body)  fmt.Println(string(data))  res.Body.Close()}

与解码器的用法相似,首先调用schema.NewEncoder()创立一个编码器encoder,创立一个User类型的对象u和表单数据对象form,调用encoder.Encode(u, form)u编码到form中。而后应用http.ClientPostForm办法发送申请。读取响应。

自定义类型转换

目前schema反对以下类型:

  • 布尔类型:bool
  • 浮点数:float32/float64
  • 有符号整数:int/int8/int32/int64
  • 无符号整数:uint/uint8/uint32/uint64
  • 字符串:string
  • 构造体:由以上类型组成的构造体
  • 指针:指向以上类型的指针
  • 切片:元素为以上类型的切片,或指向切片的指针

有时候客户端会将一个切片拼成一个字符串传到服务器,服务器收到之后须要解析成切片:

type Person struct {  Name    string   `schema:"name"`  Age     int      `schema:"age"`  Hobbies []string `schema:"hobbies"`}var (  decoder = schema.NewDecoder())func init() {  decoder.RegisterConverter([]string{}, func(s string) reflect.Value {    return reflect.ValueOf(strings.Split(s, ","))  })}func doinfo(w http.ResponseWriter, r *http.Request) {  r.ParseForm()  p := Person{}  decoder.Decode(&p, r.PostForm)  fmt.Println(p)  fmt.Fprintf(w, "Name:%s Age:%d Hobbies:%v", p.Name, p.Age, p.Hobbies)}

调用decoder.RegisterConverter()注册对应类型的转换函数,转换函数类型为:

func(s string) reflect.Value

行将申请中的字符串值转为满足咱们格局的值。

客户端申请:

type Person struct {  Name    string `schema:"name"`  Age     int    `schema:"age"`  Hobbies string `schema:"hobbies"`}var (  encoder = schema.NewEncoder())func main() {  client := &http.Client{}  form := url.Values{}  p := &Person{    Name:    "dj",    Age:     18,    Hobbies: "Game,Programming",  }  encoder.Encode(p, form)  res, _ := client.PostForm("http://localhost:8080/info", form)  data, _ := ioutil.ReadAll(res.Body)  fmt.Println(string(data))  res.Body.Close()}

客户端成心将Hobbies字段设置为字符串,发送申请。服务器将应用注册的func (s string) reflect.Value函数将该字符串切割为[]string返回。

总结

schema提供了一个简略的获取表单数据的形式,通过将数据填充到构造体对象中,咱们能够很不便的进行后续操作。schema库比拟玲珑,对个性没太多要求的能够试试~

大家如果发现好玩、好用的 Go 语言库,欢送到 Go 每日一库 GitHub 上提交 issue

参考

  1. gorilla/schema GitHub:github.com/gorilla/schema
  2. Go 每日一库 GitHub:https://github.com/darjun/go-daily-lib

我的博客:https://darjun.github.io

欢送关注我的微信公众号【GoUpUp】,独特学习,一起提高~