Go语言中的gin框架如何抽离出路由且控制器实现继承(六)

在Gin等Web框架中,路由是组织应用程序的核心部分之一。在应用程序变得越来越大时,将所有的路由都放在主文件中会使代码变得难以维护和扩展。因此,将路由抽离出来,使代码更加模块化和组织化,有以下几个好处:

提高代码可维护性:将路由单独提取出来,可以减少主文件的复杂性,降低代码的耦合性。这使得代码更容易维护和修改,也更容易进行单元测试。

提高代码可扩展性:将路由抽离出来,可以更容易地添加新的路由和处理函数,而无需修改主文件。这样,当应用程序变得更大时,可以更容易地扩展和维护。

提高代码可读性:将路由从主文件中分离出来,可以更容易地理解应用程序的结构和逻辑。这使得代码更易于阅读和理解,从而更容易协作和维护。

代码复用:将路由抽离出来,可以使不同的模块和包共享相同的路由。这样,可以减少冗余代码,提高代码复用性。

因此,将路由抽离出来是一种良好的编程实践,可以提高代码的可维护性、可扩展性、可读性和复用性。

那么怎么在Gin框架中,可以将路由(routers)抽离出来,以便更好地组织和管理应用程序。

具体的抽离方法如下:

创建一个名为"routers"的包(package)。

在该包中,创建一个名为"router.go"的文件,用于定义路由。

在该文件中,导入(import)"github.com/gin-gonic/gin"库。

定义一个名为"SetupRouter"的函数,用于设置路由。

在"SetupRouter"函数中,创建一个名为"router"的Gin引擎(engine)。

定义路由和处理函数,例如:

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


在main函数中,调用"SetupRouter"函数,并将返回的Gin引擎启动:

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


最后,在其他文件中,导入"routers"包,并使用"SetupRouter"函数设置路由。

这样,就可以将路由和处理函数从主文件中抽离出来,更好地组织和管理应用程序。

另外补充说明一下,还可以类似这样抽离路由:

在main.go 文件中,把之前的路由跳转post和get请求进行一步分组,并且给予单独的文件夹存放,类似于这样:

	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",
			})
		})

	}

这里补充一下,一个概念 router.Group()这个方法是?

在 Gin 框架中,使用 router.Group() 可以创建一个路由组,用于将一组相关的路由分组管理。抽离路由组有以下几个好处:

  1. 代码复用性:将具有相同路径前缀的路由分组管理,可以避免重复定义相同的前缀,提高代码复用性。

  2. 代码可读性:通过分组管理路由,可以使代码更具有可读性,更容易理解和维护。

  3. 可扩展性:当需要添加新的路由时,只需要在相应的路由组中添加即可,而不需要修改主文件中的代码,提高了代码的可扩展性。

  4. 中间件管理:路由组可以使用中间件,将一组路由的共同中间件分组管理,方便管理和维护。

  5. 可配置性:通过路由组,可以对不同的路由分别进行配置,例如设置路由组级别的中间件、路由组级别的错误处理函数等。

因此,抽离 router.Group() 可以提高代码的复用性、可读性、可扩展性、可配置性和中间件管理能力,使代码更加模块化和组织化。

同时,我们这里使用 router.Group()来抽离路由后,为了方便后面的控制器【controller】方法做准备;

这里抽离成功后状态路由应该是,根目录下有一个routers目录,并且下面有多个路由分组后的单个路由文件;类似于 loginRouters.go 这样的文件。那么,这些文件内部优势怎么样子的呢?接下来就是代码部分:

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",
			})
		})

	}
}

以上,就是路由分组后,各自管理自己的路有分组,并且抽离出单独的文件了。

最后一一步就是今天的最终任务,控制器controller的抽离。首先,我们为什么要有控制器,它又是一个什么东西?为啥一定要写控制器?这样的诸如此类的问题,去接着看……

在Gin框架中,将控制器(Controller)从路由处理函数中抽离出来,是一种常见的编程实践。以下是抽离控制器的几个好处:

  1. 分离业务逻辑和路由:将路由处理函数与业务逻辑分离开来,可以使代码更加模块化和组织化。这样,可以更好地管理和维护代码,并且使代码更容易理解和扩展。

  2. 提高代码复用性:将控制器从路由处理函数中抽离出来,可以使控制器代码更加通用和可复用。这样,可以避免在不同的路由处理函数中重复编写相同的代码,提高代码复用性。

  3. 提高代码可读性:将控制器从路由处理函数中抽离出来,可以使代码更加清晰、易于理解和维护。这样,可以更好地遵循“单一职责原则”,使代码更加模块化和组织化。

  4. 方便测试:将控制器从路由处理函数中抽离出来,可以使控制器更容易测试。这样,可以分别测试控制器和路由处理函数,提高代码的可测试性。

因此,将控制器从路由处理函数中抽离出来是一种良好的编程实践,可以提高代码的模块化、组织化、可复用性、可读性和可测试性。

代码演示部分同上代码演化的:

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" 这个包就是控制器部分。

    对应的controller控制器的login包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",
	})
}

以上就是 对控制器 loginControllers.go 文件的具体代码,并且,可以看出,如何从路由分组阶段,演化成 有控制器进行更细化的分类处理,路由中的函数处理方法抽离。

同时,这也缺少了一部分,关于函数是可以继承的,那么对应的控制器文件下,同一个包内是否可以通用呢,答案是……

具体的代码描述一下情况

logincontrollers.go文件

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 文件 

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--成功",
	})
}

这里是不是有点不一样或者说是一样的问题呢?

细心的人就可以看出来,这里控制器的继承 basecontroller.go文件的package 包的名字和 loginconttrollers.go文件的包名一致。

这是为了继承而搞的,如果说,不是一个包如何继承呢?这个问题,需要继续往下学习。

当然,这里如果很难理解,你可以回过头看看基础篇的,结构体继承,同样的道理。

猜你喜欢

转载自blog.csdn.net/A_LWIEUI_Learn/article/details/131298074