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:暂存区,最早…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...