从 PHP 到 AI + Golang,程序员自救转型手记(四十):基类改造
这是一个系列 Blog作者将以一个 PHP 全栈工程师的身份利用 AI 工具claude code、codex、deepseek、豆包等从零开始学习 golang 语言并最终完成 ai-go-admingithub | gitee开源项目的制作全程记录分享。在上一期我们进行了 “前端上传组件实现”本期将完成基类改造基类改造基类严格来讲不是 go 里边的概念在本 blog 中使用它范指 基控制器、基服务、基仓储接下来就是做出第一个后台的管理功能了在此之前对基类进行完善这是一个及其需要细心和周全考虑的工作各大基类的每一行代码都需要是最佳实践扩展性拉满性能拉满。基类改造 前端表格组件一起作者整整花了将近两周时间基类改造情况如下每一个小节一般就是提交给 AI 的一个需求一般一个需要需要多轮对话才能完成然后边修改边人工review最终再完成测试基仓储改造利用 gorm.Statement.Schema 检查字段是否存在必需特意写明利用gorm.Statement.Schema因为直接告诉AI需要一个检查字段是否存在的方法的话它会根据当前模型写一大堆代码预解析出Schema并缓存我测试了一下这种方案还是各大 AI 模型的首选方案实际上当然是没有必要的直接伸手向GORM拿就行了。最终检查字段是否存在方法的签名为func (r *Repository[T]) FieldExists(field string) (bool, error)获取主键字段方法依旧是利用gorm.Statement.Schema获取主键字段调用GORM Statement.Parse方法解析模型数据该函数内部会复用GORM的Schema缓存。复合主键模型返回GORM识别的优先主键字段最终方法签名为func (r *Repository[T]) PrimaryKeyField() (string, error)代码如下// FieldExists 检查当前模型是否包含指定字段// 同时支持 Go 字段名和数据库列名Statement.Parse 会复用 GORM 的 Schema 缓存func(r*Repository[T])FieldExists(fieldstring)(bool,error){fieldstrings.TrimSpace(field)iffield{returnfalse,nil}stmt:gorm.Statement{DB:r.DB()}iferr:stmt.Parse(new(T));err!nil{returnfalse,err}returnstmt.Schema.LookUpField(field)!nil,nil}增加 Count 方法此方法用于获取数据条数签名为func (r *Repository[T]) Count(c *gin.Context, opts Options) (int64, error)使用opts.Scopes忽略opts中的分页、排序、字段选择等。已有方法改造先定义一个所有方法通用的Options结构体// Options 通用仓库操作选项各选项可按需使用typeOptionsstruct{Omit[]string// 排除出入库字段将在 Create、Update、List 等方法中应用至 GORM 的 Select 方法Select[]string// 选择出入库字段其余同上Scopes[]func(*gorm.Statement)// 将在 List 和 Get 等方法中直接传递给 GORM 的 Scopes 方法可以自定义 查询、排序、分页 等等PrimaryKeystring// 主键值提供则会在 Get 方法中作为 Where 的参数}基仓储 List 改造丰富入参和功能如下// 原来的func(r*Repository[T])List(c*gin.Context,scopes...func(*gorm.Statement))([]T,error)// 改为func(r*Repository[T])List(c*gin.Context,opts Options)([]T,error)即将scopes参数改为optsopts里边可以传递scopes并且额外还可以传递排序字段、选择排除字段等选项未来要扩展也很方便List方法内根据opts确定如何读取数据另外对于Select和Omit字段我并没有使用FieldExists方法对字段名逐一确定是否存在开发者需自行对传入的字段名负责程序不会对未知字段报警。基仓储 Create / Update / Get 改造仓储层的Create / Update / Get方法也需要增加opts Options参数并应用上这些配置。在Create / Update方法内Select / Omit配置决定入库字段。在Get方法内不仅可以使用Select / Omit来决定出库字段也支持scopes和PrimaryKey主键值选项若提供了PrimaryKeyGet会拼接类似这样的查询条件Where(pk ?, opts.PrimaryKey)同时并不会忽略scopes。基控制器、基服务改造首先是整体规划的改变比如控制器要支持更多的请求数据本次改造支持了排序、分页、多字段条件查询等特别是服务层的List方法首先看基仓储的List方法它太简单了如下func(r*Repository[T])List(c*gin.Context,opts Options)([]T,error){q:gorm.G[T](r.DB()).Scopes(opts.Scopes...)// 出库字段的选择与忽略iflen(opts.Select)0{qq.Select(strings.Join(opts.Select,,))}iflen(opts.Omit)0{qq.Omit(opts.Omit...)}returnq.Find(c.Request.Context())}可以看到仓储层主要是接受了一个Scopes函数切片这意味着我们前端传递的排序、分页、多字段条件查询等都需要在服务层构建为Scopes然后直接传递给仓储层使用Select和Omit逻辑为和其他方法保持统一并未使用Scopes的方式定义。基控制器接受主键的方式优化旧的主键接受固定接受为int类型如下id,err:strconv.ParseUint(c.Param(id),10,64)新的接受方式首先变量改名为更加通用的pk然后直接接受为string并以string类型直接传递至 服务、仓储 等各层如下pk:c.Param(pk)只在需要做比较、计算时再根据当前模型的主键类型转为 int 即可且一般无需转换因为对于 GORM 来说主键传的是 int 或 string生成的 SQL 都是一样的。服务层 List 方法响应字段增加list接口目前直接响应单个data字段内容是对应模型中的数据需要改为data.list数据、data.total数据条数使用仓储层的Count方法分页支持基控制器额外接受page和limit参数传递给服务层由服务层建立一个Paginate Scopes最终传递给仓储的List方法该方法支持Scopes能直接使用分页器。排序支持基本同上。多字段条件查询支持对应基服务internal/service/base.go的BuildWhereScopes方法最终会返回多个scopes。前端传递的查询条件是这样的{wheres:[{field:username,operator:NOT ILIKE,value:test,}]}BuildWhereScopes会根据以上前端传值组装where实现起来非常简单主要是operator它代表 SQL 运算符号需要支持很多比如,,,LIKE,ILIKE,IS NULL等这里有一个小坑,,这类符号在传输时很可能被转义掉这里需要写一个转换函数如下// GetOperatorByAlias 符号类运算符别名 → SQL 运算符funcGetOperatorByAlias(opstring)string{switchop{caseeq,:returncasene:return!casegt:returncasegte:returncaselt:returncaselte:returndefault:returnop// LIKE、IN、NOT IN 等单词运算符直接透传}}然后前端使用operator: eq、operator: ne等就行了不要使用原始符号。未来还会再次完善支持字段白名单、操作符号白名单、OR 条件等测试IS NOT NULL 无效在人工测试中找到一个review没发现的问题list接口筛选数据时操作符使用IS NOT NULL无效查看了代码发现 AI 居然犯了个很低级的错误switchop{caseIS NULL,IS NOT NULL:scopesappend(scopes,func(stmt*gorm.Statement){stmt.Where(w.Field IS NULL)})}操作符号为IS NULL和IS NOT NULL时都是固定的stmt.Where(w.Field IS NULL)改为stmt.Where(w.Field op)才对。不兼容范围查询switchop{caseBETWEEN:scopesappend(scopes,func(stmt*gorm.Statement){stmt.Where(w.Field BETWEEN ? AND ?,w.Value)})}如上w.Value只有一个但是BETWEEN需要一个范围值解决方案也很简单前端传递数组或简单的以,分割多个值后端这边再切一下即可。

相关新闻

5个常用的网页制作软件和建站系统,省时又省力!

5个常用的网页制作软件和建站系统,省时又省力!

当你想建立一个网站和站群时,你会需要一款强大且便于使用的网页制作软件或建站工具。在这篇文章中,我们将为你推荐5款常用的网页制作软件或建站系统,帮助你在网页制作中省时又省力! 1. PageAdmin PageAdmin是一款国产企业级网站…

2026/10/7 23:57:50 阅读更多 →
2026论文神级降AI率平台大曝光:三步操作让AI痕迹消失无踪

2026论文神级降AI率平台大曝光:三步操作让AI痕迹消失无踪

2026年的学术战场已经彻底变了天,论文写法和审查标准都在经历一场静默的革命。过去那种只要把查重率压下去就能过关的日子一去不复返了,现在的学生不仅要面对传统查重系统的严苛筛查,还要在AI痕迹检测上如履薄冰。随着AI写作工具的普及&#…

2026/10/11 21:36:59 阅读更多 →
如何在Unity游戏中实现实时自动翻译:XUnity.AutoTranslator终极指南

如何在Unity游戏中实现实时自动翻译:XUnity.AutoTranslator终极指南

如何在Unity游戏中实现实时自动翻译:XUnity.AutoTranslator终极指南 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为外语游戏中的对话和菜单而烦恼吗?XUnity.AutoTranslator…

2026/10/15 19:34:21 阅读更多 →

最新新闻

二维码DLL工程实战:从编码模式到RS纠错的完整构建指南

二维码DLL工程实战:从编码模式到RS纠错的完整构建指南

简介:面向C开发者的二维码生成DLL封装源码工程,适用于需要在VS2008环境下将二维码编码能力封装为动态链接库、供多程序复用的场景。完整包含工程配置、核心编码算法及导出接口示例,可帮助理解Windows DLL开发流程与二维码数据编码原理。压缩包…

2026/10/16 15:55:20 阅读更多 →
慧荣SMI主控U盘量产开卡:从0字节修复到参数匹配全流程

慧荣SMI主控U盘量产开卡:从0字节修复到参数匹配全流程

简介:慧荣SMI万能开卡量产工具smV2.5.47.zip,是面向SSD维修技术人员、售后工程师及进阶玩家的慧荣主控开卡软件,重点适配SM2246ENAA、SM2246AB等SM2246系列主控,可解决固态硬盘不识别、容量异常、掉盘、需要重新初始化等问题&…

2026/10/16 15:55:20 阅读更多 →
STM32红外解码与编码实战:NEC协议解析及避坑指南

STM32红外解码与编码实战:NEC协议解析及避坑指南

简介:面向STM32红外功能开发的完整参考工程,适合嵌入式初学者入门以及进阶者快速搭建红外收发模块。资源以红外遥控代码为核心,搭配LCD液晶驱动(ILI93xx)、触摸屏(touch)与usmart串口调试组件&a…

2026/10/16 15:55:20 阅读更多 →
Android仿微信头像裁剪:Matrix手势交互与自定义View实现

Android仿微信头像裁剪:Matrix手势交互与自定义View实现

简介:面向Android开发者的仿微信换头像功能示例工程,聚焦图片缩放、旋转、裁剪与还原等核心图像处理技术,特别适合需要实现自定义头像选择、编辑功能的移动应用开发者参考。资源为RAR压缩包,共1808个文件,19.25MB&…

2026/10/16 15:55:20 阅读更多 →
MT6799 Android源码编译:虚拟机环境配置与报错排查实战

MT6799 Android源码编译:虚拟机环境配置与报错排查实战

简介:面向安卓底层开发与嵌入式工程师的MT6799开发板源码编译实战笔记,聚焦Ubuntu 16.04环境下安卓7.0(Nougat,兼顾4.4)的下载与编译流程。资源为单份Word文档,体积约895KB,内容涵盖虚拟机环境搭…

2026/10/16 15:55:20 阅读更多 →
嵌入式源码怎么读?6大经典项目拆解状态机、PID与低功耗实战

嵌入式源码怎么读?6大经典项目拆解状态机、PID与低功耗实战

简介:这个资源汇集了6个可直接研读的经典嵌入式项目源码,面向嵌入式初学者与进阶开发者,尤其适合希望了解ARM处理器外设驱动、启动初始化及通信协议实现的工程师。整个压缩包共含约300个文件,以C源码、H头文件为核心,并…

2026/10/16 15:54:19 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →