一.环境搭建
本项目旨在在云服务器上搭建清单项目
此项目是跟着七米老师视频做的,建议将他的视频看一遍。
原项目是七米老师的清单项目B站地址
使用finalshell连接云服务器。
在云服务器上安装mysqlCSDN链接
安装Navicat 16(或DBeaver)用以链接数据库。
哪个免费用哪个,那个Navicat界面确实好看。
正确的输入数据库账号和密码以及ssh的账号和密码
gin安装
go get -u github.com/gin-gonic/gin
gorm安装
go get -u gorm.io/gorm
给gorm安装上关于mysql相关的包
go get -u github.com/go-sql-driver/mysql
二.框架搭建
首先导入前端工程
这是七米老师已经进行打包的vue前端文件。
创建go项目,再创建go文件,命名为main.go。
在项目目录下创建一个templates,将项目中index.htm和favicon.iconl放在templates中。再将静态目录static放在项目目录中,这样我们能更好的搭建清单项目。
得到这样的目录
接下来我们开始写go代码
这是我们写的第一版go代码。
gin.Default()启动gin
r.Static("/static", "static")设置静态文件目录
r.LoadHTMLGlob("templates/*")运行模板文件
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
请求数据
r.Run() 运行gin框架
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default() //初始化gin
// 告诉gin框架模板文件引用的静态文件去哪里找
r.Static("/static", "static")
// 告诉gin框架去哪里找模板文件
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
r.Run()
}
然后现在让我们进入文件夹编译文件
go build main.go
再运行文件
./main
我们进入ip:8080得到
接下来我们分析功能。本质上清单无外乎增删改查,故我们添加一个group来放我们的功能组,且我们需要在数据库中创建一个bubble表供我们使用。
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
// Todo model
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Status bool `json:"status"`
}
func main() {
// 创建数据库
// sql:CREATE DATABASE bubble;
// 连接数据库
r := gin.Default()
// 告诉gin框架模板文件引用的静态文件去哪里找
r.Static("/static", "static")
// 告诉gin框架去哪里找模板文件
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
// v1
v1Group := r.Group("v1"){
// 待办事项
// 添加
v1Group.POST("/todo",func(c *gin.Context){
})
// 查看所有的
v1Group.GET("/todo",func(c *gin.Context){{
}})
// 查看某一个
v1Group.GET("/todo/:id",func(c *gin.Context){{
}})
// 修改
v1Group.PUT("/todo/:id",func(c *gin.Context){{
}})
// 删除
v1Group.DELETE("/todo/:id",func(c *gin.Context){
})
}
r.Run()
}
三.功能实现
创建一个bubble数据库
先创建struct,作为清单模型的储存
// Todo Model
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Status bool `json:"status"`
}
然后我们进行数据库的连接,将todo绑定到数据库之中。
func initMySQL() (err error) {
dsn := "root:123456@tcp(127.0.0.1:3306)/bubble?charset=utf8mb4&parseTime=True&loc=Local"
DB, err = gorm.Open("mysql", dsn)
if err != nil {
return
}
return DB.DB().Ping()
}
// 在main函数中
// 创建数据库
// sql: CREATE DATABASE bubble;
// 连接数据库
err := initMySQL()
if err != nil {
panic(err)
}
defer DB.Close() // 程序退出关闭数据库连接
// 模型绑定
DB.AutoMigrate(&Todo{})
现在我们开始一步一步实现功能,写在v1.Group中,先让我们看看整体代码,再分析每个函数干了什么
如果你对CRUD极为熟悉,那这无疑是及其简单的,唯一的区别是将CRUD套入V1这个路由组里面。如果不会可以看之前的文章。
记得修改dsn参数为自己的参数,方能很好的运行。
package main
import (
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"net/http"
)
var (
DB *gorm.DB
)
// Todo Model
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Status bool `json:"status"`
}
func initMySQL() (err error) {
dsn := "root:123456@tcp(127.0.0.1:3306)/bubble?charset=utf8mb4&parseTime=True&loc=Local"
DB, err = gorm.Open("mysql", dsn)
if err != nil {
return
}
return DB.DB().Ping()
}
func main() {
// 创建数据库
// sql: CREATE DATABASE bubble;
// 连接数据库
err := initMySQL()
if err != nil {
panic(err)
}
defer DB.Close() // 程序退出关闭数据库连接
// 模型绑定
DB.AutoMigrate(&Todo{})
r := gin.Default()
// 告诉gin框架模板文件引用的静态文件去哪里找
r.Static("/static", "static")
// 告诉gin框架去哪里找模板文件
r.LoadHTMLGlob("templates/*")
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", nil)
})
// v1
v1Group := r.Group("v1")
{
// 待办事项
// 添加
v1Group.POST("/todo", func(c *gin.Context) {
// 前端页面填写待办事项 点击提交 会发请求到这里
// 1. 从请求中把数据拿出来
var todo Todo
c.BindJSON(&todo)
// 2. 存入数据库
// 3. 反回响应
if err = DB.Create(&todo).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, todo)
}
})
// 查看所有的待办事项
v1Group.GET("/todo", func(c *gin.Context) {
// 查询todo这个表里的所有数据
var todoList []Todo
if err = DB.Find(&todoList).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, todoList)
}
})
// 查看某一个待办事项
v1Group.GET("/todo/:id", func(c *gin.Context) {
})
// 修改某一个待办事项
v1Group.PUT("/todo/:id", func(c *gin.Context) {
id, ok := c.Params.Get("id")
if !ok {
c.JSON(http.StatusOK, gin.H{"error": "无效的id"})
return
}
var todo Todo
if err = DB.Where("id=?", id).First(&todo).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
return
}
c.BindJSON(&todo)
if err = DB.Save(&todo).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, todo)
}
})
// 删除某一个待办事项
v1Group.DELETE("/todo/:id", func(c *gin.Context) {
id, ok := c.Params.Get("id")
if !ok {
c.JSON(http.StatusOK, gin.H{"error": "无效的id"})
return
}
if err = DB.Where("id=?", id).Delete(Todo{}).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, gin.H{id: "deleted"})
}
})
}
r.Run()
}
接下来我们来一个函数一个函数进行理解。
r.Group("v1")进行路由分组,将各种方法进行整合。
以下是我们gin的常用接口。
router.GET("/someGet", getting) router.POST("/somePost", posting) router.PUT("/somePut", putting) router.DELETE("/someDelete", deleting) router.PATCH("/somePatch", patching) router.HEAD("/someHead", head) router.OPTIONS("/someOptions", options)
而在路由分组后v1Group也有其方法, func(c *gin.Context){}是经典的匿名函数。
c.BindJSON(&todo)进行json文件的绑定。c这里是*gin.Context。
还有c.json()这种方法。
DB的方法均是gorm连接数据库后得到的场景,是对数据库的操作。
如DB.AutoMigrate(&Todo{}),DB.DB().Ping()。