go从0到1项目实战体系二十八:三层模型架构文件结构

1. 文件夹结构:

App 
└─ Services
   ├─ BookService.go    业务类(具体业务函数):
   │                    ①. 与架构无关,框架无关性代码.
   │                    ②. 不管是使用什么框架,使用grpc、go-mrico,这些代码是不变的.
   │
   ├─ BookEndpoint.go   Request和Response定义:
   │                    ①. 跟架构没有太大关系.
   │                    ②. 除了手工定义外,还可以通过proto文件自动生成(grpc).
   |. 专门存放request和response的定义(只是定义,下面是具体的操作规则).
   |                        a. 如请求参数定义
   |                        b. 业务最终函数定义
   |                           (1). 因为通用模型中的业务最终函数,是一个函数,并不是某个具体的struct或struct具体的方法.
   │
   └─ BookTransport.go  怎么取出参数和怎么处理响应:. 和架构有关系的

约定涉及到的对象一律使用指针.


2. 列表:

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

package main

import (
	. "api.employee.com/Init"
	"api.employee.com/Lib"
	"api.employee.com/Models"
	"api.employee.com/Service/book"
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	v1 := router.Group("/v1")
	{
		bookService := &book.BookService{}
		bookListHandler := Lib.RegisterHandler(book.CreateBookListRequest(),
			book.BookListEndpoint(bookService),
			book.CreateBookListResponse())
		v1.Handle(HTTP_METHOD_GET, "/admin/books", bookListHandler)
	}
	router.Run(SERVER_ADDRESS)
}

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

package Models
// 单实体
type AdminLogs struct {
	Id        int    `json:"id" gorm:"column:book_id;AUTO_INCREMENT;PRIMARY_KEY"`
	UserId    int    `gorm:"column:user_id;type:int"`
	Ip        string `gorm:"column:ip;type:varchar(45)"`
	SayMore   string `gorm:"column:syamore;type:varchar(255)"`
	Type      int    `gorm:"column:type;type:int"`
	CreatedAt string `gorm:"column:created_at;type:varchar(255)"`
	UpdatedAt string `gorm:"column:updated_at;type:varchar(255)"`
}
// 列表
type AdminLoges []*AdminLogs

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

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

package book
import (
	"api.employee.com/Lib"
	"api.employee.com/Models"
	"github.com/gin-gonic/gin"
)
// 定义请求结构体
type BookListRequest struct {
	Size int `form:"size"`
}
// 定义返回结构体
type BookListResponse struct {
	Result *Models.AdminLoges
}
// 业务最终函数
// 目的是把service中的struct的方法的过程,用func来做一层包装
// 为了将最终执行的结果与框架进行结耦,确保通用模型中的RegisterHandler与框架、业务无关
func BookListEndpoint(book *BookService) Lib.Endpoint {
	return func(ctx *gin.Context, request interface{}) (interface{}, error) {
		req := request.(*BookListRequest)
		return &BookListResponse{Result: book.getList(req)}, nil
	}
}

(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
}

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

package book
import (
	"api.employee.com/Lib"
	"github.com/gin-gonic/gin"
)
// 返回类型是一个函数,与框架是有关的
func CreateBookListRequest() Lib.EncodeRequestFunc {
	return func(ctx *gin.Context) (i interface{}, e error) {
		req := &BookListRequest{}
		if err := ctx.BindQuery(req); err != nil {
			return nil, err
		}
		return req, nil
	}
}
// 返回类型也是一个函数,与框架是有关的
func CreateBookListResponse() Lib.DecodeResponseFunc {
	return func(cxt *gin.Context, i interface{}) error {
		res := i.(*BookListResponse) // 断言
		cxt.JSON(200, res)
		return nil
	}
}

(7). 请求访问:

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

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