package controller import ( "context" "fmt" "github.com/rs/zerolog" "gitlab.com/go-course-project/go17/book/config" "gitlab.com/go-course-project/go17/book/exception" "gitlab.com/go-course-project/go17/book/model" "gorm.io/gorm" ) // 构造函数, 用户初始化这个结构体 func NewBookController() *BookController { return &BookController{ db: config.Get().MySQL.DB(), logger: config.Get().Log.Logger(), } } type BookController struct { db *gorm.DB logger *zerolog.Logger } type GetBookRequest struct { Isbn int64 // ... // TraceId string } // 怎么定义你的Controller的参数 // 怎么定义你BookController的接口(interface) // 函数名称 + 参数 + 返回 + 异常 // 参数 一定要 注意 兼容性 // 1.参数类型,个数 // 怎么设计一个 具有良好兼容性的接口, 个数,类型 // 采用一个请求类型 作为参数, 变更请求结构体, 不会变更类型,有更好的兼容性 // 1. 非功能性的需求, 要添加TraceID, 请求支持取消 // go context.Context 既能存储数据,也能做Gorouteine的取消 // 这个跟接口是无关的,是纯业务处理 func (c *BookController) GetBook(ctx context.Context, req *GetBookRequest) (*model.Book, error) { ins := &model.Book{} if err := c.db.WithContext(ctx).Where("isbn = ?", req.Isbn).Take(ins).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, exception.ErrNotFound("%d not found", req.Isbn) } return nil, fmt.Errorf("get book error, %s", err) } return ins, nil } // 这一层做强教育,避免内部相互调用是,处理未校验的情况 func (c *BookController) CreateBook(ctx context.Context, req *model.BookSpec) (*model.Book, error) { if err := req.Validate(); err != nil { return nil, err } // req 请求信息 // 1. fmt.Println(req) // log.Println() // 2. zerolog c.logger.Debug().Msgf("req 请求信息: %s", req) // book, save ins := &model.Book{ BookSpec: *req, } if err := c.db.Save(ins).Error; err != nil { return nil, err } return ins, nil }