使用Gin+Gorm完成清单项目

664 阅读4分钟

一.环境搭建

本项目旨在在云服务器上搭建清单项目

此项目是跟着七米老师视频做的,建议将他的视频看一遍。

原项目是七米老师的清单项目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

二.框架搭建

首先导入前端工程

下载地址在github.com/Q1mi/go_web…

这是七米老师已经进行打包的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这个路由组里面。如果不会可以看之前的文章。

简单使用gin+gorm实现CRUD

记得修改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()。