go从0到1项目实战体系二十七:三层架构模式介绍

1. 前言:

. 三层架构模式,并不是MVC,在go-kit中也有使用了.
    a. 功能比较简单的项目可以不使用这种模式.
	b. 适合项目移植.. 考虑到可扩展性:
    a. 整个业务代码写完后,框架都变化了,使用其它的框架,需要快速修改和切换.
    b. 需要有一定的模式.
    c. 有了一定的架构后,代码基本上不用变,只要改相关的接口部分.
    d. gin web框架的代码,如果换成微服务框架grpc,使用proto文件生成对应的文件,移植起来比较方便.

2. 业务解耦:

v1.Handle("GET", "/prods", func(context *gin.Context) {
	// result := []*Models.Books{}
	// 另一种写法:如果加了*指针,下面就不用加&
    result := Models.BookList{}
    Init.GetDB().Limit(10).Order("book_id desc").Find(&result)
    context.JSON(http.StatusOK, result)
}):. Handle的第三个参数,这个函数最终是要返回一个func,只要有context *gin.Context这个参数就可以(v1才能识别).
    => 关键是要返回一个func(context *gin.Context). 如果有参数,怎么获取?
    => 参数包括url形式的、form形式的、json形式的.. result := Models.BookList{}
    Init.GetDB().Limit(10).Order("book_id desc").Find(&result)
    => 这两句代码用面向对象来讲就是属于哪一个类的方法,属于哪个struct.. result获取出来了,一定是用json返回吗?是否还有其它方式,并不仅仅是输出字符串.. 以上都需要相关机制来控制的,并不是直接在函数中写死.

3. 通用模型:

func RegisterHandler(怎么取参数, 业务最终函数, 怎么处理业务结果) func(context *gin.Context) {
  return func(context *gin.Context) {
    // 参数到底是url、form、json的?是否需要做验证?也不一定会有参数.
	1. 参数 := 怎么取参数()
	
    // 到底怎么取?取什么?比如在数据库中取值.
	2. 业务结果 := 业务最终函数(context, 参数)
	
    // 执行完成了返回什么?返回json只是一种方式,保存文件也是一种方式.
    3. 怎么处理业务结果(业务结果)
  }
}:. 3个形参都是函数,最终只要返回一个context *gin.Context的func,v1路由就能识别.. 为了和业务进行解耦,3个函数不能写死,是一个通用的.并不是某个产品、订单的函数.. 约定所有使用到对象都使用指针.      => 为了统一规范.. 不过过渡依赖gin的封装的便捷方法.   => 尽量与框架无关,可移值性比较高的方式.

(1). BsyErp\Contract\App\Lib\ServiceHelper.go:

package Lib
import (
	"context"
	"net/http"
)

// 怎么取参数
// 为了兼容不同的业务,统一使用interface,而不使用业务的struct
type EncodeRequestFunc func(*gin.Context) (interface{}, error)
// 业务最终函数,request是参数
// 业务结果 := 业务最终函数(参数)
type Endpoint func(ctx context.Context, request interface{}) (response interface{}, err error)
// 怎么处理响应
type DecodeResponseFunc func(*gin.Context, interface{}) error

func RegisterHandler(encodeFunc EncodeRequestFunc, endpoint Endpoint, decodeFunc DecodeResponseFunc) func(context *gin.Context) {
	return func(ctx *gin.Context) {
		// 获取参数
		req, err := encodeFunc(ctx)
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{"ServerNo": "SN500", "ResultData": "参数错误:" + err.Error()})
			return
		}
		// 执行业务过程
		res, err := endpoint(ctx, req)
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{"ServerNo": "SN500", "ResultData": "执行错误:" + err.Error()})
			return
		}
		// 处理业务执行结果
		err = decodeFunc(ctx, res)
		if err != nil {
			ctx.JSON(http.StatusInternalServerError, gin.H{"ServerNo": "SN500", "ResultData": "返回错误:" + err.Error()})
		}
	}
}:. 三个参数都是函数类型,传入函数,最终执行函数.

你可能感兴趣的:(go,微服务,系统架构,gin)