🐌 前提
分别学习完GIN、GORM后,下一步我们学习GIN和GORM的整合。我们接下来将实现http接口对外提供书籍的增删改查功能。
1、新建go project。
2、命令行执行go mod init
,模块下载执行go mod tidy
。
3、新建handler、book目录。
4、下面我给出我的目录结构。
x:xxxWEB-API
│ go.mod
│ go.sum
│ main.go
│
├─.idea
│ misc.xml
│ modules.xml
│ web-api.iml
│ workspace.xml
│
├─book
│ entity.go
│ input.go
│ repository.go
│ request.go
│ service.go
│
└─handler
book.go
🐉 结构说明
在本例中我们可以看到:
-
main.go:程序主函数,是程序的入口。
-
handler:存放各个实体类的controllor。
-
book.go:接收book相关请求和参数,传递请求参数给service层进行逻辑处理,并且接收结果封装返回。
-
book:存放book相关,如:book实体类、dao、请求实体类、返回Vo类、service。
-
entity.go:实体类,对应数据库表。结构属性对应数据库表字段。
-
input.go:封装请求处理结果返回,类似Vo类,这里我们没有再进行封装。
-
repository:类似dao层,封装了程序对book表的原子操作。
-
service:上承handler,下接repository,主要业务处理都在这里。
-
request.go:表单请求绑定实体。类似requestbody。
-
go.mod&go.sum:go mod的配置相关。
🐇 方法梳理
下面以createBook功能为例,梳理请求扭转逻辑。
请求调用:main.go->handler.go-request.go->service.go->repository.go-entity.go
返回:repository.go->service.go->handler.go-input.go->main.go
-
main.go
v1.POST("/createBook", bookHandler.CreateBookHandler)
-
handler:book.go
func (h Handler)CreateBookHandler(c *gin.Context){
......
book, err := h.service.Create(requestBook)
......
}
-
service.go
func (service *service) Create(requestBook RequestBook) (Book, error){
......
bookRes, err := service.repository.Create(book)
......
}
-
repository.go
func (r *repository) Create(book Book) (Book, error){
err := r.db.Debug().Create(&book).Error
return book, err
}
由上述代码我们可以看出代码之间是相互调用一层扣一层。
🐛 show me the code
-
main.go
package main
import (
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
"web-api/book"
"web-api/handler"
)
func main(){
// 数据库连接更换成自己的
dsn := "user:password@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{
log.Fatal("Database connect error!")
}
// 数据库迁移
db.AutoMigrate(&book.Book{})
// Repository向外提供服务
bookRepository := book.NewRepository(db)
// Service向外提供服务
bookService := book.NewService(bookRepository)
// Handler向外提供服务
bookHandler := handler.NewHandler(bookService)
router := gin.Default()
// 路由组
v1 := router.Group("/v1")
// 请求入口
v1.POST("/createBook", bookHandler.CreateBookHandler)
router.Run(":8888")
}
-
repository.go
package book
import (
"gorm.io/gorm"
)
type Repository interface {
Create(book Book) (Book, error)
}
type repository struct {
db *gorm.DB
}
func NewRepository(db *gorm.DB) *repository{
return &repository{db}
}
// 新建书记录
func (r *repository) Create(book Book) (Book, error){
err := r.db.Debug().Create(&book).Error
return book, err
}
-
service.go
package book
import "fmt"
type Sercice interface {
Create(book RequestBook) (Book, error)
}
type service struct {
repository Repository
}
func NewService(repository Repository) *service{
return &service{repository}
}
// // 新建书服务
func (service *service) Create(requestBook RequestBook) (Book, error){
price, _ := requestBook.Price.Int64()
rate, _ := requestBook.Rating.Int64()
book := Book{
Description: requestBook.Description,
Price: int(price),
Rating: int(rate),
Title: requestBook.Title,
}
bookRes, err := service.repository.Create(book)
if err != nil {
fmt.Println("========================")
fmt.Println("Create Book record error")
fmt.Println("========================")
}
return bookRes, err
}
-
handler:book.go
package handler
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"net/http"
"web-api/book"
)
func NewHandler(sercice book.Sercice) *Handler{
return &Handler{sercice}
}
type Handler struct {
service book.Sercice
}
// 新建书handler
func (h Handler)CreateBookHandler(c *gin.Context){
var requestBook book.RequestBook
err := c.ShouldBindJSON(&requestBook)
if err != nil {
errMessages := []string{}
for _, e := range err.(validator.ValidationErrors){
errMessage := fmt.Sprintf("Error on field %s, condition: %s", e.Field(),e.ActualTag())
errMessages = append(errMessages, errMessage)
}
c.JSON(http.StatusBadRequest, gin.H{
"errors": errMessages,
})
return
}
book, err := h.service.Create(requestBook)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"error": err,
})
return
}
c.JSON(http.StatusOK, gin.H{
"data": book,
})
}
整体编码格式是,NewXXX函数(供外部调用)返回封装结构体。XXXXX interface内为接口函数,repository实现了Repository,他们之间的关系我理解为Java中的上转型对象。XXXXX struct实现函数(即方法供外部调用),结构体内为下层对象。
🐳 接口测试
postman接口请求截图:
可以看到postman调用请求插入数据成功!到这里gin和gorm整合使用就完成了!
📢📢📢欢迎大家在公众号后台留言交流学习!!!📢📢📢
原文始发于微信公众号(fairy with you):gin-gorm框架整合
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/29662.html