Introduction
gorilla/schema
is a library for processing forms in the gorilla development kit. It provides a simple way to easily convert form data into structure objects, or convert structure objects into form data.
Quick to use
The code in this article uses Go Modules.
Create a directory and initialize:
$ mkdir gorilla/schema && cd gorilla/schema
$ go mod init github.com/darjun/go-daily-lib/gorilla/schema
Install the gorilla/schema
library:
$ go get -u github.com/gorilla/schema
Let's take the previous login example:
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))
}
First call the schema.NewDecoder()
method to create a decoder decoder
. In the processor, first call r.ParseForm()
parse the form data, then create a user object u
, call decoder.Decode(&u, r.PostForm)
to fill the object with the form data.
schema
uses reflection to correspond to forms and structure fields. We can specify the correspondence between form data and fields through structure tags.
Above we use the decoder as a global variable in a package, because decoder
will cache some structure metadata, and it is that is concurrently safe.
In the main
function, we created the gorilla/mux
route, registered the /
root processing function, and used the middleware handlers.MethodHandler
to register the /login
of the GET and POST methods of the path 06101ef895f5a3 respectively. Then call http.Handle("/", r)
forward all requests to gorilla/mux
routing processing. Finally, start the Web server to accept the request.
coding
In addition to the server to decode the form data, schema
can also be used on the client side to encode structure objects into the form data and send it to the server. We write a program to log in to the server above:
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()
}
Similar to the usage of the decoder, first call schema.NewEncoder()
create an encoder encoder
, create a User
type object u
and form data object form
, call encoder.Encode(u, form)
to u
into form
. Then http.Client
the PostForm
method of transmitting a request. Read the response.
Custom type conversion
Currently schema
supports the following types:
- Boolean type:
bool
- Floating point number:
float32/float64
- Signed integer:
int/int8/int32/int64
- Unsigned integer:
uint/uint8/uint32/uint64
- String:
string
- Structure: a structure composed of the above types
- Pointer: Pointer to the above type
- Slice: The element is a slice of the above type, or a pointer to a slice
Sometimes the client will combine a slice into a string and send it to the server, and the server needs to parse it into slices after receiving it:
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)
}
Call decoder.RegisterConverter()
register the conversion function of the corresponding type. The conversion function type is:
func(s string) reflect.Value
That is, the string value in the request is converted to a value that meets our format.
Client request:
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()
}
The client deliberately sets the Hobbies
field to a string and sends the request. The server uses the register func (s string) reflect.Value
function to cut the string []string
return.
Summarize
schema
provides a simple way to get form data. By filling the data into the structure object, we can easily perform subsequent operations. schema
library is relatively small, so you can try it if you don’t have much requirements for features~
If you find a fun and useful Go language library, welcome to submit an issue on the Go Daily Library GitHub😄
refer to
- gorilla/schema GitHub:github.com/gorilla/schema
- Go daily library GitHub: https://github.com/darjun/go-daily-lib
I
My blog: https://darjun.github.io
Welcome to follow my WeChat public account [GoUpUp], learn together and make progress together~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。