Home基于 Gin 封装的高效 Web 框架
基于 Gin 封装的高效 Web 框架

基于 Gin 封装的高效 Web 框架

@新亮

从零开始教你如何基于 Gin 框架封装自己的 Web 框架,涵盖框架设计与实现。无论你经验水平如何,都可获得实际项目开发技巧,提高开发效率。

相比于我的开源项目 go-gin-api(GitHub 5.4K Star),此框架去掉了一些集成的功能和界面,使得整个框架更加简洁、轻量。此外也对代码进行了升级以确保性能和稳定性。开发者就可以更灵活地选择所需的功能,并获得更好的性能和稳定性。

原价 199 元,限时特惠,只需 59.9 元。

买过后,从置顶帖【目录合集】加微信,发源码 + 进交流群。
订阅129
文章44
最后更新:2024-1-12 14:47
查看 【基于 Gin 封装的高效 Web 框架】 详情查看 【新亮】 主页
分享到微信打开

免费内容

2024-2-20 13:37

5.6 示例二:集成登录、注册和用户管理功能

缘起:有部分开发者提出了这样的需求:“亮哥,看了文档和源码后,我还是不知道如何下手,可以基于 gin-api-mono 集成下登录、注册和用户管理功能吗?”于是就有它。为了避免有些开发者不需要这些功能,我重新开了一个新项目去实现。效果操作流程初始化数据表时,请使用 README.md 文档中的表结构。项目启动与 gin-api-mono 一致,查看接口文档。操作「管理员注册」接口,创建数据。操作「管理员登录」接口,登录成功并获取 Token。在接口文档 Authorize 中配置 Token,可访问用户管理相关接口。获取源码,可添加我微信 wx-xinliang 。有启发,左下角点击“启发”告诉我呀,点我即可直接跳转到小册目录合集 。

2024-1-12 14:31

3.4 实现链路日志记录

目前可收集日志类型包括:当前的请求日志当前的响应日志自定义调试日志MySQL 操作日志Redis 操作信息Mongo 操作信息请求三方 API 接口的请求与响应日志日志收集,代码片段:// ./internal/pkg/core/core.go // region 记录日志 var t *trace.Trace if x := context.Trace(); x != nil { t = x.(*trace.Trace) } else { return } decodedURL, _ := url.QueryUnescape(ctx.Request.URL.RequestURI()) // ctx.Request.Header,精简 Header 参数 traceHeader := map[string]string{ "Content-Type": ctx.GetHeader("Content-Type"), } t.WithRequest(&trace.Request{ TTL: "un-limit", Method: ctx.Request.Method, DecodedURL: decodedURL, Header: traceHeader, Body: string(context.RawData()), }) var responseBody interface{} if response != nil { responseBody = response } t.WithResponse(&trace.Response{ Header: ctx.Writer.Header(), HttpCode: ctx.Writer.Status(), HttpCodeMsg: http.StatusText(ctx.Writer.Status()), BusinessCode: businessCode, BusinessCodeMsg: businessCodeMsg, Body: responseBody, CostSeconds: time.Since(ts).Seconds(), }) t.Success = !ctx.IsAborted() && (ctx.Writer.Status() == http.StatusOK) t.CostSeconds = time.Since(ts).Seconds() logger.Info("trace-log", zap.Any("method", ctx.Request.Method), zap.Any("path", decodedURL), zap.Any("http_code", ctx.Writer.Status()), zap.Any("business_code", businessCode), zap.Any("success", t.Success), zap.Any("cost_seconds", t.CostSeconds), zap.Any("trace_id", t.Identifier), zap.Any("trace_info", t), zap.Error(abortErr), ) // endregion使用日志组件,代码片段:// main.go import "gin-api-mono/internal/pkg/logger" // 将日志输出到文件 accessLogger, err := logger.NewJSONLogger( logger.WithField("domain", fmt.Sprintf("%s[%s]", configs.ProjectName, env.Active().Value())), logger.WithTimeLayout(timeutil.CSTLayout), logger.WithFileP(configs.ProjectAccessLogFile), ) // 将日志输出到文件 + 控制台 accessLogger, err := logger.NewJSONLogger( logger.WithOutputInConsole(), logger.WithField("domain", fmt.Sprintf("%s[%s]", configs.ProjectName, env.Active().Value())), logger.WithTimeLayout(timeutil.CSTLayout), logger.WithFileP(configs.ProjectAccessLogFile), ) // 如果需要日志分割,可以使用 WithFileRotationP() 方法。记录自定义调试日志,代码片段:import "gin-api-mono/internal/pkg/debug" // 示例一,记录多个数据 debug.WithContext(ctx.RequestContext()).Logger("这是调试信息A1", "这是调试信息A2") // 示例二,记录单个数据 debug.WithContext(ctx.RequestContext()).Logger("这是调试信息B")记录 MySQL 操作日志,代码片段:// 查询数据,核心是使用 .WithContext() 方法 h.db.GetDbR().WithContext(ctx.RequestContext()).Where(queryWhere).Find(&resultData)记录 Redis 操作日志,代码片段:import "gin-api-mono/internal/repository/redis" // get,核心是使用 ctx.RequestContext() 参数 getResult, err := redis.GetRedisClient().Get(ctx.RequestContext(), "name").Result()记录 Mongo 操作日志,代码片段:import "gin-api-mono/internal/repository/mongo" // 获取 Mongo Client client := mongo.GetMongoClient() // 获取 Collection,例如 Database 为 gin_api_mono,Collection 为 user collection := client.Database("gin_api_mono").Collection("user") // 查询数据,核心是使用 ctx.RequestContext() 参数 findResult, err := collection.Find(ctx.RequestContext(), bson.D{})记录请求三方 API 接口的日志,代码片段:import "gin-api-mono/internal/pkg/httpclient" // 支持在上下文记录执行日志的 httpclient client := httpclient.GetHttpClientWithContext(ctx.RequestContext()) // 普通的 httpclient client := httpclient.GetHttpClient() // GET resp, err := client.R(). SetQueryParams(map[string]string{ "page_no": "1", "limit": "20", "sort":"name", "order": "asc", "random":strconv.FormatInt(time.Now().Unix(), 10), }). SetHeader("Accept", "application/json"). SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F"). Get("/search_result")日志结构,代码片段:// ./internal/pkg/trace/trace.go // Trace 记录的参数 type Trace struct { mux sync.Mutex Identifier string `json:"trace_id"` // 链路ID Request *Request `json:"request"` // 请求信息 Response *Response `json:"response"` // 返回信息 ThirdPartyRequests []*HttpLog `json:"third_party_requests"` // 调用第三方接口的信息 Debugs []*Debug `json:"debugs"` // 调试信息 SQLs []*SQL `json:"sqls"` // 执行的 SQL 信息 Redis []*Redis `json:"redis"` // 执行的 Redis 信息 Mongos []*Mongo `json:"mongos"` // 执行的 Mongo 信息 Success bool `json:"success"` // 请求结果 true or false CostSeconds float64 `json:"cost_seconds"` // 执行时长(单位秒) }不同组件能够将日志记录到上下文的核心是 拦截器,具体在第三方组件集成章节详细描述,此模块有些复杂,也可以微信找我沟通。有启发,左下角点击“启发”告诉我呀,点我即可直接跳转到小册目录合集 。

2024-1-12 13:43

3.1 实现服务启动时可选的配置项

使用 Options 设计模式实现,它可以让我们在服务启动时根据需要选择性地配置应用程序。可配置项,代码片段:// ./internal/pkg/core/core.go type option struct { enablePProf bool enableSwagger bool enablePrometheus bool enableCors bool alertNotify proposal.AlertHandler recordHandler proposal.RecordHandler } // WithEnablePProf 启用 pprof func WithEnablePProf() Option { return func(opt *option) { opt.enablePProf = true } } // WithEnableSwagger 启用 swagger func WithEnableSwagger() Option { return func(opt *option) { opt.enableSwagger = true } } // WithEnablePrometheus 启用 prometheus func WithEnablePrometheus(recordHandler proposal.RecordHandler) Option { return func(opt *option) { opt.enablePrometheus = true opt.recordHandler = recordHandler } } // WithAlertNotify 设置告警通知 func WithAlertNotify(alertHandler proposal.AlertHandler) Option { return func(opt *option) { opt.alertNotify = alertHandler } } // WithEnableCors 设置支持跨域 func WithEnableCors() Option { return func(opt *option) { opt.enableCors = true } }服务启动,代码片段:// ./internal/router/router.go mux, err := core.New(logger, core.WithEnableCors(), core.WithEnableSwagger(), core.WithEnablePProf(), core.WithAlertNotify(alert.NotifyHandler()), core.WithEnablePrometheus(metrics.RecordHandler()), )通过使用 Options 设计模式,我们可以根据需要选择性地配置服务器参数,使得应用程序更加灵活和可扩展。有启发,左下角点击“启发”告诉我呀,点我即可直接跳转到小册目录合集 。

2023-12-8 16:37

【目录合集】内容汇总 | 必看收藏

缘起:有部分开发者提出了这样的需求:“亮哥,你的开源项目 go-gin-api 项目非常适合我,但是我只需要 API 接口和 CURD 操作示例,不需要界面和其他集成功能。能否提供一个简化版的框架供我快速上手?”针对这个需求,gin-api-mono(框架名称) 应运而生。它是一个 简洁、轻量级 的 API 框架,集成了常用组件 并提供了 CURD 操作示例,方便开发者快速上手。与 go-gin-api 不同的是,gin-api-mono 去掉了一些集成的功能和界面,使得整个框架更加简洁、轻量化。此外 gin-api-mono 也对代码进行了升级以确保性能和稳定性。简单说一下 go-gin-api 项目,是一个基于 Gin 的 API 框架,它提供了 WEB 界面一键安装的方式,让你可以快速启动一个开箱即用的 Go 项目 (新手入门必备) 。仓库地址为 https://github.com/xinliangnote/go-gin-api。目前,该项目已经获得了 5.4K 的 Star。学会后,你将 具备中级 Go 工程师的能力,这将使你有机会获得升职和加薪。以 59.9 元的价格来说,仅相当于一顿饭的费用,但它能极大地提高你的工作效率和生产力。这是一个非常值得投资的机会。目前开源项目 go-gin-api 已经过验证,受到了广泛认可,目前已经获得了超过 5.4K 的 Star。这显示了它在开发者社区中的受欢迎程度和影响力。购买后第一步:添加我微信 wx-xinliang,分享源码 + 邀请加入小册交流群。源码分为两套:极简版 CURD 代码带有 登录、注册、用户管理模块提供授课式讲解或答疑服务,收费为每小时 150 元。看看我精心整理的 Go 面试干货,面试时候能帮到你。点我免费进入知识星球:亮哥陪你终身成长。如何用它做小项目,例如「按调用次数收费的接口管理系统」?第一章:了解 Gin 框架1.1 Gin 框架介绍与特点1.2 安装与初始化 Gin1.3 路由和中间件基础第二章:构建自己的 Web 框架2.1 框架设计理念与目标2.2 项目目录结构规划2.3 配置管理与环境切换第三章:核心功能实现3.1 实现服务启动时可选的配置项(免费预览)3.2 实现异常捕获与告警3.3 实现错误处理与告警3.4 实现链路日志记录(免费预览)3.5 包装 gin IRoutes3.6 包装 gin Context3.7 定义统一错误码与错误信息语言包3.8 定义接口返回数据规范第四章:第三方组件集成4.1 集成 gorm 进行 MySQL 数据库操作,并支持主从数据库配置4.2 集成 redis 进行 Redis 数据库操作4.3 集成 mongo 进行 MongoDB 数据库操作4.4 集成 resty 进行 HTTP 接口调用4.5 集成 jwt 实现身份认证及验证中间件4.6 集成 swagger 实现自动生成接口文档4.7 集成 aes 对称加密算法4.8 集成 rsa 非对称加密算法4.9 集成 snowflake 实现生成唯一 ID4.10 集成 cors 实现允许前端跨域请求4.11 集成 prometheus 客户端实现注册和暴露指标4.12 集成 pprof 实现应用程序性能分析4.13 集成 gin 开发环境下实现代码的热更新部署第五章:RESTful API 设计与实现5.1 资源映射和路由设计5.2 自定义编写中间件及使用5.3 请求参数解析与验证5.4 基本 CRUD 操作的实现5.5 运行使用与编译成二进制文件(免费预览)5.6 示例二:集成登录、注册和用户管理功能(免费预览)第六章:加餐6.1 关于 10 个框架设计的实践6.2 Go 开发者成长路线6.3 MySQL 研发规范6.4 Redis 研发规范6.5 Git 使用规范6.6 RESTful API 规范有启发,左下角点击“启发”告诉我呀。

2023-12-6 11:20

5.5 运行使用与编译成二进制文件

环境准备1. golang 1.19 +2. MySQL将本地的 MySQL 信息,配置到 configs/fat_configs.toml 文件中,示例如下:[mysql.read] addr = '127.0.0.1:3306' name = 'gin_api_mono' pass = '123456789' user = 'root' [mysql.write] addr = '127.0.0.1:3306' name = 'gin_api_mono' pass = '123456789' user = 'root'初始化表数据:-- 创建数据表 -- CREATE TABLE `admin` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', `username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名', `mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号', `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员表'; -- 初始化数据 -- INSERT INTO `admin` (`id`, `username`, `mobile`) VALUES (1, '张三', '13888888888'), (2, '李四', '13888888888'), (3, '赵五', '13888888888');启动$ go run main.go -env fat // -env 表示设置哪个环境,主要是区分使用哪个配置文件,默认为 fat // -env dev 表示为本地开发环境,使用的配置信息为:configs/dev_configs.toml // -env fat 表示为测试环境,使用的配置信息为:configs/fat_configs.toml // -env uat 表示为预上线环境,使用的配置信息为:configs/uat_configs.toml // -env pro 表示为正式环境,使用的配置信息为:configs/pro_configs.toml如上,表示启动成功。查看接口文档接口文档地址:http://127.0.0.1:9999/swagger/index.html心跳检测地址:http://127.0.0.1:9999/system/health{ "time": "2023-12-03 22:10:01", "environment": "fat", "host": "127.0.0.1:9999", "status": "ok" }至此,我们就创建了一个简单的 API 项目。编译成二进制文件在项目根目录执行:go build . 以 Mac 环境为例,在项目根目录中会生成一个 gin-api-mono 二进制文件。将二进制文件拷到任何地方,均可执行。获取源码,可添加我微信 wx-xinliang 。有启发,左下角点击“启发”告诉我呀,点我即可直接跳转到小册目录合集 。