预览
课程特色
本教程录制于2024年8月8日,使用Go1.22版本,基于Goland2024进行开发,采用的技术栈比较新。
每节课控制在十分钟以内,课时精简,每节课都是一个独立的知识点,如果有遗忘,完全可以当做字典来查询,绝不浪费大家的时间。
整个课程从两行代码实现注册登录API接口讲起,以一个课程系统为实战,结合Vue3开发的前端,实现一个基本的前后端分离的课程管理系统,层层递进,学习路径平缓。
Golang是当前国内越来越多的企业正在全面转的一门系统级别的高性能的编程语言,比C语言写法更加的简单,比Python性能更加的好,是新时代的C语言,建议每个程序员都掌握!
视频课程
最近发现越来越多的公司在用Golang了,所以精心整理了一套视频教程给大家,这个是其中的第15部,后续还会有很多。
视频已经录制完成,完整目录截图如下:
本套录播课的售价是319元。
本套课程的特色是每节课都是一个核心知识点,每个视频控制在十分钟左右,精简不废话,拒绝浪费大家的时间。
课程目录
- 01 概述
- 02 搭建项目环境
- 03 连接MySQL数据库
- 04 课程表的设计和创建
- 05 项目工程化
- 06 整合gin框架
- 07 两行代码自动生成注册和登录接口
- 08 封装路由模块
- 09 实现新增课程的接口
- 10 实现分页查询的接口
- 11 实现根据ID查询课程的接口
- 12 解决根据ID查询不生效的问题
- 13 实现根据ID修改课程的接口
- 14 实现根据ID删除课程的接口
- 15 前端界面的整体预览和开发思路
- 16 实现登录的功能
- 17 实现记录token和跳转首页的功能
- 18 实现显示登录用户名的功能
- 19 实现注销的功能
- 20 解决注销按钮无法自动显示的BUG
- 21 完善写作页面和双向绑定变量的设计
- 22 给写作接口添加简单的权限校验
- 23 实现添加文章的功能
- 24 实现文章的请求和动态渲染
- 25 将秒值转换为年月日字符串
- 26 实现点击文章标题跳转详情页面的功能
- 27 实现文章详情的渲染
- 28 渲染课程的价格
- 29 渲染编辑按钮
- 30 实现编辑课程的功能
- 31 给编辑文章的接口添加简单的权限校验
- 32 总结
完整代码
03 连接MySQL数据库
package g
import (
"api/model"
ginLogin "github.com/zhangdapeng520/zdpgo_gin_login"
gorm "github.com/zhangdapeng520/zdpgo_gorm"
_ "github.com/zhangdapeng520/zdpgo_mysql"
)
var GDB *gorm.DB
func initMySQL() {
var err error
GDB, err = gorm.Open(
"mysql",
"root:root@tcp(127.0.0.1:3306)/blog?charset=utf8mb4&parseTime=True&loc=Local",
)
if err != nil {
panic(err)
}
GDB.AutoMigrate(&model.CourseArticle{
})
GDB.AutoMigrate(&ginLogin.GinLoginUser{
})
}
func closeMySQL() {
GDB.Close()
}
04 课程表的设计和创建
package model
type CourseArticle struct {
Id int `json:"id"`
Title string `json:"title" gorm:"unique"` // 标题
Category string `json:"category"` // 分类
Description string `json:"description"` // 描述
Content string `json:"content" gorm:"type:longtext"` // 内容
Price float64 `json:"price" gorm:"type:decimal"` // 价格
SaleNum int `json:"sale_num"` // 销量
GoodNum int `json:"good_num"` // 点赞数量
MoneyNum int `json:"money_num"` // 打赏数量
ViewNum int `json:"view_num"` // 浏览量
AddTime int `json:"add_time"` // 添加时间
UpdateTime int `json:"update_time"` // 修改时间
}
07 两行代码自动生成注册和登录接口
package router
import (
"api/g"
gin "github.com/zhangdapeng520/zdpgo_gin"
ginLogin "github.com/zhangdapeng520/zdpgo_gin_login"
)
func initUser(app *gin.Engine) {
group := app.Group("/user")
group.POST(
"/register/",
ginLogin.GetRegisterHandler(g.GDB, g.PasswordSalt),
)
group.POST(
"/login/",
ginLogin.GetLoginHandler(g.GDB, g.JwtKey, g.PasswordSalt),
)
}
09 实现新增课程的接口
package course_article
import (
"api/g"
"api/model"
gin "github.com/zhangdapeng520/zdpgo_gin"
"time"
)
func add(c *gin.Context) {
// 解析请求
var req requestCourseArticle
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{
"error": err.Error()})
return
}
// 对作者做简单的限制,只有指定的作者才能拥有写作权限
if req.Author != "zhangdapeng" {
c.JSON(402, gin.H{
"error": "you have not authorization"})
return
}
// 新增
now := int(time.Now().Unix())
g.GDB.Create(&model.CourseArticle{
Title: req.Title,
Category: req.Category,
Description: req.Description,
Content: req.Content,
Price: req.Price,
SaleNum: 0,
GoodNum: 0,
MoneyNum: 0,
ViewNum: 0,
AddTime: now,
UpdateTime: now,
})
c.JSON(200, nil)
}
10 实现分页查询的接口
package course_article
import (
"api/g"
"api/model"
gin "github.com/zhangdapeng520/zdpgo_gin"
"strconv"
)
func getAll(c *gin.Context) {
pageStr := c.DefaultQuery("page", "1")
sizeStr := c.DefaultQuery("size", "20")
page, err := strconv.Atoi(pageStr)
if err != nil {
c.JSON(400, gin.H{
"error": err.Error()})
return
}
size, err := strconv.Atoi(sizeStr)
if err != nil {
c.JSON(400, gin.H{
"error": err.Error()})
return
}
var articles []model.CourseArticle
g.GDB.
Limit(size).
Offset((page - 1) * size).
Order("update_time desc").
Find(&articles)
c.JSON(200, articles)
}
func get(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)
if err != nil {
c.JSON(400, gin.H{
"error": err.Error()})
return
}
var article model.CourseArticle
g.GDB.Find(&article, "id=?", id)
c.JSON(200, article)
}
13 实现根据ID修改课程的接口
package course_article
import (
"api/g"
"api/model"
gin "github.com/zhangdapeng520/zdpgo_gin"
"strconv"
)
func update(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)
if err != nil {
c.JSON(400, gin.H{
"error": err.Error()})
return
}
// 解析请求
var req requestCourseArticle
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(400, gin.H{
"error": err.Error()})
return
}
// 添加简单的权限校验
if req.Author != "zhangdapeng" {
c.JSON(402, gin.H{
"error": "you have not authorization"})
return
}
// 根据ID查询
var article model.CourseArticle
g.GDB.Find(&article, "id=?", id)
if article.Id == 0 {
c.JSON(404, gin.H{
"error": "article not found"})
return
}
// 修改
article.Title = req.Title
article.Category = req.Cat