15分钟学 Go 实践项目二:打造博客系统

打造博客系统

项目概述

在本项目中,我们将创建一个简单的博客系统,重点实现CRUD(创建、读取、更新、删除)操作和用户管理。这个博客系统将使用户能够发布文章,评论,并管理其个人账户信息。

目标

  1. 实现用户注册、登录、注销功能。
  2. 用户能够创建、查看、更新和删除自己的博客文章。
  3. 实现基本的评论功能。
  4. 使用Go语言的标准库和框架,实现项目结构化管理。

技术栈

  • 编程语言:Go
  • Web框架:Gin
  • 数据库:GORM(Go ORM)
  • 数据库:SQLite(用于简化操作)

系统架构与流程图

以下是该系统的基本架构流程图:

[用户输入] --> [前端页面] --> [Gin路由] --> [控制器] --> [GORM ORM] --> [数据库]

我们将使用Gin作为HTTP框架,GORM作为ORM框架连接至SQLite数据库。

数据库设计

数据表设计

表名字段类型描述
usersidINTEGER用户ID(主键,自增)
usernameVARCHAR(50)用户名(唯一)
passwordVARCHAR(255)密码(哈希)
emailVARCHAR(100)邮箱(唯一)
blogsidINTEGER博客ID(主键,自增)
user_idINTEGER用户ID(外键)
titleVARCHAR(100)博客标题
contentTEXT博客内容
created_atDATETIME创建时间
updated_atDATETIME更新时间
commentsidINTEGER评论ID(主键,自增)
blog_idINTEGER博客ID(外键)
user_idINTEGER用户ID(外键)
contentTEXT评论内容
created_atDATETIME创建时间

数据库初始化

创建一个名为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大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/466047.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于梧桐数据库的实时数据分析解决方案

一、背景 在当今信息时代,数据的价值不言而喻。然而,处理海量数据并将其转化为有意义的洞察力是一项艰巨的任务。传统的数据处理方法已经无法满足我们日益增长的需求。为了满足这一挑战,实时数据处理系统应运而生。 ​ 实时数据处理系统是一…

WireShark入门学习笔记

学习视频:WireShark入门使用教程 扩展学习:wireshark分析常见的网络协议 文章目录 WireShark介绍WireShark抓包入门操作WireShark过滤器使用WireShark之ARP协议分析WireShark之ICMP协议TCP连接的3次握手协议TCP连接断开的4次挥手协议WireShark抓HTTP协…

牛客网Java高频面试题(2024最新版含答案)

作为 Java 程序员,选择学习什么样的技术?什么技术该不该学?去招聘网站上搜一搜、看看岗位要求就十分清楚了,自己具备的技术和能力,直接影响到你工作选择范围和能不能面试成功。 如果想进大厂,那就需要在 Ja…

别名路径联想设置

如何使用/进行路径提示? 找到jsconfig.json文件,如何项目中没有的话,自行创建 {"compilerOptions": {"paths": {"/*": ["./src/*"]}},"exclude": ["node_modules", "dis…

【万字详解】如何在微信小程序的 Taro 框架中设置静态图片 assets/image 的 Base64 转换上限值

设置方法 mini 中提供了 imageUrlLoaderOption 和 postcss.url 。 其中: config.limit 和 imageUrlLoaderOption.limit 服务于 Taro 的 MiniWebpackModule.js , 值的写法要 ()KB * 1024。 config.maxSize 服务于 postcss-url 的…

不愧是阿里巴巴最新开源的Java面试笔记,30万字精华总结 + 面试1300问附答案整理

前言 作为一个 Java 程序员,你平时总是陷在业务开发里,每天噼里啪啦忙敲着代码,上到系统开发,下到 Bug 修改,你感觉自己无所不能。然而偶尔的一次聚会,你听说和自己一起出道的同学早已经年薪 50 万&#x…

C6.【C++ Cont】cout的格式输出

目录 1.头文件 2.使用 1.控制宽度和填充 setw函数(全称set field width设置字段宽度) setfill函数(全称Set fill character设置填充字符) 2.控制数值格式 3.控制整数格式 4.控制对齐方式 1.头文件 用cout进行格式化输出前,先引用头文件iomanip(全称input&output m…

基于SSM+小程序的高校寻物平台管理系统(失物1)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 本基于微信小程序的高校寻物平台有管理员,用户以及失主三个角色。 1、管理员功能有个人中心,用户管理,失主管理,寻物启示管理,拾…

视频——教学篇——拍摄和剪辑

文章目录 拍摄与录制。如何提升音质?如何提升画质?一、提升视频呈现的重点1.音质在很大程度上优先于画质2.在音质层面,环境可能比设备好坏更重要。3.提升视频画面方面,打光比买更好的相机更重要。4.画面的构图不如分镜的节奏来的重…

在线绘制带颜色标注的大脑脑区图

导读:大脑是人体最为复杂的器官之一,由多个功能特化的脑区构成。每个脑区承担着特定的生理和认知功能。通过应用定量数据映射技术,将数值以色彩编码的形式呈现于各个脑区,可以显著增强对不同脑区定量信息的视觉识别和理解。 《bio…

第十九周机器学习笔记:GAN的数学理论知识与实际应用的操作

第十九周周报 摘要Abstratc一、机器学习——GAN Basic Theory1. Maximum Likelihood Estimation2. 复习训练GAN的过程3. Objective function与JS散度相关性推导4. GAN的实际做法 总结 摘要 本周周报主要围绕生成对抗网络(GAN)的基础知识和理论进行深入探…

刷题小记11:栈队列

包括单调栈和优先队列 232. 用栈实现队列 用栈实现队列 两个栈 入队:向入队栈中加入元素 出队:从出队栈中出栈元素,如果出队栈为空,将入队栈所有元素入栈到出队栈。这样顺序就对了 225. 用队列实现栈 用队列实现栈 优化 …

【Qt问题】解决 Cannot retrieve debugging output

【Qt问题】解决 Cannot retrieve debugging output Chapter1 【Qt问题】解决 Cannot retrieve debugging output方案1 关闭其他Qt工程实例(等于没说)方案2 在PRO文件中,加上CONFIG console Chapter1 【Qt问题】解决 Cannot retrieve debuggi…

git 提交代码流程

1. 公-->私-->本-->私-->公 缺点:多了一个步骤,就多了一次申请时间,首先在公仓申请合并到私仓,私仓同意合并,获取到公仓最新版本; 优点:不容易污染公仓 2. 公-->本-->私--&…

Java 中的 transient 关键字:深入解析与实战

在 Java 编程中,transient 关键字是一个非常有用的工具,尤其是在处理对象序列化时。尽管 transient 关键字在日常开发中可能不常被使用,但了解它的作用和使用场景对于提升代码的安全性和性能至关重要。本文将深入探讨 transient 关键字的作用…

App渠道来源追踪方案全面分析(iOS/Android/鸿蒙)

一、App 渠道来源追踪概述 渠道来源统计/追踪,其原理都可以称之为归因,归因是用于判断用户在什么原因、什么时间、什么场景下载了 App,以及打通他们在激活 App 后进行的一系列操作(比如注册、付费、加购等)。 渠道来…

参数跟丢了之JS生成器和包装器

如需转载请注明出处.欢迎小伙伴一起讨论技术. 逆向网址:aHR0cHM6Ly91bmlvbi5qZC5jb20vcHJvTWFuYWdlci9pbmRleD9wYWdlTm89MQ 跟踪接口:aHR0cHM6Ly9hcGkubS5qZC5jb20vYXBp 跟踪参数:h5st 本文目标:记录学习下自定义的生成器和包装器,不做具体的参数加密逻辑分析 直接启动器进…

Redis集群——针对实习面试

目录 Redis集群Redis集群解决了什么问题?Redis集群是如何分片的?什么是Sentinel?Redis如何使用哨兵(Sentinel)系统?集群如何进行故障转移?Redis集群中的主从复制模型是怎样的?Redis集…

【种完麦子,我就往南走,去西双版纳,过个冬天!】

麦子奶奶:冰哥,你好。 大冰:你好,咱俩不定谁大呢。 麦子奶奶:嗯,我大,我60多了,你各方面都是哥。 大冰:阿姨好 麦子奶奶:我想出去看看祖国的大好河山&…

长亭那个检测能力超强的 WAF,出免费版啦

告诉你们一个震撼人心的消息,那个检测能力超强的 WAF——长亭雷池,他推出免费社区版啦,体验地址见文末。 八年前我刚从学校毕业,在腾讯做安全研究,看到宇森在 BlackHat 上演讲的议题 《永别了,SQL 注入》 …