使用 Beego 框架实现博客系统的增删改查(CRUD):从路由、ORM 到模板渲染的完整实战
文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载本文是《Build Web Application with Golang》第 13 章构建 Web 框架的收官实战篇对应 pt-br/13.5.md。前四节分别完成了框架的项目规划、路由设计、控制器基类与日志与配置系统本节将把这些组件拼装成一个完整的博客系统实现博客的浏览、新建、编辑与删除。读完本文你将掌握基于 Beego 风格的 MVC 分层思想如何组织项目目录、注册 RESTful 路由、编写控制器与数据模型以及如何用模板完成页面渲染。博客项目目录结构本节实现的博客系统示例项目名beelog遵循 13.1 节的 MVC 目录规划完整结构如下/main.go 应用入口路由注册与启动 /views: 视图模板目录 /view.tpl 博客详情页 /new.tpl 新建博客表单页 /layout.tpl 公共布局模板菜单栏 /index.tpl 博客列表首页 /edit.tpl 编辑博客表单页 /models/model.go 数据模型层Blog 结构体与 ORM 操作 /controllers: 控制器目录 /index.go IndexController首页列表 /view.go ViewController查看详情 /new.go NewController新建 /delete.go DeleteController删除 /edit.go EditController编辑该结构与 13.1 节中规划的main.go / conf / controllers / models / utils / static / views七层目录一脉相承main.go负责初始化并注册路由controllers承载业务逻辑models封装数据库操作views存放 Gotemplate模板文件。从源码结构可以看出示例仓库中相同风格的 MVC 分层也出现在其他章节例如 pt-br/code/src/apps/ch.5.5/main.go 展示了 ORM 层的 CRUD 能力可作为模型层实现的对照参考。博客路由注册动态参数与正则约束路由是整个系统的入口。本节博客在main.go中注册了五条路由规则完整代码如下// 显示博客首页 beego.RegisterController(/, controllers.IndexController{}) // 查看博客详细信息 beego.RegisterController(/view/:id([0-9]), controllers.ViewController{}) // 新建博客博文 beego.RegisterController(/new, controllers.NewController{}) // 删除博文 beego.RegisterController(/delete/:id([0-9]), controllers.DeleteController{}) // 编辑博文 beego.RegisterController(/edit/:id([0-9]), controllers.EditController{})这三类路由模式在 13.2 节的路由实现中都有对应支撑静态路由/与/new直接映射到控制器实例动态参数路由:id会被路由器解析为命名参数存入this.Ctx.Params例如strconv.Atoi(this.Ctx.Params[:id])即可取出id正则约束路由:id([0-9])允许在参数名后以括号形式自定义匹配表达式底层实现将:id([0-9])拆分为参数名:id与正则([0-9])再编译为完整的 URL 正则参见 13.2 节 中ControllerRegistor.Add的解析逻辑从而保证/view/123命中而/view/abc被拒绝。在转发阶段路由器会先匹配静态文件路径再遍历已注册路由用正则子匹配填充参数 map并按请求方法GET/POST/PUT/DELETE 等通过反射调用控制器上对应的方法Get、Post等若全部未命中则返回http.NotFound。这正是博客五个控制器能够各自只实现Get()或同时实现Get()/Post()即可工作的原因。数据库结构设计博客系统使用最简单的单表存储博客信息MySQL 建表语句如下CREATE TABLE entries ( id INT AUTO_INCREMENT, title TEXT, content TEXT, created DATETIME, primary key (id) );entries表包含四个字段自增主键id、标题title、正文content与创建时间created。模型层的Blog结构体正是这张表的映射见下文模型层字段类型一一对应Id int、Title string、Content string、Created time.Time。控制器层五个控制器的完整实现Beego 风格的控制器通过内嵌beego.Controller基类获得完整的生命周期Init → Prepare → 方法处理 → Render → Finish详见 13.3 节子类只需覆写需要处理的 HTTP 方法。IndexController博客列表首页type IndexController struct { beego.Controller } func (this *IndexController) Get() { this.Data[blogs] models.GetAll() this.Layout layout.tpl this.TplNames index.tpl }控制器将查询结果写入this.Data[blogs]并指定布局模板layout.tpl与内容模板index.tpl。当AutoRender开启时框架会在Get()执行后自动调用Render()渲染页面。ViewController查看博客详情type ViewController struct { beego.Controller } func (this *ViewController) Get() { inputs : this.Input() id, _ : strconv.Atoi(this.Ctx.Params[:id]) this.Data[Post] models.GetBlog(id) this.Layout layout.tpl this.TplNames view.tpl }this.Input()返回请求的输入集合this.Ctx.Params[:id]是从 URL 动态参数中取出的字符串 id经strconv.Atoi转为整数后传给模型层查询。NewController新建博客type NewController struct { beego.Controller } func (this *NewController) Get() { this.Layout layout.tpl this.TplNames new.tpl } func (this *NewController) Post() { inputs : this.Input() var blog models.Blog blog.Title inputs.Get(title) blog.Content inputs.Get(content) blog.Created time.Now() models.SaveBlog(blog) this.Ctx.Redirect(302, /) }Get()仅渲染新建表单Post()接收表单提交的title与content字段填充Blog结构体Created取当前时间调用models.SaveBlog持久化后以 302 重定向回首页。同一个控制器同时处理 GET 与 POST正是 13.2 节 所强调的 REST 风格方法映射路由将请求按 HTTP 方法分派给控制器上的同名方法。EditController编辑博客type EditController struct { beego.Controller } func (this *EditController) Get() { inputs : this.Input() id, _ : strconv.Atoi(this.Ctx.Params[:id]) this.Data[Post] models.GetBlog(id) this.Layout layout.tpl this.TplNames edit.tpl } func (this *EditController) Post() { inputs : this.Input() var blog models.Blog blog.Id, _ strconv.Atoi(inputs.Get(id)) blog.Title inputs.Get(title) blog.Content inputs.Get(content) blog.Created time.Now() models.SaveBlog(blog) this.Ctx.Redirect(302, /) }编辑与新建的区别在于Get()需要先按:id查出原文章并注入this.Data[Post]供表单回显Post()除读取title/content外还通过隐藏字段id取得待更新的记录主键同样调用models.SaveBlog完成保存Beedb 的Save会根据结构体主键判断是插入还是更新。DeleteController删除博客type DeleteController struct { beego.Controller } func (this *DeleteController) Get() { id, _ : strconv.Atoi(this.Ctx.Params[:id]) blog : models.GetBlog(id) this.Data[Post] blog models.DelBlog(blog) this.Ctx.Redirect(302, /) }删除操作通过Get()触发先按:id取出文章对象再调用models.DelBlog(blog)删除最后 302 重定向回首页。五个控制器共用一套this.Layout layout.tpl的写法页面外观因此保持一致。模型层基于 Beedb ORM 的 CRUD 封装模型层位于models/model.go通过 Beedb ORM 操作 MySQL 数据库package models import ( database/sql github.com/astaxie/beedb _ github.com/ziutek/mymysql/godrv time ) type Blog struct { Id int PK Title string Content string Created time.Time } func GetLink() beedb.Model { db, err : sql.Open(mymysql, blog/astaxie/123456) if err ! nil { panic(err) } orm : beedb.New(db) return orm } func GetAll() (blogs []Blog) { db : GetLink() db.FindAll(blogs) return } func GetBlog(id int) (blog Blog) { db : GetLink() db.Where(id?, id).Find(blog) return } func SaveBlog(blog Blog) (bg Blog) { db : GetLink() db.Save(blog) return bg } func DelBlog(blog Blog) { db : GetLink() db.Delete(blog) return }要点说明连接建立GetLink()使用标准库database/sql打开mymysql驱动连接连接串为blog/astaxie/123456即 用户名/密码 形式再用beedb.New(db)包装为 ORM 句柄。从源码结构看GetLink在每个操作函数中被重复调用属于为演示简洁而采用的临时连接模式实际项目中建议复用连接或使用连接池主键标注Blog.Id上的PK标签告诉 Beedb 该字段是主键Save与Delete都依赖它定位记录查询 APIFindAll(blogs)批量查询映射到结构体切片Where(id?, id).Find(blog)支持带占位符的条件查询并映射到单个结构体写入与删除Save(blog)依据主键执行插入或更新Delete(blog)按主键删除。Beedb 的这套 APISave/Find/FindAll/Where/Delete与仓库中 pt-br/code/src/apps/ch.5.5/main.go 的完整演示一脉相承——该文件还展示了SetTable、Insert、Update、FindMap、GroupBy、Join等更多能力并包含Userinfo结构体主键标注与 ORM 初始化的完整示例适合作为深入学习 Beedb 的参考。视图层Go 模板渲染博客页面视图层由五个.tpl模板文件组成使用 Gotext/template语法。layout.tpl公共布局模板html head titleMy Blog/title style #menu { width: 200px; float: right; } /style /head body ul idmenu lia href/Home/a/li lia href/newNew Post/a/li /ul {{.LayoutContent}} /body /html布局模板定义了全站统一的 HTML 骨架与右侧导航菜单{{.LayoutContent}}是内容模板的注入占位符。渲染时框架将布局文件与控制器指定的内容模板一起解析执行对应 13.3 节 中Render()对Layout与TplNames的处理逻辑。index.tpl博客列表首页h1Blog posts/h1 ul {{range .blogs}} li a href/view/{{.Id}}{{.Title}}/a from {{.Created}} a href/edit/{{.Id}}Edit/a a href/delete/{{.Id}}Delete/a /li {{end}} /ul{{range .blogs}}遍历控制器注入的博客切片对应this.Data[blogs]每条记录渲染出标题链接、创建时间以及编辑、删除操作链接。链接中的{{.Id}}恰好匹配/view/:id([0-9])、/edit/:id([0-9])、/delete/:id([0-9])三条动态路由。view.tpl博客详情页h1{{.Post.Title}}/h1 {{.Post.Created}}br/ {{.Post.Content}}详情页直接输出this.Data[Post]中的标题、创建时间与正文。new.tpl新建博客表单页h1New Blog Post/h1 form action methodpost Title:input typetext nametitlebr Contenttextarea namecontent colspan3 rowspan10/textarea input typesubmit /form表单以methodpost提交到当前路径/new字段名title与content与NewController.Post()中inputs.Get(title)/inputs.Get(content)一一对应。edit.tpl编辑博客表单页h1Edit {{.Post.Title}}/h1 h1New Blog Post/h1 form action methodpost Title:input typetext nametitle value{{.Post.Title}}br Contenttextarea namecontent colspan3 rowspan10{{.Post.Content}}/textarea input typehidden nameid value{{.Post.Id}} input typesubmit /form编辑表单通过value{{.Post.Title}}与 textarea 内嵌{{.Post.Content}}实现内容回显并通过隐藏字段input typehidden nameid value{{.Post.Id}}把待更新记录的主键传给EditController.Post()。运行与验证将上述文件按目录结构放入$GOPATH/src/beelog下GOPATH 设置方式参见 13.1 节确保 MySQL 中已创建entries表然后启动应用go run main.go浏览器访问http://localhost:8080即可看到博客首页依次可以完成以下完整流程点击菜单New Post进入/new填写标题与内容并提交POST 请求被NewController.Post()处理并重定向回首页新文章出现在列表中点击文章标题进入/view/1查看详情命中ViewController.Get()点击Edit进入/edit/1表单回显原文修改后提交由EditController.Post()保存更新点击Delete访问/delete/1由DeleteController.Get()删除记录并重定向回首页。至此一个覆盖浏览GET/、GET/view/:id、新建GET/POST/new、编辑GET/POST/edit/:id、删除GET/delete/:id的完整博客系统便基于自研框架全部打通——路由、控制器、模型与视图四个层次各司其职也验证了前四节框架设计的正确性。若希望进一步扩展可以参照 13.4 节 将数据库连接串与端口等信息抽入app.conf配置文件并用beego.AppConfig.String(...)读取使系统具备更强的可配置性。赞分享文档教程【免费下载链接】build-web-application-with-golangA golang ebook intro how to build a web with golang项目地址https://gitcode.com/gh_mirrors/bu/build-web-application-with-golang点击查看免费下载相关推荐使用 Beego 框架构建博客系统从 MVC 路由到博客文章增删改查的完整实战使用 Beego 框架构建博客系统从 MVC 路由到博客文章增删改查的完整实战 本指南以开源仓库 build web application with gol文档教程基于 Beego 框架实现博客增删改查第 13.5 节完整实战路由、控制器、ORM 与模板全解析基于 Beego 框架实现博客增删改查第 13.5 节完整实战路由、控制器、ORM 与模板全解析 导读 本节是《Build Web Application文档教程beego 实战用 Go 语言构建博客增删改查CRUD系统——build-web-application-with-golang 第 13.5 节详解beego 实战用 Go 语言构建博客增删改查CRUD系统——build web application with golang 第 13.5 节详解 导文档教程上一篇React-PDF预览导航控件实现PDF预览的页面导航控件下一篇Nerd Fonts 桑基图更新全流程指南从图标数据统计到 SankeyMATIC 出图与 Inkscape 精修创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

深入解析 Remote In Tech 公司档案:以 Spotify 条目(src/companies/spotify.md)为例解读远程友好公司目录的数据结构与渲染机制

深入解析 Remote In Tech 公司档案:以 Spotify 条目(src/companies/spotify.md)为例解读远程友好公司目录的数据结构与渲染机制

数据集 【免费下载链接】remote-jobs Source for remoteintech.company — a community-maintained directory of remote-friendly tech companies 项目地址: https://gitcode.com/GitHub_Trending/re/remote-jobs 点击查看 免费下载 导读 本文以开源仓库 remote-…

2026/10/5 1:51:21 阅读更多 →
Himalaya 打包规范解析:从 Cargo 特性门控到发布产物的工程实践

Himalaya 打包规范解析:从 Cargo 特性门控到发布产物的工程实践

CLI 【免费下载链接】himalaya CLI to manage emails 项目地址: https://gitcode.com/gh_mirrors/hi/himalaya 点击查看 免费下载 Himalaya(CLI to manage emails)作为 Pimalaya 技术栈顶层的应用层,其打包策略决定了二进制产物的…

2026/10/5 1:51:21 阅读更多 →
Filtmall-Shopping-Skill售后教程:订单、物流、取消、退货退款与客服入口一次讲清

Filtmall-Shopping-Skill售后教程:订单、物流、取消、退货退款与客服入口一次讲清

Filtmall-Shopping-Skill售后教程:订单、物流、取消、退货退款与客服入口一次讲清 【免费下载链接】Filtmall-Shopping-Skill Agent-native shopping for extreme value: verifiable same-product price evidence, checkout, orders, delivery, and after-sales. …

2026/10/5 1:51:21 阅读更多 →

最新新闻

抗锯齿方案全解析:从MSAA到TAA与DLSS的选型与实践

抗锯齿方案全解析:从MSAA到TAA与DLSS的选型与实践

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

2026/10/5 2:29:38 阅读更多 →
第061篇 Kotlin 与 Java 的关系:同一 JVM 上的两门语言

第061篇 Kotlin 与 Java 的关系:同一 JVM 上的两门语言

Kotlin 与 Java 的关系这题,Android 岗几乎必问。 答"互操作、Kotlin 编译成 JVM 字节码"只够及格;真正拉开差距的是最后那一步——混编工程里那些容易出事的地方:平台类型(platform type)让可空性在边界处消失、internal 修饰的成员被 Java 调用时不受保护、注…

2026/10/5 2:29:38 阅读更多 →
你的 seek() 为何在文本文件中“迷路”?——Python 文本模式随机访问的编码陷阱与正确姿势

你的 seek() 为何在文本文件中“迷路”?——Python 文本模式随机访问的编码陷阱与正确姿势

你的 seek() 为何在文本文件中“迷路”?——Python 文本模式随机访问的编码陷阱与正确姿势 在 Python 中,seek() 和 tell() 是文件随机访问的基石。在二进制模式下,它们的行为清晰明了:tell() 返回当前的字节偏移量,se…

2026/10/5 2:29:38 阅读更多 →
微客AI助手实战复盘:企业微信AI自动回复答非所问——知识库检索层的三次翻车与一次选型

微客AI助手实战复盘:企业微信AI自动回复答非所问——知识库检索层的三次翻车与一次选型

客户在微信客服里问"这个多少钱",机器人回了一段功能介绍,末尾还补了句"可以试用"。截图发过来,客服同事问是不是 AI 坏了。模型没坏,坏在它前面的知识库检索层——AI 拿到的上下文里根本没有价格信息&#x…

2026/10/5 2:29:38 阅读更多 →
云服务器nacos搭建-集群持久化

云服务器nacos搭建-集群持久化

云服务器nacos搭建-单机-CSDN博客默认:MODE"cluster"集群方式启动,如果单机启动需要设置-m standalone参数,否则,启动失败。账号密码:nacos/nacos。https://blog.csdn.net/guo13313/article/details/1669946…

2026/10/5 2:29:38 阅读更多 →
(142页PPT)PLM+ERP系统选型及建设方案建议书(附下载方式)

(142页PPT)PLM+ERP系统选型及建设方案建议书(附下载方式)

篇幅所限,本文只提供部分资料内容,完整资料请看下面链接 https://download.csdn.net/download/2501_92796370/92933136 资料解读:《(142页PPT)PLMERP系统选型及建设方案建议书》 详细资料请看本解读文章的最后内容。…

2026/10/5 2:28:38 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

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

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

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

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/4 1:00:58 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/4 1:00:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/4 11:40:45 阅读更多 →
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/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练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/4 20:14:29 阅读更多 →