1.gin框架介绍
1.1介绍
Gin 是一个用 Go (Golang) 编写的 HTTP Web 框架。使用了httprouter,高性能的API框架。
1.2安装
go get -u github.com/gin-gonic/gin
1.3 hello gin
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
r := gin.Default()
// 2.绑定路由规则,执行的函数
// gin.Context,封装了request和response
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "hello World!")
})
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8080")
r.Run(":8000")
}
安装gin之前要创建一个go模块文件才能进行gin的安装
1.4RESTful API
REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”。
简单来说,REST的含义就是客户端与Web服务器之间进行交互的时候,使用HTTP协议中的4个请求方法代表不同的动作。
GET用来获取资源
POST用来新建资源
PUT用来更新资源
DELETE用来删除资源。
r.GET("/book", func(c *gin.Context) {
c.JSON(200, gin.H{
"method": "GET",
})
})
r.POST("/book", func(c *gin.Context) {
c.JSON(200, gin.H{
"method": "POST",
})
})
r.PUT("/book", func(c *gin.Context) {
c.JSON(200, gin.H{
"method": "PUT",
})
})
r.DELETE("/book", func(c *gin.Context) {
c.JSON(200, gin.H{
"method": "DELETE",
})
})
1.5接收参数的几种方式
get接收
id := c.Query(“id”) Query接受参数
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
r := gin.Default()
userpath := r.Group("") //添加前缀
User(userpath) //调用
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8080")
r.Run(":8000")
}
func User(userGrp *gin.RouterGroup) {
userGrp.Use().GET("/user", findUser) //路由前缀 指定方法
}
func findUser(c *gin.Context) {
id := c.Query("id")
name := c.Query("name")
fmt.Println(id)
fmt.Println(name)
c.JSON(200, gin.H{
"method": "GET",
"id":id,
"name":name,
})
}
post form提交
func User(userGrp *gin.RouterGroup) {
userGrp.Use().GET("/user", findUser) //路由前缀 指定方法
userGrp.Use().POST("/add", addUser) //路由前缀 指定方法
}
func addUser(c *gin.Context) {
id := c.PostForm("id")
name := c.PostForm("name")
fmt.Println(id)
fmt.Println(name)
c.JSON(200, gin.H{
"method": "GET",
"id": id,
"name": name,
})
}
json提交
需要导入"encoding/json"
var m map[string]interface{} map类型
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
// 1.创建路由
r := gin.Default()
userpath := r.Group("") //添加前缀
User(userpath)
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8080")
r.Run(":8000")
}
func User(userGrp *gin.RouterGroup) {
userGrp.Use().POST("/a", aUser) //路由前缀 指定方法
}
func aUser(c *gin.Context) {
b, _ := c.GetRawData() // 从c.Request.Body读取请求数据
// 定义map或结构体
var m map[string]interface{}
// 反序列化
_ = json.Unmarshal(b, &m)
c.JSON(200, gin.H{
"method": "GET",
"m": m,
"id": m["id"],
"name": m["name"],
})
}
结构体接收传参
//创建结构体 结构体里的字段名要大写
type AddStu struct {
Name string
Id int
}
func aaUser(c *gin.Context) {
// 前面要加上&符号 如果在别的文件里的结构体 就在最前加
// 例如 schemas文件夹 其中一个go文件里的结构体
// addStu := &schemas.AddStu{}
// 定义结构体接收参数
addStu := &AddStu{}
//绑定参数
_ = c.Bind(addStu)
c.JSON(200, gin.H{
"method": "GET",
"data": addStu,
})
}
2.结构体方式传参数据库添加
2.1定义接收参数的结构体
新建schemas文件夹,在文件夹下新建user_schemas.go文件
注意:结构体中的变量名必须大写,否则无法使用
package schemas
type AddStu struct {
Name string
Age int
}
2.2在方法中使用
func addUser(c *gin.Context) {
//定义结构体接收参数
addStu := &schemas.AddStu{}
//绑定参数
_ = c.Bind(addStu)
//直接使用
stu := &model.Student{
Name: addStu.Name,
Age: addStu.Age,
}
//加入数据库
model.DB.Create(stu)
c.JSON(200, gin.H{
"method": "GET",
})
}
2.gorm介绍
1.1介绍
全功能 ORM
关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
Create,Save,Update,Delete,Find 中钩子方法
支持 Preload、Joins 的预加载
事务,嵌套事务,Save Point,Rollback To Saved Point
Context,预编译模式,DryRun 模式
批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询
复合主键,索引,约束
Auto Migration
自定义 Logger
灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
每个特性都经过了测试的重重考验
开发者友好
1.2安装
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
go get -u gorm.io/driver/mysql
2.使用
在项目内创建model文件夹里创建model go文件
package model
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// 用户表
type User struct {
gorm.Model //系统自带的一个模型
Name string `gorm:"type:varchar(20);not null"` // 三个约束类型意思都差不多
Mobile string `gorm:"varchar(11);not null;unique"` //unique 唯一性
Password string `gorm:"size:255;not null"`
Tscore int //整形
Tmoney float32 //浮点型
}
var DB *gorm.DB
func InitDB() *gorm.DB {
dsn := "root:数据库密码@tcp(127.0.0.1:3306)/数据库名?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) //使用mysq连接数据库,第二个参数可以增加更多的配置(可有可无)
if err != nil {
fmt.Println(err)
}
db.AutoMigrate(&User{}) //创建表?判断是否表结构存在
DB = db
return db
}
func GetDb() *gorm.DB {
return DB
}
gorm.Model模型定义
下面这个模型是系统自带的一个模型, 包含的字段有 ID,CreatedAt, UpdatedAt, DeletedAt。
Time是time包里的一个结构体
在go运行文件里编写
type Model struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt DeletedAt `gorm:"index"`
}
在go运行文件里编写连捏数据库
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"p10_2/src/model"
)
func main() {
model.InitDB() //导入model里定义的链接数据库
// 1.创建路由
r := gin.Default()
userpath := r.Group("") //添加前缀
User(userpath)
// 3.监听端口,默认在8080
// Run("里面不指定端口号默认为8080")
r.Run(":8000")
}
运行会自动生成表 注:数据库要自行创建
表名会自动在后边加一个s
例如 上边写的表名是user 创建后数据库中的表名是users
添加数据
func addUser2(c *gin.Context) {
addu := &model.User{ //根据结构体插入数据
Name: "zs",
Mobile: "15936821111",
Password: "aaa",
Tscore: 20,
Tmoney: 20.2,
}
//向数据库中插入数据 ,它的返回值只有一个类型,没有error类型
res := model.GetDb().Create(addu)
//注:如果上面写成stu := Student{...},则这里写成Create(&addu)
if res.Error != nil {
fmt.Println(res.Error)
}
c.JSON(200, gin.H{
"code": 200,
"msg": "添加成功",
})
}
接收参数插入
func addUser2(c *gin.Context) {
addu := &model.User{}
_ = c.Bind(addu)
//向数据库中插入数据 ,它的返回值只有一个类型,没有error类型
res := model.GetDb().Create(addu)
//注:如果上面写成stu := Student{...},则这里写成Create(&addu)
if res.Error != nil {
fmt.Println(res.Error)
c.JSON(400, gin.H{
"code": 400,
"msg": "添加失败",
"type": res.Error,
})
return
}
c.JSON(200, gin.H{
"code": 200,
"msg": "添加成功",
})
}
查询数据
var student Student
//查询First查询一条
conn.First(&student)
fmt.Println(student)
fmt.Println(student.Id)
//条件查询
conn.First(&student, "name=? and id=?", "yang", 1)
fmt.Println(student)
//查询所有 Find
var stu []Student
conn.Table("students").Find(&stu)
for _, v := range stu {
fmt.Println(v.Name)
}
// IN
var students []Student
conn.Table("students").Where("name IN ?", []string{"abc", "bili"}).Find(&students)
fmt.Println(students)
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// Time
db.Where("updated_at > ?", time.Date(2022,05,20,0,0,0,0,&time.Location{})).Find(&users)
// BETWEEN
db.Where("created_at BETWEEN ? AND ?", time.Date(2022,05,20,0,0,0,0,&time.Location{}), time.Now()).Find(&users)
查询First查询一条
func getuser(c *gin.Context) {
// users := model.User{} //另一种方法
var users model.User
model.GetDb().First(&users)
c.JSON(200, gin.H{
"msg": "获取成功",
"data": users,
"id": users.ID,
})
}
条件查询
func gteuser2(c *gin.Context) {
users := model.User{}
model.GetDb().First(&users, "name=? and id=?", "asd", 6)
fmt.Println("ssssssss", users)
if users.ID == 0 {
c.JSON(400, gin.H{
"msg": "没有此人",
})
return
}
c.JSON(200, gin.H{
"msg": "查询成功",
"data": users,
})
}
查询所有 Find
func getall(c *gin.Context) {
//var userall []model.User //另一种方法
userall := []model.User{}
model.GetDb().Table("users").Find(&userall)
for _, v := range userall {
fmt.Println(v.Name)
}
c.JSON(200, gin.H{
"msg": "获取成功",
"data": userall,
})
}
逻辑查询
func getuser3(c *gin.Context) {
//var userall []model.User //另一种方法
users := []model.User{}
model.GetDb().Where("name IN ?", []string{"zs", "asd"}).Find(&users)
c.JSON(200, gin.H{
"msg": "获取成功",
"data": users,
})
}
更新数据
//第一种
model.GetDb().Table("users").Where("id=?", 1).Update("name", "zs3")
//第二种
model.GetDb().Table("users").Where("id=?", 1).Updates(&model.User{Name: "zsd"})
//第三种
users := model.User{}
model.GetDb().First(&users, "id=?", 6)
users.Name = "ass"
model.GetDb().Save(&users)
//第四种
model.GetDb().Table("users").Where("id=?", 1).Updates(map