146 lines
3.5 KiB
Go
146 lines
3.5 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
"net/http"
|
||
"os"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"gitlab.com/go-course-project/go17/book/config"
|
||
)
|
||
|
||
func Failed(ctx *gin.Context, err error) {
|
||
ctx.JSON(http.StatusBadRequest, gin.H{"code": 0, "msg": err.Error()})
|
||
}
|
||
|
||
// 规定好风格: JSON Restful Api
|
||
func main() {
|
||
// 从配置文件中加载配置
|
||
// 加载配置
|
||
path := os.Getenv("CONFIG_PATH")
|
||
if path == "" {
|
||
path = "application.yaml"
|
||
}
|
||
if err := config.LoadConfigFromYaml(path); err != nil {
|
||
fmt.Printf("加载配置错误: %s\n", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
// 访问加载后的配置
|
||
conf := config.Get()
|
||
|
||
// gin Engine, 它包装了http server
|
||
server := gin.Default()
|
||
|
||
db := conf.MySQL.DB()
|
||
// 配置业务路有, 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 {
|
||
Failed(ctx, err)
|
||
return
|
||
}
|
||
|
||
// book, save
|
||
if err := db.Save(ins).Error; err != nil {
|
||
Failed(ctx, err)
|
||
return
|
||
}
|
||
|
||
ctx.JSON(http.StatusOK, ins)
|
||
})
|
||
// 查询Book列表 -> []*Book
|
||
// SELECT * FROM `books`
|
||
book.GET("", func(ctx *gin.Context) {
|
||
var books []Book
|
||
if err := db.Find(&books).Error; err != nil {
|
||
Failed(ctx, err)
|
||
return
|
||
}
|
||
ctx.JSON(http.StatusOK, books)
|
||
})
|
||
// 查询Book详情
|
||
book.GET("/:isbn", func(ctx *gin.Context) {
|
||
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)
|
||
})
|
||
// 更新Book
|
||
book.PUT("/:isbn", func(ctx *gin.Context) {
|
||
id := ctx.Param("isbn")
|
||
|
||
// 获取用户参数, 读取用户的更新参数
|
||
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
|
||
}
|
||
|
||
// 查询出更新后的数据
|
||
ctx.JSON(http.StatusOK, ins)
|
||
})
|
||
// 删除Book
|
||
book.DELETE("/:isbn", func(ctx *gin.Context) {
|
||
id := ctx.Param("isbn")
|
||
if err := db.Where("isbn = ?", id).Delete(&Book{}).Error; err != nil {
|
||
Failed(ctx, err)
|
||
return
|
||
}
|
||
})
|
||
|
||
if err := server.Run(conf.App.Address()); err != nil {
|
||
log.Println(err)
|
||
}
|
||
}
|
||
|
||
// Book 结构体定义
|
||
type Book struct {
|
||
// grom:"column:isbn;", 具体文档: https://gorm.io/docs/models.html#Fields-Tags
|
||
IsBN uint `json:"isbn" gorm:"primaryKey;column:isbn"`
|
||
BookSpec
|
||
}
|
||
|
||
type BookSpec struct {
|
||
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"`
|
||
// bool false
|
||
// nil 是零值, false
|
||
IsSale *bool `json:"is_sale" gorm:"column:is_sale"`
|
||
}
|
||
|
||
// 定义该对象映射到数据里 表的名称
|
||
func (t *Book) TableName() string {
|
||
return "books"
|
||
}
|