补充Tag

This commit is contained in:
yumaojun03 2025-04-26 17:02:34 +08:00
parent 9bb1b327ad
commit 79ad21efd0
4 changed files with 209 additions and 82 deletions

View File

@ -6,10 +6,157 @@ import (
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type Book struct {
Title string `json:"title"`
// 对象Id
ID uint `json:"id" gorm:"primaryKey;column:id"`
// type 用于要使用gorm 来自动创建和更新表的时候 才需要定义
Title string `json:"title" gorm:"column:title;type:varchar(200)" validate:"required"`
Author string `json:"author" gorm:"column:author;type:varchar(200);index" validate:"required"`
Price float64 `json:"price" gorm:"column:price" validate:"required"`
// bool false
// nil 是零值, false
IsSale *bool `json:"is_sale" gorm:"column:is_sale"`
}
// books
func (b *Book) TableName() string {
return "books"
}
// 初始化数据库
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
}
var db = setupDatabase()
var h = &BookApiHandler{}
type BookApiHandler struct {
}
// 实现后端分页的
func (h *BookApiHandler) ListBook(ctx *gin.Context) {
// /api/books?page_number=1&page_size=20
pageNumber := ctx.Query("page_number")
pn, err := strconv.ParseInt(pageNumber, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
pageSize := ctx.Query("page_size")
ps, err := strconv.ParseInt(pageSize, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
//
bookList := []Book{}
// select * from books
// 通过sql的offset limte 来实现分页
// offset (page_number -1) * page_size, limit page_size
// 2 offset 20, 20
// 3 offset 40, 20
// 4 offset 3 * 20, 20
offset := (pn - 1) * ps
if err := db.Offset(int(offset)).Limit(int(ps)).Find(&bookList).Error; err != nil {
ctx.JSON(500, gin.H{"code": 500, "message": err.Error()})
return
}
// 获取总数, 总共多少个, 总共有多少页
ctx.JSON(200, bookList)
}
func (h *BookApiHandler) CreateBook(ctx *gin.Context) {
// payload, err := io.ReadAll(ctx.Request.Body)
// if err != nil {
// ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
// return
// }
// defer ctx.Request.Body.Close()
// // {"title": "Go语言"}
// c.Request.Header.Get(key)
// ctx.GetHeader("Authincation")
// new(Book)
bookInstance := &Book{}
// // 通过JSON的 Struct Tag
// // bookInstance.Title = "Go语言"
// if err := json.Unmarshal(payload, bookInstance); err != nil {
// ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
// return
// }
// 获取到bookInstance
if err := ctx.BindJSON(bookInstance); err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
// 数据入库(Grom), 补充自增Id的值
if err := db.Save(bookInstance).Error; err != nil {
ctx.JSON(400, gin.H{"code": 500, "message": err.Error()})
return
}
// 返回响应
ctx.JSON(200, bookInstance)
}
func (h *BookApiHandler) GetBook(ctx *gin.Context) {
// URI
bnStr := ctx.Param("bn")
bn, err := strconv.ParseInt(bnStr, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
fmt.Println(bn)
}
func (h *BookApiHandler) UpdateBook(ctx *gin.Context) {
// URI
bnStr := ctx.Param("bn")
bn, err := strconv.ParseInt(bnStr, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
fmt.Println(bn)
// 读取body里面的参数
bookInstance := &Book{}
// 获取到bookInstance
if err := ctx.BindJSON(bookInstance); err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
}
func (h *BookApiHandler) DeleteBook(ctx *gin.Context) {
// URI
bnStr := ctx.Param("bn")
bn, err := strconv.ParseInt(bnStr, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
fmt.Println(bn)
}
func main() {
@ -17,84 +164,16 @@ func main() {
// Book Restful API
// List of books
server.GET("/api/books", func(ctx *gin.Context) {
// /api/books?page_number=1&page_size=20
// ctx.Query("page_number")
// ctx.Query("page_size")
})
server.GET("/api/books", h.ListBook)
// Create new book
// Body: HTTP Entity
server.POST("/api/books", func(ctx *gin.Context) {
// payload, err := io.ReadAll(ctx.Request.Body)
// if err != nil {
// ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
// return
// }
// defer ctx.Request.Body.Close()
// // {"title": "Go语言"}
bookInstance := &Book{}
// // 通过JSON的 Struct Tag
// // bookInstance.Title = "Go语言"
// if err := json.Unmarshal(payload, bookInstance); err != nil {
// ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
// return
// }
// 获取到bookInstance
if err := ctx.BindJSON(bookInstance); err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
// 数据入库(Grom)
// 返回响应
ctx.JSON(200, bookInstance)
})
server.POST("/api/books", h.CreateBook)
// Get book by book number
server.GET("/api/books/:bn", func(ctx *gin.Context) {
// URI
bnStr := ctx.Param("bn")
bn, err := strconv.ParseInt(bnStr, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
fmt.Println(bn)
})
server.GET("/api/books/:bn", h.GetBook)
// Update book
server.PUT("/api/books/:bn", func(ctx *gin.Context) {
// URI
bnStr := ctx.Param("bn")
bn, err := strconv.ParseInt(bnStr, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
fmt.Println(bn)
// 读取body里面的参数
bookInstance := &Book{}
// 获取到bookInstance
if err := ctx.BindJSON(bookInstance); err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
})
server.PUT("/api/books/:bn", h.UpdateBook)
// Delete book
server.DELETE("/api/books/:bn", func(ctx *gin.Context) {
// URI
bnStr := ctx.Param("bn")
bn, err := strconv.ParseInt(bnStr, 10, 64)
if err != nil {
ctx.JSON(400, gin.H{"code": 400, "message": err.Error()})
return
}
fmt.Println(bn)
})
server.DELETE("/api/books/:bn", h.DeleteBook)
if err := server.Run(":8080"); err != nil {
fmt.Println(err)

View File

@ -1,6 +1,6 @@
<mxfile host="65bd71144e">
<diagram id="_BetgHJPjSULUI-ME64i" name="第 1 页">
<mxGraphModel dx="890" dy="256" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<mxGraphModel dx="890" dy="510" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
@ -39,18 +39,48 @@
<mxCell id="12" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="2" target="3" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="14" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="14" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="180" y="540" width="90" height="30" as="geometry"/>
</mxCell>
<mxCell id="15" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="15" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="280" y="540" width="20" height="30" as="geometry"/>
</mxCell>
<mxCell id="16" value="" style="endArrow=classic;html=1;entryX=1;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" target="14">
<mxCell id="16" value="" style="endArrow=classic;html=1;entryX=1;entryY=0;entryDx=0;entryDy=0;" parent="1" target="14" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="270" y="490" as="sourcePoint"/>
<mxPoint x="290" y="460" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="23" style="edgeStyle=none;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;" edge="1" parent="1" source="17" target="20">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="17" value="Requeststruct)" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="140" y="680" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="19" style="edgeStyle=none;html=1;exitX=1;exitY=0.3333333333333333;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="18" target="17">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="18" value="Actor" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
<mxGeometry x="20" y="660" width="30" height="60" as="geometry"/>
</mxCell>
<mxCell id="25" style="edgeStyle=none;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;" edge="1" parent="1" source="20" target="24">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="20" value="Progress" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="340" y="740" width="170" height="140" as="geometry"/>
</mxCell>
<mxCell id="21" value="Handler" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="354" y="750" width="120" height="30" as="geometry"/>
</mxCell>
<mxCell id="22" value="Controller" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="354" y="840" width="120" height="30" as="geometry"/>
</mxCell>
<mxCell id="26" style="edgeStyle=none;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="24" target="18">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="24" value="Responsestruct)" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="140" y="840" width="120" height="60" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>

11
go.mod
View File

@ -2,7 +2,11 @@ module 122.51.31.227/go-course/go18
go 1.24.1
require github.com/gin-gonic/gin v1.10.0
require (
github.com/gin-gonic/gin v1.10.0
gorm.io/driver/mysql v1.5.7
gorm.io/gorm v1.26.0
)
require (
github.com/bytedance/sonic v1.11.6 // indirect
@ -14,7 +18,10 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
@ -28,7 +35,7 @@ require (
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/text v0.20.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

15
go.sum
View File

@ -23,11 +23,17 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@ -74,8 +80,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
@ -85,5 +91,10 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.26.0 h1:9lqQVPG5aNNS6AyHdRiwScAVnXHg/L/Srzx55G5fOgs=
gorm.io/gorm v1.26.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=