In this chapter, we'll improve upon our previous example by introducing structured data handling to eliminate hardcoded parameter names.
Request Structure
Let's define a structure to handle client parameters:
type HelloReq struct {
Name string // User's name
Age int // User's age
}
This approach allows us to document our parameters and specify their types explicitly, eliminating the need for hardcoded parameter names.
Implementation
Here's our updated web server implementation:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
type HelloReq struct {
Name string // User's name
Age int // User's age
}
func main() {
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request) {
var req HelloReq
if err := r.Parse(&req); err != nil {
r.Response.Write(err.Error())
return
}
if req.Name == "" {
r.Response.Write("name should not be empty")
return
}
if req.Age <= 0 {
r.Response.Write("invalid age value")
return
}
r.Response.Writef(
"Hello %s! Your Age is %d",
req.Name,
req.Age,
)
})
s.SetPort(8000)
s.Run()
}
Key improvements in this version:
- We use
r.Parse
to automatically map request parameters to our struct. This method handles the parameter parsing and assignment based on predefined mapping rules (which we'll cover in detail in the type conversion documentation). - We've added input validation to ensure both
Name
andAge
parameters contain valid values.
Testing the API
When we visit http://127.0.0.1:8000/?name=john&age=18, we get the expected response:
Let's test the validation by making a request without parameters to http://127.0.0.1:8000/:
Room for Improvement
While we've made progress by using structured data, there are still several areas we can enhance:
- The
r.Parse
operation is boilerplate code that should be separated from our business logic - Having to call
r.Parse
in every API handler becomes repetitive - The manual validation using multiple
if
statements can become unwieldy as the number of parameters grows
Can we make this code more elegant and maintainable? Absolutely! In the next chapter, we'll explore a more streamlined approach to handle these concerns.