This is the 13th day of my participation in the August More text Challenge. For details, see: August More Text Challenge
Gin is a standard Web services framework that follows the Restful API specification and its routing library is based on Httproute implementation.
This section describes how to use Gin in various routing scenarios, starting with Gin routing.
The basic routing
Gin supports GET, POST, PUT, PATCH, DELETE, and OPTIONS request types.
Example:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main(a) {
route := gin.Default()
// Set a GET request with a URL of /hello and implement a simple response
route.GET("/get".func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "this is a get method response!",})})// Implementations can define a separate function
route.POST("/post", postHandler)
route.PUT("/put".func(c *gin.Context) {
})
route.PATCH("/patch".func(c *gin.Context) {
})
route.DELETE("/delete".func(c *gin.Context){})/ /...
route.Run()
}
func postHandler(c *gin.Context) {
c.JSON(http.StatusOK, "this is a post method response!")}Copy the code
Processing parameters
The path parameter
The Param function of *gin.Context is used to obtain the parameters in the Path of the request. The parameters in the Path start with:, such as: /user/:name, which matches the Path /user/xx.
Example:
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
func main(a) {
route := gin.Default()
users := []User{
{
Username: "xcbeyond",
Sex: "Male",
Age: 18,
Labels: []string{"Young"."Handsome"}},}// There are parameters in the request path
route.GET("/user/:name".func(c *gin.Context) {
// Get the parameters in the request path
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, fmt.Errorf("not found user [%s]", name))
})
route.Run()
}
Copy the code
Query parameters
You can take arguments from the Query function of *gin.Context, such as: /user? Name = xcbeyond.
Example:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
func main(a) {
route := gin.Default()
users := []User{
{
Username: "xcbeyond",
Sex: "Male",
Age: 18,
Labels: []string{"Young"."Handsome"}},}// Query parameters, such as: /user? name=xcbeyond
route.GET("/user".func(c *gin.Context) {
// Get the parameters in
name := c.Query("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, "not found user "+name)
})
route.Run()
}
Copy the code
…
Routing group
Gin provides the capability of grouping routes to facilitate group management. It classifies routes that have the same URL prefix. These routes are grouped in different versions, for example, / API /v1 and/API /v1.
In addition, multi-level grouping is supported.
Example:
package main
import (
"math/rand"
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
func main(a) {
route := gin.Default()
users := []User{
{
Username: "xcbeyond",
Sex: "Male",
Age: 18,
Labels: []string{"Young"."Handsome"},
},
{
Username: "niki",
Sex: "Female",
Age: 16,
Labels: []string{"Beautiful"}},}/ / API group
api := route.Group("/api")
{
/ / v1 grouping
v1 := api.Group("/v1")
{
v1.GET("/user/:name".func(c *gin.Context) {
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, "not found user :"+name)
})
}
/ / v2 grouping
v2 := api.Group("/v2")
{
v2.GET("/user/:name".func(c *gin.Context) {
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return}}// If none is found, return one randomly
user := users[rand.Intn(len(users)- 1)]
c.JSON(http.StatusOK, "not found user ["+name+"],but user ["+user.Username+"] is exist!")
})
}
}
route.Run()
}
Copy the code
Routing split
In the routing examples above, all routing information is written in the same source file, function, but in a real project involving a large number of interfaces, it is not appropriate to write together.
In a real project, we would prefer to split the routing code into separate packages, multiple routing source files, and so on.
According to the size of the actual project, it can be divided into different granularity.
(The following route split is for reference only and can be flexibly adjusted according to specific projects!)
Routes are split into individual source files or packets
Separating the routing implementation into a separate package makes the project structure clearer. The project structure is as follows:
.├ ─ main.go ├── routes.goCopy the code
Example complete source code: route-split-v1
Implement and register routing information in the /routes/routes.go file:
package routes
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
Username string `json:"username"`
Sex string `json:"sex"`
Age int `json:"age"`
Labels []string `json:"lalels"`
}
var users []User
// For testing purposes, the value is assigned directly in init mode. In actual projects, data is usually obtained through other methods such as database query.
func init(a) {
users = []User{
{
Username: "xcbeyond",
Sex: "Male",
Age: 18,
Labels: []string{"Young"."Handsome"},
},
{
Username: "niki",
Sex: "Female",
Age: 16,
Labels: []string{"Beautiful"}},}}// SetupRouter Configures routes
func SetupRouter(a) *gin.Engine {
route := gin.Default()
route.GET("/user/:name", querUserHandler)
// More routes
return route
}
// handler
func querUserHandler(c *gin.Context) {
name := c.Param("name")
for _, user := range users {
if user.Username == name {
c.JSON(http.StatusOK, user)
return
}
}
c.JSON(http.StatusOK, "not found user :"+name)
}
Copy the code
Call SetupRouter in main.go:
func main(a) {
route := routes.SetupRouter()
iferr := route.Run(); err ! =nil {
fmt.Printf("startup server failed,err: %v", err)
}
}
Copy the code
The route is split into multiple source files
As the service functions of the project become rich and the volume becomes larger, all routes are written in a routes.go source file, resulting in more and more bloated source file, which is not easy to maintain and read in the later period.
Therefore, it can be split into multiple routing files according to a certain dimension to achieve different business functions. The project structure is as follows:
. ├ ─ ─ main. Go └ ─ ─ routes ├ ─ ─ auth. Go ├ ─ ─ routes. Go └ ─ ─ user. GoCopy the code
Example complete source code: route-split-V2
The Routes package is divided into multiple routing implementation files based on certain dimensions. For example, the routes can be divided into authentication module (auth.go) and user module (user.go) based on service modules. The routes file implements specific service functions and implements route registration.
For example, authentication module auth.go:
package routes
import (
"github.com/gin-gonic/gin"
)
// AuthRegister route register
func AuthRegister(e *gin.Engine) {
e.GET("/auth/login", loginHandler)
e.POST("/auth/logout", logoutUserHanler)
/ /...
}
// loginHandler
func loginHandler(c *gin.Context){}// logoutUserHanler
func logoutUserHanler(c *gin.Context){}Copy the code
The AuthRegister function is defined to register all routes under the module. Note that this function starts with an uppercase letter and can be called as a global function outside the package main.go.
In routes/routes. Go, configure routes and register routes for all modules.
package routes
import (
"github.com/gin-gonic/gin"
)
// SetupRouter Configures routes
func SetupRouter(a) *gin.Engine {
route := gin.Default()
// other config
// register all route.
UserRegister(route)
AuthRegister(route)
/ /...
return route
}
Copy the code
Main. go, as in the previous version, serves as an entry point for programs and so on:
func main(a) {
route := routes.SetupRouter()
iferr := route.Run(); err ! =nil {
fmt.Printf("startup server failed,err: %v", err)
}
}
Copy the code
References:
- api-examples
- Gin framework route splitting and registration