How does the gin framework in Go language extract routing and implement inheritance for controllers (6)

In web frameworks like Gin, routing is one of the core parts of organizing an application. As your application grows larger, placing all your routes in the main file makes the code difficult to maintain and extend. Therefore, extracting routing and making the code more modular and organized has the following benefits:

Improve code maintainability: Extracting routes separately can reduce the complexity of the main file and reduce the coupling of the code. This makes the code easier to maintain and modify, and easier to unit test.

Improve code scalability: With routing out of the way, new routing and processing functions can be added more easily without modifying the main file. This way, when the application becomes larger, it can be expanded and maintained more easily.

Improve code readability: Separating routes from the main file makes it easier to understand the structure and logic of your application. This makes the code easier to read and understand, making it easier to collaborate and maintain.

Code reuse: Extracting routes allows different modules and packages to share the same routes. In this way, redundant code can be reduced and code reusability improved.

Therefore, extracting routing is a good programming practice that can improve the maintainability, scalability, readability, and reusability of the code.

So how can routers be extracted from the Gin framework to better organize and manage applications.

The specific extraction methods are as follows:

Create a package called "routers".

In this package, create a file called "router.go" that defines the routes.

In this file, import the "github.com/gin-gonic/gin" library.

Define a function named "SetupRouter" for setting up routing.

In the "SetupRouter" function, create a Gin engine named "router".

Define routing and processing functions, for example:

func SetupRouter() *gin.Engine {
    router := gin.Default()
    router.GET("/hello", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Hello World!",
        })
    })
    return router
}


In the main function, call the "SetupRouter" function and start the returned Gin engine:

func main() {
    r := SetupRouter()
    r.Run(":8080")
}


Finally, in the other files, import the "routers" package and use the "SetupRouter" function to set up the routes.

In this way, routing and processing functions can be extracted from the main file to better organize and manage the application.

In addition, as a supplement, you can also extract routing like this:

In the main.go file, group the previous route jump post and get requests in one step, and store them in separate folders, similar to this:

	r.GET("/admin/index", func(ctx *gin.Context) {
		new := &Article{
			Title:   "admin/index",
			Content: "这是一个首页后台管理",
		}
		ctx.HTML(http.StatusOK, "admin/index.html", gin.H{
			"title": "后台首页",
			"news":  new,
		})
	})

	r.GET("/admin/edit", func(ctx *gin.Context) {
		new := &Article{
			Title:   "admin/index",
			Content: "这是一个首页后台管理",
		}
		ctx.HTML(http.StatusOK, "admin/index.html", gin.H{
			"title": "后台首页",
			"news":  new,
		})
	})

// 这里对这两个路由请求 get请求进行分组 
    loginRouters := r.Group("/login")
	{
		loginRouters.GET("/", func(ctx *gin.Context) {
			ctx.HTML(http.StatusOK, "default/login.html", gin.H{
				"title": "login",
			})
		})
		loginRouters.GET("/edit", func(c *gin.Context) {
			c.HTML(http.StatusOK, "default/login.html", gin.H{
				"title": "login/edit",
			})
		})

	}

Let me add here, what is the concept router.Group() method?

In the Gin framework, you  router.Group() can create a routing group to manage a group of related routes. Detaching a routing group has the following benefits:

  1. Code reusability: Grouping and managing routes with the same path prefix can avoid repeatedly defining the same prefix and improve code reusability.

  2. Code readability: By managing routing in groups, the code can be made more readable and easier to understand and maintain.

  3. Scalability: When you need to add a new route, you only need to add it in the corresponding routing group without modifying the code in the main file, which improves the scalability of the code.

  4. Middleware management: Routing groups can use middleware to group and manage common middleware for a group of routes to facilitate management and maintenance.

  5. Configurability: Through routing groups, different routes can be configured separately, such as setting routing group-level middleware, routing group-level error handling functions, etc.

Therefore, abstraction  router.Group() can improve the reusability, readability, scalability, configurability and middleware management capabilities of the code, making the code more modular and organized.

At the same time, after we use  router.Group()来abstract routing here, we are preparing for the convenience of the controller [controller] method later;

After the extraction is successful, the status routing should be that there is a routers directory in the root directory, and there is a single routing file grouped by multiple routes below; a file similar to loginRouters.go. So, what do the internal advantages of these files look like? Next is the code part:

 

package routers

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func LoginRoutersinit(r *gin.Engine) {
	loginRouters := r.Group("/login")
	{
		loginRouters.GET("/", func(ctx *gin.Context) {
			ctx.HTML(http.StatusOK, "default/login.html", gin.H{
				"title": "login",
			})
		})
		loginRouters.GET("/edit", func(c *gin.Context) {
			c.HTML(http.StatusOK, "default/login.html", gin.H{
				"title": "login/edit",
			})
		})

	}
}

The above is that after routing is grouped, each manages its own route grouping and separates it into separate files.

The last step is today's final task, the detachment of the controller. First of all, why do we have a controller, and what is it? Why do we need to write a controller? Questions like this, go and read...

In the Gin framework, it is a common programming practice to separate the controller (Controller) from the routing processing function. Here are a few benefits of detaching the controller:

  1. Separate business logic and routing: Separating route processing functions from business logic can make the code more modular and organized. This way, the code can be better managed and maintained, and made easier to understand and extend.

  2. Improve code reusability: Separating the controller from the routing processing function can make the controller code more versatile and reusable. In this way, you can avoid writing the same code repeatedly in different routing processing functions and improve code reusability.

  3. Improve code readability: Separating the controller from the route processing function can make the code clearer, easier to understand and maintain. In this way, the "single responsibility principle" can be better followed and the code can be made more modular and organized.

  4. Ease of testing: Separating the controller from the route processing function can make the controller easier to test. In this way, the controller and routing processing functions can be tested separately, improving the testability of the code.

Therefore, it is a good programming practice to separate the controller from the route handler function, which can improve the modularity, organization, reusability, readability and testability of the code.

The code demonstration part is the same as the code evolution above:

package routers

import (
	"github.com/gin-gonic/gin"

	"****/controllers/login"  
)

func LoginRoutersinit(r *gin.Engine) {
	loginRouters := r.Group("/login")
	{
		loginRouters.GET("/", login.LoginControllers{}.Index)
		loginRouters.GET("/edit", login.LoginControllers{}.Edit)

	}
}

// 这里就对路由中函数处理,进行了抽离 放到了对应的控制器包内"****/controllers/login" 这个包就是控制器部分。

    The code demonstration part inside the corresponding controller's login package package login:

package login

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

type LoginControllers struct {
}

func (con LoginControllers) Index(ctx *gin.Context) {

	ctx.HTML(http.StatusOK, "default/login.html", gin.H{
		"title": "login-controller",
	})

}
func (con LoginControllers) Edit(ctx *gin.Context) {
	ctx.HTML(http.StatusOK, "default/login.html", gin.H{
		"title": "login/edit-controller",
	})
}

The above is the specific code for the controller loginControllers.go file, and we can see how it evolved from the routing grouping stage to a controller for more detailed classification processing, and the function processing method in the routing was abstracted.

At the same time, this is also missing a part. As for functions that can be inherited, can the corresponding controller file be used universally in the same package? The answer is...

Describe the situation with specific code

logincontrollers.go file

package login

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

// 控制器继承, 和结构体 一样。 

type LoginControllers struct {
	BaseControllers
}

func (con LoginControllers) Index(ctx *gin.Context) {

	con.success(ctx)

}

basecontrollers.go file 

package login

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

type BaseControllers struct {
}

// 控制器继承, 和结构体 一样。
func (con BaseControllers) success(ctx *gin.Context) {
	ctx.HTML(http.StatusOK, "default/login.html", gin.H{
		"title": "login-controller--成功",
	})
}

Is there something different here or is it the same problem?

Careful people can see that the package name of the controller inherited from the basecontroller.go file is the same as the package name of the loginconttrollers.go file.

This is done for inheritance. If it is not a package, how can it be inherited? This issue requires further study.

Of course, if it is difficult to understand here, you can go back and look at the basics of structure inheritance for the same reason.

 

Guess you like

Origin blog.csdn.net/A_LWIEUI_Learn/article/details/131298074
Recommended