go从0到1项目实战体系三十:演示案列实例二

(1). BsyErp\Contract\main.go:

package main
import (
	"Contract.bsybx.com/App/Lib"
	"Contract.bsybx.com/App/Services"
	"Contract.bsybx.com/Init"
)
func main () {
	router := gin.Default()
	v1 := router.Group("/v1")
	{
    	// 获取book列表
		v1.Handle(Init.HTTP_METHOD_GET, "/books", Lib.RegisterHandler(
			Services.CreateBookListRequest(),
			Services.BookListEndPoint(&Services.BookService{}),
			Services.CreateBookListResponse(),
    	))
    	// 获取book详情
		v1.Handle(Init.HTTP_METHOD_GET, "/book/:id", Lib.RegisterHandler(
			Services.CreateBookDetailRequest(),
			Services.BookDetailEndPoint(&Services.BookService{}),
			Services.CreateBookDetailResponse(),
		))
	}
	router.Run(Init.SERVER_ADDRESS)
}

(2). bookModel(BsyErp\Contract\Models\Books.go):

package Models
// 单实体
type Books struct{
	BookID int `gorm:"column:book_id;AUTO_INCREMENT;PRIMARY_KEY"`
	BookName string `gorm:"column:book_name;type:varchar(50)"`
	BookIntr string `gorm:"column:book_intr;type:text"`
	BookPrice float64 `gorm:"column:book_price;type:decimal"`
	BookKind int `gorm:"column:book_kind;type:int"`
}
// 列表
type BooksList []*Books

注:. 属性名有规范,字段名就不一定有规范.

(4). BsyErp\Contract\App\Services\BookEndpoint.go:

package Services
import (
	"Contract.bsybx.com/App/Lib"
	"Contract.bsybx.com/Models"
	"context"
)
// v1/books?page=1&size=1
type BookListRequest struct { // 请求参数
	Page int  `form:"page"`
	Size int `form:"size"`
}
type BookListResponse struct { // 响应参数
	Result *Models.BooksList `json:"ResultData"` // 返回一个切片
}
// v1/book/12
type BookDetailRequest struct {
	// max可以做预估判断
	BookID int `uri:"id" binding:"required,gt=0,max=1000000"`
}
type BookDetailResponse struct {
	Result *Models.Books `json:"ResultData"` // 返回一个struct
}
func BookListEndPoint(book *BookService)  Lib.Endpoint {
   return func(ctx context.Context, request interface{}) (response interface{}, err error) {
	   req := request.(*BookListRequest)
	   return &BookListResponse{Result:book.BookList(req)}, nil
   }
}
func BookDetailEndPoint(book *BookService) Lib.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(*BookDetailRequest)
		return &BookDetailResponse{Result:book.BookDetail(req)}, nil
	}
}:. 单从上面两个EndPoint方法来看,是冗余的,有优化空间.但是加上缓存后,业务逻辑是不一样的.

(5). BsyErp\Contract\App\Services\BookService.go:

package book
import (
	"api.employee.com/Init"
	"api.employee.com/Models"
)

type BookService struct {
}
// 这是上次struct的方法(类似一个类的方法),在通用模型中是识别不了类方法的.
// 通用模型中的业务最终函数,是一个函数,并不是某个具体的struct或struct具体的方法,否则又耦合了.
func(this *BookService) getList(req *BookListRequest) *Models.AdminLoges {
	// 如果这里不写&,在下面Find那里传&books
	books := &Models.AdminLoges{}
	// 请求多少条,是从req参数中获取的size,至于size怎么去取,与这个类没有任何关系,代码就结耦了
	Init.GetDB().Limit(req.Size).Order("id desc").Find(books)
	return books
}

func(this *BookService) getDetail(req *BookDetailRequest) *Models.AdminLogs {
	book := &Models.AdminLogs{}
	Init.GetDB().Find(book, req.Id)
	return book
}

(6). BsyErp\Contract\App\Services\BookTransport.go:

package Services
import (
	"Contract.bsybx.com/App/Lib"
)
func CreateBookListRequest() Lib.EncodeRequestFunc {
	return func(context *gin.Context) (i interface{}, e error) {
		req := &BookListRequest{}
		// 和框架有关系了,获取一个get参数,并且绑定到BookListRequest上,会去寻找这个BookListRequest struct中是否有size。如果有绑定,否则出错。
		err := context.BindQuery(req)
		fmt.Println(req)
		if err != nil{
			return nil, err
		}
		return req, nil
	}
}
func CreateBookListResponse() Lib.DecodeResponseFunc  {
	return func(context *gin.Context, i interface{}) error {
		res := i.(*BookListResponse)       // 取出BookListResponse,后再断言
		context.JSON(200, res)
		return nil
	}
}
func CreateBookDetailRequest() Lib.EncodeRequestFunc {
	return func(context *gin.Context) (interface{}, error) {
		req := &BookDetailRequest{}
		// 优化把err合并为一句
		if err := context.ShouldBindUri(req); err != nil {
			return nil, err
		}
		return req, nil
	}
}
func CreateBookDetailResponse() Lib.DecodeResponseFunc {
	return func(context *gin.Context, i interface{}) error {
		res := i.(*BookDetailResponse)
		context.JSON(200, res)
		return nil
	}
}:. 两个Response都是差不多逻辑,可以优化为:
   func CreateBookResponse() Lib.DecodeResponseFunc {
     return func(context *gin.Context, res interface{}) error {
       context.JSON(200, res)
       return nil
     }
   }

(7). 请求访问:

①. 列表:
   GET http://localhost/v1/books?page=1&size=1

②. 详情:
   GET http://localhost/v1/book/200

你可能感兴趣的:(golang,开发语言,后端,go,gin,性能优化,系统架构)