Introduction to the
Gorilla/Schema is the gorilla Development kit’s library for processing forms. It provides a simple way to easily convert form data into structured objects and from structured objects to form data.
Quick to use
The code in this article uses Go Modules.
Create directory and initialize:
$ mkdir gorilla/schema && cd gorilla/schema
$ go mod init github.com/darjun/go-daily-lib/gorilla/schema
Copy the code
To install the Gorilla/Schema library:
$ go get -u github.com/gorilla/schema
Copy the code
Let’s take the example from the previous login:
func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World")}func login(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, `
Login )}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(a) {
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))
}
Copy the code
First create a decoder by calling the schema.newdecoder () method. In the processor, r.ParseForm() is called to parse the form data, and then the user object U is created, which is populated with the form data by calling decoder.decode (&u, R.OstForm).
Schema uses reflection to map form and struct fields, and we can specify the mapping between form data and fields using the struct label.
Above we treat the decoder as a global variable within the package, because the decoder will cache some of the structure’s metadata and it is concurrency safe.
In the main function, we create gorilla/mux routing, register the/root handler, and use the middleware handlers.MethodHandler to register the handlers for the GET and POST methods of the path /login, respectively. It then calls http.handle (“/”, r) to leave all requests to Gorilla/Mux routing. Finally, start the Web server to accept the request.
coding
In addition to being used by the server to decode form data, schemas can also be used by the client to encode structural objects into the form data and send it to the server. Let’s write a program to log in to the server above:
var (
encoder = schema.NewEncoder()
)
func main(a) {
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()
}
Copy the code
Similar to the decoder usage, first call schema.newencoder () to create an encoder encoder, create an object of type User u and form data object form, call encoder.encode (u, form) to Encode U into the form. The request is then sent using the PostForm method of http.Client. Read the response.
Custom type conversion
Currently, the following types of schemas are supported:
- Boolean type:
bool
- Floating point Numbers:
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 one of the above types
- Slice: The element is a slice of the above type, or a pointer to a slice
Sometimes a client will send a string from a slice to the server, and the server will parse the string:
type Person struct {
Name string `schema:"name"`
Age int `schema:"age"`
Hobbies []string `schema:"hobbies"`
}
var (
decoder = schema.NewDecoder()
)
func init(a) {
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)
}
Copy the code
Call decoder. RegisterConverter () registration of the corresponding type conversion function, transform function of type:
func(s string) reflect.Value
Copy the code
Convert the string value in the request into a value that satisfies 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(a) {
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()
}
Copy the code
The client sends the request intentionally with the Hobbies field set to a string. The server will use the registered func (s string) reflect.value function to cut the string into a []string return.
conclusion
Schema provides an easy way to get form data, which we can easily follow up by populating the data into a structured object. Schema library is relatively small, do not have too many requirements for features can try ~
If you find a fun and useful Go library, please Go to GitHub and submit the issue😄
reference
- Gorilla/schema GitHub:github.com/gorilla/sch…
- Go daily GitHub: github.com/darjun/go-d…
I
My blog: darjun.github. IO
Welcome to follow my wechat public account [GoUpUp], learn together, make progress together ~