GoLang Web框架Gin
本文最后更新于:2 小时前
网络请求Method
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping/:id", func(c *gin.Context) {
id := c.Param("id")
user := c.DefaultQuery("user", "qiuqian")
password := c.Query("password")
c.JSON(200, gin.H{
"success": "true",
"id": id,
"user": user,
"password": password,
})
})
r.POST("/ping", func(c *gin.Context) {
user := c.DefaultPostForm("user", "aowu")
password := c.PostForm("password")
c.JSON(200, gin.H{
"success": "true",
"user": user,
"password": password,
})
})
r.DELETE("/ping/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(200, gin.H{
"success": "true",
"id": id,
})
})
r.PUT("/ping", func(c *gin.Context) {
user := c.DefaultPostForm("user", "aowu")
password := c.PostForm("password")
c.JSON(200, gin.H{
"success": "true",
"user": user,
"password": password,
})
})
r.Run(":8088")
}
Bind
package main
import "github.com/gin-gonic/gin"
type PostParams struct {
Name string `json:"name" uri:"name" form:"name"`
Gender bool `json:"gender" uri:"gender" form:"gender"`
Age int `json:"age" uri:"age" form:"age"`
}
func main() {
r := gin.Default()
r.POST("/testBind", func(c *gin.Context) {
var p PostParams
// 这里修改传参方式
err := c.ShouldBindQuery(&p)
if err != nil {
c.JSON(200, gin.H{
"msg": "报错了",
"data": gin.H{},
})
} else {
c.JSON(200, gin.H{
"msg": "success",
"data": p,
})
}
})
r.Run(":8088")
}
binding
必须有参数,否则报错
package main
import "github.com/gin-gonic/gin"
type PostParams struct {
Name string `json:"name" binding:"required"`
Gender bool `json:"gender" binding:"required"`
Age int `json:"age" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("/testBind", func(c *gin.Context) {
var p PostParams
// 这里修改传参方式
err := c.ShouldBindJSON(&p)
if err != nil {
c.JSON(200, gin.H{
"msg": "报错了",
"data": gin.H{},
})
} else {
c.JSON(200, gin.H{
"msg": "success",
"data": p,
})
}
})
r.Run(":8088")
}
自定义校验: age must > 18
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
)
type PostParams struct {
Name string `json:"name"`
Gender bool `json:"gender"`
// binging里面的用逗号分割,不可以加空格!!
Age int `json:"age" binding:"required,mustBig"`
}
// 自定义校验
func mustBig(fl validator.FieldLevel) bool {
fmt.Println(fl.Field().Interface().(int))
if fl.Field().Interface().(int) <= 18 {
return false
}
return true
}
func main() {
r := gin.Default()
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("mustBig", mustBig)
}
r.POST("/testBind", func(c *gin.Context) {
var p PostParams
// 这里修改传参方式
err := c.ShouldBindJSON(&p)
if err != nil {
fmt.Println(err.Error())
c.JSON(200, gin.H{
"msg": "报错了",
"data": gin.H{},
})
} else {
c.JSON(200, gin.H{
"msg": "success",
"data": p,
})
}
})
r.Run(":8088")
}
中间件和路由分组
洋葱模型 鉴权 日志等
中间件: 请求达到路由放大前,后的一系列操作,有点类似 Spring 的面向切面编程
package main
import (
"fmt"
"github.com/gin-gonic/gin"
)
func middle() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println("我在方法前1...")
c.Next()
fmt.Println("我在方法后1...")
}
}
func middle2() gin.HandlerFunc {
return func(c *gin.Context) {
fmt.Println("我在方法前2...")
c.Next()
fmt.Println("我在方法后2...")
}
}
func main() {
r := gin.Default()
// 路由分组 中间件
v1 := r.Group("v1").Use(middle(), middle2())
v1.GET("group", func(c *gin.Context) {
fmt.Println("我在方法内部...")
c.JSON(200, gin.H{
"success": true,
})
})
r.Run(":8088")
}
/** 请求结果
我在方法前1...
我在方法前2...
我在方法内部...
我在方法后2...
我在方法后1...
**/
GORM
创建链接
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
dsn := "username:pwd@tcp(ip:port)/dbName?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open("mysql", dsn)
if err != nil {
panic(err)
}
// 关闭db
defer db.Close()
}
自动迁移
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type HelloWorld struct {
/** 自动创建基础结构
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
*/
gorm.Model
Name string
Gender bool
Age int
}
func main() {
dsn := "username:pwd@tcp(ip:port)/dbName?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open("mysql", dsn)
if err != nil {
panic(err)
}
// 自动迁移,查看是否有表,没有会自动创建
db.AutoMigrate(&HelloWorld{})
defer db.Close()
}
CRUD
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type HelloWorld struct {
/** 自动创建基础结构
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
*/
gorm.Model
Name string
Gender bool
Age int
}
func main() {
dsn := "username:pwd@tcp(ip:port)/dbName?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open("mysql", dsn)
if err != nil {
panic(err)
}
// 自动迁移,查看是否有表,没有会自动创建
db.AutoMigrate(&HelloWorld{})
// 创建数据
//db.Create(&HelloWorld{
// Name: "ysml",
// Gender: true,
// Age: 25,
//})
// 查
// hello 用于接收
//var hello HelloWorld
//db.First(&hello, "name = ?", "aowu")
//db.Find(&hello, "age >= ?", "20")
// 条件写前面最常用
// Or 可以写进SQL语句也可以在后面显示编写
//db.Where("age > ?", "20").Or("name = ?", "qiuqian").Find(&hello)
//fmt.Println(hello)
// 改
//db.Where("name = ?", "qiuqian").First(&HelloWorld{}).Update("name", "qiuqian123")
//fmt.Println(hello)
// map批量修改
//db.Where("id in (?)", []int{2, 3}).Find(&[]HelloWorld{}).Updates(map[string]interface{}{
// "Name": "updated",
// "Gender": true,
// "Age": 22,
//})
// 删
// 软删除
db.Where("id in (?)", []int{1, 2}).Delete(&HelloWorld{})
// 物理删除
//db.Where("id in (?)", []int{1, 2}).Unscoped().Delete(&HelloWorld{})
defer db.Close()
}
创建
func CreatUsers() int {
// 批量创建
res := global.DBEngine.Create(&[]model.User{
{Name: "yz1", Age: 17},
{Name: "yz2", Age: 18},
{Name: "yz3", Age: 19},
{Name: "yzz", Age: 20},
})
if res.Error != nil {
fmt.Println("创建失败")
return utils.ERROR
} else {
fmt.Println("创建成功")
return utils.SUCCESS
}
}
查询
模型
携带了 gorm 规定的标签或实现了接口的一种结构体,书写良好的模型可以增加gorm的操作效率
嵌入结构体,会自动创建 id created_at updated_at deleted_at 列名
package model
import "gorm.io/gorm"
type User struct {
// 嵌入结构体,会自动创建 id created_at updated_at deleted_at 列名
gorm.Model
Username string `json:"username"`
Password string `json:"password"`
}
也可以自定义
以 Model 匿名结构放进 User 结构体后,整个字段都会被继承
package model
import (
"time"
)
type Model struct {
UUID uint `gorm:"primaryKey"`
// 重命名列名
Time time.Time `gorm:"column:my_time"`
}
type User struct {
Model Model `gorm:"embedded;embeddedPrefix:prefix_"` // 前缀
Username string `gorm:"not null;default:qiuqian;comment:密码"`
Password string
}
JWT
package main
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"time"
)
type MyClaims struct {
Username string `json:"username"`
jwt.StandardClaims
}
func main() {
// 下面是签发
mySignedStringKey := []byte("qiuqianaowu")
// 结构体的方式
c := MyClaims{
Username: "qiuqian",
StandardClaims: jwt.StandardClaims{
// 生效时间
NotBefore: time.Now().Unix() - 60,
// 失效时间 2h
ExpiresAt: time.Now().Unix() + 60*60*2,
// 签发者
Issuer: "qiuqian",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
// 对 token 加密
sign, err := token.SignedString(mySignedStringKey)
if err != nil {
fmt.Println("%s", err)
}
fmt.Println(sign)
// 下面是解密
t, e := jwt.ParseWithClaims(sign, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
return mySignedStringKey, nil
})
if e != nil {
fmt.Println("%s", e)
}
// 在这里取出
fmt.Println(t.Claims.(*MyClaims).Username)
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!