15分钟学 Go 实践项目二:打造博客系统
打造博客系统
项目概述
在本项目中,我们将创建一个简单的博客系统,重点实现CRUD(创建、读取、更新、删除)操作和用户管理。这个博客系统将使用户能够发布文章,评论,并管理其个人账户信息。
目标
- 实现用户注册、登录、注销功能。
- 用户能够创建、查看、更新和删除自己的博客文章。
- 实现基本的评论功能。
- 使用Go语言的标准库和框架,实现项目结构化管理。
技术栈
- 编程语言:Go
- Web框架:Gin
- 数据库:GORM(Go ORM)
- 数据库:SQLite(用于简化操作)
系统架构与流程图
以下是该系统的基本架构流程图:
[用户输入] --> [前端页面] --> [Gin路由] --> [控制器] --> [GORM ORM] --> [数据库]
我们将使用Gin作为HTTP框架,GORM作为ORM框架连接至SQLite数据库。
数据库设计
数据表设计
| 表名 | 字段 | 类型 | 描述 |
|---|---|---|---|
| users | id | INTEGER | 用户ID(主键,自增) |
| username | VARCHAR(50) | 用户名(唯一) | |
| password | VARCHAR(255) | 密码(哈希) | |
| VARCHAR(100) | 邮箱(唯一) | ||
| blogs | id | INTEGER | 博客ID(主键,自增) |
| user_id | INTEGER | 用户ID(外键) | |
| title | VARCHAR(100) | 博客标题 | |
| content | TEXT | 博客内容 | |
| created_at | DATETIME | 创建时间 | |
| updated_at | DATETIME | 更新时间 | |
| comments | id | INTEGER | 评论ID(主键,自增) |
| blog_id | INTEGER | 博客ID(外键) | |
| user_id | INTEGER | 用户ID(外键) | |
| content | TEXT | 评论内容 | |
| created_at | DATETIME | 创建时间 |
数据库初始化
创建一个名为blog_system.db的SQLite数据库,并使用以下代码初始化:
package mainimport ("gorm.io/driver/sqlite""gorm.io/gorm""log"
)type User struct {ID uint `gorm:"primaryKey"`Username string `gorm:"unique"`Password stringEmail string `gorm:"unique"`
}type Blog struct {ID uint `gorm:"primaryKey"`UserID uintTitle stringContent stringCreatedAt time.TimeUpdatedAt time.Time
}type Comment struct {ID uint `gorm:"primaryKey"`BlogID uintUserID uintContent stringCreatedAt time.Time
}func InitDB() *gorm.DB {db, err := gorm.Open(sqlite.Open("blog_system.db"), &gorm.Config{})if err != nil {log.Fatalf("failed to connect database: %v", err)}db.AutoMigrate(&User{}, &Blog{}, &Comment{})return db
}
用户管理模块
用户注册
// 注册用户
func Register(db *gorm.DB, username, password, email string) error {user := User{Username: username, Password: HashPassword(password), Email: email}if err := db.Create(&user).Error; err != nil {return err}return nil
}
用户登录
// 登录用户
func Login(db *gorm.DB, username, password string) (*User, error) {var user Userif err := db.Where("username = ?", username).First(&user).Error; err != nil {return nil, err}if !CheckPasswordHash(password, user.Password) {return nil, fmt.Errorf("incorrect password")}return &user, nil
}
用户注销
用户可以通过服务端清除session实现注销,这里简单演示。
// 注销用户
func Logout(c *gin.Context) {session := sessions.Default(c)session.Clear()session.Save()c.JSON(http.StatusOK, gin.H{"message": "logged out"})
}
博客操作模块
创建博客
// 创建博客
func CreateBlog(c *gin.Context) {var blog Blogif err := c.ShouldBindJSON(&blog); err != nil {c.JSON(http.StatusBadRequest, err)return}blog.CreatedAt = time.Now()blog.UpdatedAt = time.Now()if err := db.Create(&blog).Error; err != nil {c.JSON(http.StatusInternalServerError, err)return}c.JSON(http.StatusOK, blog)
}
读取博客
// 读取博客列表
func GetBlogs(c *gin.Context) {var blogs []Blogdb.Find(&blogs)c.JSON(http.StatusOK, blogs)
}// 读取单篇博客
func GetBlog(c *gin.Context) {id := c.Param("id")var blog Blogif err := db.First(&blog, id).Error; err != nil {c.JSON(http.StatusNotFound, err)return}c.JSON(http.StatusOK, blog)
}
更新博客
// 更新博客
func UpdateBlog(c *gin.Context) {id := c.Param("id")var blog Blogif err := db.First(&blog, id).Error; err != nil {c.JSON(http.StatusNotFound, err)return}if err := c.ShouldBindJSON(&blog); err != nil {c.JSON(http.StatusBadRequest, err)return}blog.UpdatedAt = time.Now()db.Save(&blog)c.JSON(http.StatusOK, blog)
}
删除博客
// 删除博客
func DeleteBlog(c *gin.Context) {id := c.Param("id")if err := db.Delete(&Blog{}, id).Error; err != nil {c.JSON(http.StatusNotFound, err)return}c.JSON(http.StatusOK, gin.H{"message": "blog deleted"})
}
评论功能模块
添加评论
// 添加评论
func AddComment(c *gin.Context) {var comment Commentif err := c.ShouldBindJSON(&comment); err != nil {c.JSON(http.StatusBadRequest, err)return}comment.CreatedAt = time.Now()if err := db.Create(&comment).Error; err != nil {c.JSON(http.StatusInternalServerError, err)return}c.JSON(http.StatusOK, comment)
}
获取评论
// 获取博客的评论
func GetComments(c *gin.Context) {blogID := c.Param("blogId")var comments []Commentdb.Where("blog_id = ?", blogID).Find(&comments)c.JSON(http.StatusOK, comments)
}
项目结构
以下是我们项目的结构示意:
/blog-system├── main.go├── models.go├── handlers.go├── routes.go├── db.go
main.go:主入口文件,负责启动服务。models.go:定义数据库模型。handlers.go:处理请求的相关逻辑。routes.go:定义路由。db.go:数据库初始化和相关操作。
main.go 文件示例
package mainimport ("github.com/gin-gonic/gin""gorm.io/gorm"
)var db *gorm.DBfunc main() {db = InitDB()r := gin.Default()SetRoutes(r)r.Run(":8080")
}
路由配置
package mainimport "github.com/gin-gonic/gin"func SetRoutes(r *gin.Engine) {r.POST("/register", func(c *gin.Context) {// 处理用户注册})r.POST("/login", func(c *gin.Context) {// 处理用户登录})r.POST("/blogs", CreateBlog)r.GET("/blogs", GetBlogs)r.GET("/blogs/:id", GetBlog)r.PUT("/blogs/:id", UpdateBlog)r.DELETE("/blogs/:id", DeleteBlog)r.POST("/blogs/:blogId/comments", AddComment)r.GET("/blogs/:blogId/comments", GetComments)
}
安全性与哈希处理
记得在所有密码存储过程中,一定要使用哈希处理,更加安全。例如,使用bcrypt库。
package mainimport ("golang.org/x/crypto/bcrypt"
)func HashPassword(password string) string {bytes, _ := bcrypt.GenerateFromPassword([]byte(password), 14)return string(bytes)
}func CheckPasswordHash(password, hash string) bool {err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))return err == nil
}
总结
以上内容提供了一个基于Go语言的简单博客系统的创建指南,通过实现用户管理和CRUD操作,你可以深入理解Go语言的应用场景和开发流程。你可以根据该代码扩展新功能,例如用户角色管理、使用JWT进行验证等,进一步提升项目的复杂度与实用性。希望这个项目对你有帮助,勇于实践,将理论转化为生产力。
怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!
相关文章:
15分钟学 Go 实践项目二:打造博客系统
打造博客系统 项目概述 在本项目中,我们将创建一个简单的博客系统,重点实现CRUD(创建、读取、更新、删除)操作和用户管理。这个博客系统将使用户能够发布文章,评论,并管理其个人账户信息。 目标 实现用…...
Follow软件的使用入门教程
开篇 看到很多兄弟还不知道怎么用这个当下爆火的浏览器!在这里简单给需要入门的小伙伴一些建议: 介绍 简单解释一下,RSS 意思是简易信息聚合,用户可以通过 RSS 阅读器或聚合工具自主订阅并浏览各个平台的内容源,不用…...
【IC验证】systemverilog的设计特性
systemverilog的设计特性 一.概述二.面向硬件的过程语句块1.说明2.always_comb2.always_latch3.always_ff 三.关系运算符1.说明2.例子 四.inside判定符1.说明2.例子 五.条件分支语句(1)说明(2)例子(case和unique case的…...
【点击劫持漏洞(附测试代码)】
漏洞描述 点击劫持(Clickjacking)是一种网络攻击技术,攻击者通过将一个恶意的页面或按钮隐藏在合法网站的页面下,诱使用户在不知情的情况下点击隐藏的内容,从而触发攻击者设计的操作。这种攻击通常会导致用户无意中执…...
【AD】3-4 在原理图中放置元件
1.打开原理图库,选中元件点击放置 2.点击工程右键,选择,,进行编译,点击Components,选中鼠标点击拖动即可...
协程2 --- 相关概念
文章目录 协程切换方案协程库的完善程度协程栈方案协程调度实现有栈协程与无栈协程对称协程与非对称协程 协程切换方案 具体使用和解析看栈切换那个博客 使用setjump、longjump c语言提供的方案 可参考:libmill 使用操作系统提供的api:ucontext、fiber …...
Hadoop-005-HDFS分布式文件存储原理
一、HDFS数据如何存储 分布式存储:每个服务器(节点)存储文件的一部分, 本文提到的part只是为方便理解, 指的文件部分数据, 并不是真实存在的概念 #mermaid-svg-qjJMG6r2bzRNcWkF {font-family:"trebuchet ms",verdana,arial,sans-s…...
【多线程入门篇】 创建线程以及线程的属性
大家好呀 我是浪前 今天给大家讲解的是创建线程以及线程的属性 祝愿所有点赞关注的人,身体健康,一夜暴富,升职加薪迎娶白富美!!! 点我领取迎娶白富美大礼包 🍓多线程编程: 前言: 我们为什么不用多进程?…...
三十四、Python基础语法(文件操作-上)
一、介绍 文件:可以储存在长期储存设备上的一段数据,在计算机储存的数据都是二进制的形式储存的,我们用软件打开文件不是看见0和1是因为软件会自动将二进制数据进行转换。 二、文件操作 1.打开文件 打开文件:文件是在硬盘中储…...
【大咖云集,院士出席 | ACM独立出版】第四届大数据、人工智能与风险管理国际学术会议 (ICBAR 2024,11月15-17日)--冬季主会场
第四届大数据、人工智能与风险管理国际学术会议 (ICBAR 2024)--冬季主会场 2024 4th International Conference on Big Data, Artificial Intelligence and Risk Management 官方信息 会议官网:www.icbar.net 2024 4th International Conference on Big Data, Art…...
03 Oracle进程秘籍:深度解析Oracle后台进程体系
文章目录 Oracle进程秘籍:深度解析Oracle后台进程体系一、Oracle后台进程概览1.1 DBWn(Database Writer Process)1.2 LGWR(Log Writer Process)1.3 SMON(System Monitor Process)1.4 PMON&#…...
AndroidStudio通过Bundle进行数据传递
作者:CSDN-PleaSure乐事 欢迎大家阅读我的博客 希望大家喜欢 使用环境:AndroidStudio 目录 1.新建活动 2.修改页面布局 代码: 效果: 3.新建类ResultActivity并继承AppCompatActivity 4.新建布局文件activity_result.xml 代…...
Linux篇(文件管理命令)
目录 一、Linux下文件命名规则 1. 可以使用哪些字符 2. 文件名的长度 3. 文件名的大小写 4. Linux文件扩展名 二、目录创建与删除 1. 目录创建 1.1. mkdir创建目录 1.2. mkdir -p 递归创建目录 1.3. 使用mkdir同时创建多个目录 2. 目录删除(必须是空目录&…...
大数据新视界 -- 大数据大厂之 Impala 性能优化:数据存储分区的艺术与实践(下)(2/30)
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
【数据结构】B树
B树(B-Tree)是一种自平衡的多叉搜索树,广泛应用于数据库系统和文件系统中,以便高效地进行数据存储和检索。它的设计目标是减少磁盘I/O操作,使得在大量数据的情况下依然能够进行快速的查找、插入和删除操作。 B树的特点…...
Docker 容器网络模式详解
Docker 容器网络模式详解 1.1 引言 1.1.1 Docker 网络简介 Docker 是一个开源的应用容器引擎,它允许开发者将应用和依赖打包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器采用沙箱机制,彼此…...
吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)4.11
目录 第四门课 卷积神经网络(Convolutional Neural Networks)第四周 特殊应用:人脸识别和神经风格转换(Special applications: Face recognition &Neural style transfer)4.11 一维到三维推广(1D and 3…...
小游戏开发,出现了降本增效的技术?
中国经济下行大周期下,要说受影响程度较小的,非游戏行业莫属了。 小游戏的快速增长主要得益于其便捷的使用方式和轻量化的特点。小游戏通常无需下载,即点即玩,适合在碎片时间内进行娱乐,这种特性吸引了大量用户。此外…...
(4)Java 编程基础概览:Java中的输入输出操作与代码注释详解
目录 1. 控制台输出操作2. 控制台输入操作代码解释:3. 代码注释3.1 单行注释3.2 多行注释3.3 文档注释3.4 注释的重要性3.5 注意事项在Java编程语言中,输入与输出(I/O)操作扮演着举足轻重的角色。它们允许程序与外界环境进行数据的交互,无论是从用户处获取信息,还是向用户…...
Git使用指南
目录 工作机制基本框架:流程图 基本命令分支操作远程仓库本地仓库关联远程仓库 参考 工作机制 基本框架: Workspace:开发者工作区,也就是你当前写代码的目录,它一般保持的是最新仓库代码。Index / Stage:暂存区,最早…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
