diff --git a/book/v1/main.go b/book/v1/main.go index fc55369..20bae3d 100644 --- a/book/v1/main.go +++ b/book/v1/main.go @@ -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) diff --git a/docs/gateway_arch.drawio b/docs/gateway_arch.drawio index ef9d664..1d1dd74 100644 --- a/docs/gateway_arch.drawio +++ b/docs/gateway_arch.drawio @@ -1,6 +1,6 @@ - + @@ -39,18 +39,48 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/go.mod b/go.mod index 90457cd..3330caa 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index 7f08abb..1b0844c 100644 --- a/go.sum +++ b/go.sum @@ -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=