go17/skills/gin/main.go

142 lines
3.5 KiB
Go
Raw Normal View History

2024-11-16 12:11:19 +08:00
package main
import (
2024-11-16 15:44:25 +08:00
"fmt"
2024-11-16 12:11:19 +08:00
"log"
"net/http"
"github.com/gin-gonic/gin"
2024-11-16 14:57:48 +08:00
"gorm.io/driver/mysql"
"gorm.io/gorm"
2024-11-16 12:11:19 +08:00
)
2024-11-16 14:57:48 +08:00
// 初始化数据库, 能过与数据库交互的 连接池对象: db
func setupDatabase() *gorm.DB {
dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&Book{}) // 自动迁移
return db
}
2024-11-16 15:44:25 +08:00
func Failed(ctx *gin.Context, err error) {
ctx.JSON(http.StatusBadRequest, gin.H{"code": 0, "msg": err.Error()})
}
2024-11-16 14:57:48 +08:00
// 规定好风格: JSON Restful Api
2024-11-16 12:11:19 +08:00
func main() {
// gin Engine, 它包装了http server
server := gin.Default()
2024-11-16 14:57:48 +08:00
db := setupDatabase()
// 配置业务路有, Book类型的资源的 一套简单的CRUD
// 创建Book -> Book
// POST, Body
book := server.Group("/api/books")
book.POST("", func(ctx *gin.Context) {
// 获取Book用户传达的参数
ins := new(Book)
if err := ctx.ShouldBindJSON(ins); err != nil {
2024-11-16 15:44:25 +08:00
Failed(ctx, err)
2024-11-16 14:57:48 +08:00
return
}
// book, save
if err := db.Save(ins).Error; err != nil {
2024-11-16 15:44:25 +08:00
Failed(ctx, err)
2024-11-16 12:11:19 +08:00
return
}
2024-11-16 14:57:48 +08:00
ctx.JSON(http.StatusOK, ins)
})
// 查询Book列表 -> []*Book
book.GET("", func(ctx *gin.Context) {
2024-11-16 15:44:25 +08:00
var books []Book
if err := db.Find(&books).Error; err != nil {
Failed(ctx, err)
return
}
ctx.JSON(http.StatusOK, books)
2024-11-16 14:57:48 +08:00
})
// 查询Book详情
book.GET("/:isbn", func(ctx *gin.Context) {
2024-11-16 15:44:25 +08:00
var ins Book
id := ctx.Param("isbn")
if err := db.Where("isbn = ?", id).Take(&ins).Error; err != nil {
Failed(ctx, fmt.Errorf("Book not found"))
return
}
ctx.JSON(http.StatusOK, ins)
2024-11-16 14:57:48 +08:00
})
// 更新Book
book.PUT("/:isbn", func(ctx *gin.Context) {
2024-11-16 15:44:25 +08:00
id := ctx.Param("isbn")
2024-11-16 14:57:48 +08:00
2024-11-16 15:44:25 +08:00
// 获取用户参数, 读取用户的更新参数
req := BookSpec{}
if err := ctx.ShouldBindJSON(&req); err != nil {
Failed(ctx, err)
return
}
// gorm更新是如果字段为零值 就不更新该字段, is_sale 没办法更新为false
// 如果越到零值,也需要更新,则需要转化为 指针类型
if err := db.Where("isbn = ?", id).Model(&Book{}).Updates(req).Error; err != nil {
Failed(ctx, err)
return
}
// 针对有零值的字段独立更新
// if err := db.Where("isbn = ?", id).Model(&Book{}).Update("is_sale", req.IsSale).Error; err != nil {
// Failed(ctx, err)
// return
// }
// // ......
// 再次查询出来
var ins Book
if err := db.Where("isbn = ?", id).Take(&ins).Error; err != nil {
Failed(ctx, fmt.Errorf("Book not found"))
return
}
2024-11-16 14:57:48 +08:00
2024-11-16 15:44:25 +08:00
// 查询出更新后的数据
ctx.JSON(http.StatusOK, ins)
})
2024-11-16 14:57:48 +08:00
// 删除Book
book.DELETE("/:isbn", func(ctx *gin.Context) {
2024-11-16 15:44:25 +08:00
id := ctx.Param("isbn")
if err := db.Where("isbn = ?", id).Delete(&Book{}).Error; err != nil {
Failed(ctx, err)
return
}
2024-11-16 12:11:19 +08:00
})
if err := server.Run("127.0.0.1:8080"); err != nil {
log.Println(err)
}
}
2024-11-16 14:57:48 +08:00
// Book 结构体定义
2024-11-16 12:11:19 +08:00
type Book struct {
2024-11-16 14:57:48 +08:00
// grom:"column:isbn;", 具体文档: https://gorm.io/docs/models.html#Fields-Tags
2024-11-16 15:44:25 +08:00
IsBN uint `json:"isbn" gorm:"primaryKey;column:isbn"`
BookSpec
}
type BookSpec struct {
2024-11-16 14:57:48 +08:00
Title string `json:"title" gorm:"column:title;type:varchar(200)"`
Author string `json:"author" gorm:"column:author;type:varchar(200);index"`
Price float64 `json:"price" gorm:"column:price"`
2024-11-16 15:44:25 +08:00
// bool false
// nil 是零值, false
IsSale *bool `json:"is_sale" gorm:"column:is_sale"`
2024-11-16 14:57:48 +08:00
}
// 定义该对象映射到数据里 表的名称
func (t *Book) TableName() string {
return "books"
2024-11-16 12:11:19 +08:00
}