一、由于以前的代码是通过pb来传输数据的,大体流程是:前端—>后端的接口–>后端再请求pb服务接口。示例代码如下:
1.接收前端参数
// @Summary LTV趋势
// @Description LTV趋势
// @Tags 投放数据/LTV数据
// @Accept application/json
// @Product application/json
// @Param data body dass.GetLtvDataListRequest true "body"
// @Success 200 {string} string "{"code": 200, "message": "success"}"
// @Router /api/v1/custom/finance/financedata/ltv/list [post]
// @Security Bearer
func GetLtvDataList(c *gin.Context) {
request := &pb.GetLtvDataListRequest{}
err := c.ShouldBindBodyWith(&request, binding.JSON)
err = c.ShouldBindBodyWith(&request.Request, binding.JSON)
tools.HasError(err, "", -1)
global.Logger.Debug(request)
if len(request.GetRequest().Games) == 0 {
err = errors.New("游戏不能为空")
tools.HasError(err, "", -1)
}
err = common.CheckGamesPerm(c, &request.GetRequest().Games)
tools.HasError(err, "", -1)
err = common.CheckPlatformsPerm(c, &request.GetRequest().Platforms)
tools.HasError(err, "", -1)
if request.GetRequest().AdChannelId == "" {
err = common.CheckAdChannelIdsPerm(c, &request.GetRequest().AdChannelIds)
tools.HasError(err, "", -1)
}
response, err := dass.GetLtvDataList(request)
tools.HasError(err, "", -1)
app.OK(c, response.List, "success")
}
2.请求 dass.GetLtvDataList()
// 获取LTV数据列表
func GetLtvDataList(request *pb.GetLtvDataListRequest) (response *pb.GetLtvDataListResponse, err error) {
response = rpc.GetLtvDataListRequest(request)
if response == nil {
err = errorDassService
return
}
if response.Code != StatusOk {
return nil, errors.New(response.Msg)
}
return
}
3.请求pb方法 rpc.GetLtvDataListRequest()
//获取LTV数据列表
func GetLtvDataListRequest(request *pb.GetLtvDataListRequest) *pb.GetLtvDataListResponse {
rpcClient := pb.NewFinanceDataApiClient(xrpc.DassConn())
ctx, cancel := context.WithTimeout(context.Background(), DassRpcTimeout)
defer cancel()
response, err := rpcClient.GetLtvDataList(ctx, request)
if err != nil {
global.Logger.Warning("func=grpcSvc_GetLtvDataListRequest&err=%s", err.Error())
return nil
}
return response
}
问题:每个后台走pb的接口都要新建一个2和3的方法,里面的逻辑都是一样的 就造成了代码的的冗余。
改善:前端请求到后端接口之后,我只需要请求一个固定的方法,传对应的参数就可以了 而不需要重复的去写2和3的方法。
具体思路:
(1).把pb的方法列表注册到map里面
(2)请求过来之后把方法的名称,和参数传到CallLogMeth()方法里面
(3)CallLogMeth方法去请求对应的pb方法
用到了,go语言的反射和依赖注入。最开始是打算使用inject/Invoke这个第三方包来实现,但是在调用invoke这个方法的时候会报参数不全最开始的代码如下:
const (
FunctionNotFund = "方法未找到!"
OperationsAppGiftApiClientAddGift = "OperationsAppGiftApiClient.AddGift"
OperationsAppGiftApiClientDeleteGift = "OperationsAppGiftApiClient.DeleteGift"
OperationsAppGiftApiClientGetGiftById = "OperationsAppGiftApiClient.GetGiftById"
OperationsAppGiftApiClientGetGiftList = "OperationsAppGiftApiClient.GetGiftList"
OperationsAppGiftApiClientUpdateGift = "OperationsAppGiftApiClient.UpdateGift"
OperationsAppGiftRecordApiClientGetGiftRecordList = "OperationsAppGiftRecordApiClient.GetGiftRecordList"
OperationsAppGeneralApiClientGetAppGeneralConfInfo = "OperationsAppGeneralApiClient.GetAppGeneralConfInfo"
OperationsAppGeneralApiClientUpdateAppGeneralConf = "OperationsAppGeneralApiClient.UpdateAppGeneralConf"
)
var RPCFuns *RpcFunc
type CodeResponse interface {
GetCode() int32
GetMsg() string
}
func init() {
RPCFuns = new(RpcFunc)
RPCFuns.FunsInit()
}
type RpcFunc struct {
RpcFuncList map[string]interface{}
}
func (c *RpcFunc) CallLogMeth(methodName string, params interface{}) (response interface{}, err error) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
inj := inject.New()
inj.Map(ctx)
inj.Map(¶ms)
if fn, ok := c.RpcFuncList[methodName]; ok {
response, err = inj.Invoke(fn)
if err != nil {
global.Logger.Warning("func=grpcSvc_welfare_%s&err=%s", methodName, err.Error())
return
}
if res, ok := response.(CodeResponse); ok {
if res.GetCode() != StatusOk {
return nil, errors.New(res.GetMsg())
}
}
} else {
err = errors.New(FunctionNotFund)
}
return
}
func (c *RpcFunc) FunsInit() {
AppGiftApiClient := pb.NewAppGiftApiClient(xrpc.Welfare())
RPCFuns.RpcFuncList = map[string]interface{}{}
RPCFuns.RpcFuncList[OperationsAppGiftApiClientAddGift] = AppGiftApiClient.AddGift
RPCFuns.RpcFuncList[OperationsAppGiftApiClientDeleteGift] = AppGiftApiClient.DeleteGift
RPCFuns.RpcFuncList[OperationsAppGiftApiClientGetGiftById] = AppGiftApiClient.GetGiftById
RPCFuns.RpcFuncList[OperationsAppGiftApiClientGetGiftList] = AppGiftApiClient.GetGiftList
RPCFuns.RpcFuncList[OperationsAppGiftApiClientUpdateGift] = AppGiftApiClient.UpdateGift
AppGiftRecordApiClient := pb.NewAppGiftRecordApiClient(xrpc.Welfare())
RPCFuns.RpcFuncList[OperationsAppGiftRecordApiClientGetGiftRecordList] = AppGiftRecordApiClient.GetGiftRecordList
AppGeneralApiClient := pb.NewAppGeneralApiClient(xrpc.Welfare())
RPCFuns.RpcFuncList[OperationsAppGeneralApiClientGetAppGeneralConfInfo] = AppGeneralApiClient.GetAppGeneralConfInfo
RPCFuns.RpcFuncList[OperationsAppGeneralApiClientUpdateAppGeneralConf] = AppGeneralApiClient.UpdateAppGeneralConf
}
最后我在map里面存方法,然后参数过来之后我用断言这个参数的类型的方式来完成调用。最后代码及流程如下
1.接收前端的请求
// @Summary 详情
// @Description 详情
// @Tags 运营中心/新游社/礼包管理
// @Accept application/json
// @Product application/json
// @Param data body welfare.WelfareIdRequest false "param"
// @Success 200 {object} welfare.GetGiftByIdResponse
// @Router /api/v1/custom/operatecenter/xys/package/info [get]
// @Security Bearer
func GetPackageInfo(c *gin.Context) {
id, _ := tools.StringToInt(c.Query("id"))
request := &pb.WelfareIdRequest{
Id: uint32(id),
}
global.Logger.Debug(request)
response, err := xrpc.RPCFuns.CallLogMeth(xrpc.OperationsAppGiftApiClientGetGiftById, request)
tools.HasError(err, "", -1)
app.OK(c, response, "success")
}
2.请求pb的接口
const StatusOk = 1000
const (
FunctionNotFund = "方法未找到!"
OperationsAppGiftApiClientAddGift = "OperationsAppGiftApiClient.AddGift"
OperationsAppGiftApiClientDeleteGift = "OperationsAppGiftApiClient.DeleteGift"
OperationsAppGiftApiClientGetGiftById = "OperationsAppGiftApiClient.GetGiftById"
OperationsAppGiftApiClientGetGiftList = "OperationsAppGiftApiClient.GetGiftList"
OperationsAppGiftApiClientUpdateGift = "OperationsAppGiftApiClient.UpdateGift"
OperationsAppGiftRecordApiClientGetGiftRecordList = "OperationsAppGiftRecordApiClient.GetGiftRecordList"
OperationsAppGeneralApiClientGetAppGeneralConfInfo = "OperationsAppGeneralApiClient.GetAppGeneralConfInfo"
OperationsAppGeneralApiClientUpdateAppGeneralConf = "OperationsAppGeneralApiClient.UpdateAppGeneralConf"
)
var RPCFuns *RpcFunc
type CodeResponse interface {
GetCode() int32
GetMsg() string
}
func init() {
RPCFuns = new(RpcFunc)
}
type RpcFunc struct {
RpcFuncList map[string]GrpcFunc
}
type GrpcFunc = func(ctx context.Context, request interface{}) (interface{}, error)
func (c *RpcFunc) CallLogMeth(methodName string, params interface{}) (response interface{}, err error) {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
if fn, ok := c.RpcFuncList[methodName]; ok {
response, err = fn(ctx, params)
if err != nil {
global.Logger.Warning("func=grpcSvc_%s&err=%s", methodName, err.Error())
return
}
global.Logger.Debug(response)
if res, ok := response.(CodeResponse); ok {
if res.GetCode() != StatusOk {
return nil, errors.New(res.GetMsg())
}
}
} else {
err = errors.New(FunctionNotFund)
}
return
}
func (c *RpcFunc) FunsInit() {
AppGiftApiClient := welfarePb.NewAppGiftApiClient(Welfare())
RPCFuns.RpcFuncList = map[string]GrpcFunc{}
RPCFuns.RpcFuncList[OperationsAppGiftApiClientAddGift] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGiftApiClient.AddGift(ctx, request.(*welfarePb.AddGiftRequest))
}
RPCFuns.RpcFuncList[OperationsAppGiftApiClientDeleteGift] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGiftApiClient.DeleteGift(ctx, request.(*welfarePb.WelfareIdRequest))
}
RPCFuns.RpcFuncList[OperationsAppGiftApiClientGetGiftById] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGiftApiClient.GetGiftById(ctx, request.(*welfarePb.WelfareIdRequest))
}
RPCFuns.RpcFuncList[OperationsAppGiftApiClientGetGiftList] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGiftApiClient.GetGiftList(ctx, request.(*welfarePb.GiftListRequest))
}
RPCFuns.RpcFuncList[OperationsAppGiftApiClientUpdateGift] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGiftApiClient.UpdateGift(ctx, request.(*welfarePb.UpdateGiftRequest))
}
AppGiftRecordApiClient := welfarePb.NewAppGiftRecordApiClient(Welfare())
RPCFuns.RpcFuncList[OperationsAppGiftRecordApiClientGetGiftRecordList] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGiftRecordApiClient.GetGiftRecordList(ctx, request.(*welfarePb.GiftRecordListRequest))
}
AppGeneralApiClient := welfarePb.NewAppGeneralApiClient(Welfare())
RPCFuns.RpcFuncList[OperationsAppGeneralApiClientGetAppGeneralConfInfo] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGeneralApiClient.GetAppGeneralConfInfo(ctx, request.(*welfarePb.WelfareNullRequest))
}
RPCFuns.RpcFuncList[OperationsAppGeneralApiClientUpdateAppGeneralConf] = func(ctx context.Context, request interface{}) (interface{}, error) {
return AppGeneralApiClient.UpdateAppGeneralConf(ctx, request.(*welfarePb.AppGeneralApiInfo))
}
}
二、这种方法感觉还不够简洁,还想在优化优化,请各位大佬指教