掘金 后端 ( ) • 2024-06-29 09:41

前言

这可以算是一个非主流的框架,但其实它更接近于一个实践项目,而非高度封装的框架。它不像通常框架那样拥有繁多的接口和复杂的封装,而是将所有功能直接体现在代码中,使得开发者能够一目了然地理解其意义,并轻松地根据需要进行修改。

这个框架的仓库地址是goDemoX

  • 功能齐全:包括admin用户管理、登录、权限及角色管理,且前后端功能完备。
  • 可观测性强:内置日志、追踪、指标等可观测性解决方案,方便开发者进行问题定位和性能调优。
  • 文档与测试完备:提供方便的文档交流和测试解决方案,确保代码质量。
  • 自动化管理:支持task自动化管理,包括测试、文档生成、开发及部署等流程。
  • 完善的测试代码:为了保证代码的稳定性和可维护性,该框架拥有完善的测试代码。
  • 技术栈丰富:涉及的技术栈包括gin、gorm、redis等。

这个框架几乎可以拿来即用,但由于其涉及的功能和知识点较多,我将通过一系列文章来详细介绍其实现原理和使用方法。本文将首先探讨gin代码的路由组织。

gin代码的路由组织

在web开发中,路由是任何API框架的核心。gin框架以其简洁的API和强大的中间件功能,使得路由的组织变得异常灵活和方便。

gin允许我们根据需要对路由进行分组,例如按照功能、权限或其他标准进行分组。这种分组方式不仅使代码结构更加清晰,还便于我们进行权限控制、中间件管理等操作。

下面是一个简单的示例代码,演示了如何使用gin进行路由分组:


package main

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

// 顶层路由组织
type Router struct {
    Root *gin.RouterGroup
    Jwt  *gin.RouterGroup //jwt登陆
    Auth *gin.RouterGroup //权限
}

func JwtMiddler() gin.HandlerFunc {
    return func(context *gin.Context) {

       //...jwt校验逻辑
       context.Next()
       //...
    }
}
func AuthMiddler() gin.HandlerFunc {
    return func(context *gin.Context) {

       //...权限校验逻辑
       context.Next()
       //...
    }
}

func NewRouter(g *gin.Engine) *Router {
    return &Router{
       Root: g.Group("/api"),
       Jwt:  g.Group("/api", JwtMiddler()),
       Auth: g.Group("/api", AuthMiddler()),
    }
}

type (
    IHandler interface {
       Do() error
    }
    HandlerFunc func(c *gin.Context) IHandler
)

// api Handler
type ApiHandler struct {
    ctx *gin.Context
}

func NewApiHandler(ctx *gin.Context) IHandler {
    return &ApiHandler{ctx}
}

func (this *ApiHandler) Do() error {
    this.ctx.String(200, "hello world")
    return nil
}

// 异常统一处理
func Do(f HandlerFunc) func(c *gin.Context) {
    return func(c *gin.Context) {

       if err := f(c).Do(); err != nil {
          c.JSON(400, gin.H{"error": err.Error})
       }
    }
}

func main() {
    g := gin.Default()
    router := NewRouter(g)
    router.Root.GET("/test", Do(NewApiHandler))
    g.Run(":8080")
}

这个代码首先定义了router类,所有顶级路由分组都以这个对象为基础,后期想要添加中间件或者添加新的路由分组,可以很容易实现。

业务代码为ApiHandler,实现一个Do()error接口,主要为了实现统一错误处理。

最后通过router.Root.GET("/test", Do(NewApiHandler))这句代码把handler和路由关联到一起。

这是核心代码,为了说明问题,并没有进行任何的目录结构组织。

其他

一个server服务包括什么?配置文件,日志,cli,form表单校验,统一的Response响应,方便的handler代码编写,甚至可观测性。。。。

东西不少,一点点记录下来。