gokit的理解

理解的流程图如下所示:
在这里插入图片描述
现更加具体示例来理解。

示例目的

新建两个WebApi:

  • 根据UserId获取UserInfo

  • 获取所有的年龄大于30的UserInfo
    期望如下:

  • 请求http://xxxx:8080?userId=1,返回如下格式:

{
	user_id:1,
	user_name:"tony",
	age:35
}
  • 请求http://xxxx:8081?age=30返回格式如下:
[	
{
	user_id:1,
	user_name:"tony",
	age:35
},
{
	user_id:2,
	user_name:"TEST",
	age:40
},
]

开始编码

搭建使用gokit的项目目录:

为了避免命名冲突所以在三个文件夹和包名称前面加上了My,不过不影响,只不过是名称而已
在这里插入图片描述

初始化包管理器

go mod init microservicetest

引用gokit

go get -u github.com/go-kit/kit

定义通用的Model实体

model.go:

package Model

type UserInfo struct {
	UserId   int    `json:"user_id"`
	UserName string `json:"user_name"`
	Age      int    `json:"age"`
}

定义业务逻辑上的请求和响应

业务逻辑上的请求和响应,需要为结构体
请注意,为什么要定义业务逻辑上的请求和响应:
这里有个区分:

  • 传输层(http请求)的参数和响应
  • 业务逻辑处理的请求(方法参数)和响应(方法返回值)

这两个是不一样的,但是有一些关键的信息关联。
传输层(http请求)的参数,只是提供一些关键的简单的信息,比如用户ID等
业务逻辑处理的请求,包含业务逻辑处理所需要的全部参数。
比如:http请求中包含很多参数,有用户ID,有token,有用户姓名,我们的逻辑处理可能只需要用到用户ID。
又比如:http请求中只包含关键信息用户ID,但是连接数据的信息没有包含,业务逻辑层的处理函数可能会使用到这些。
简单来讲,就是如下的一个转换过程:
在这里插入图片描述
http请求中得到我们需要的信息,组成业务逻辑的request
这个定义过程,放在endpoint.go中:

  • 请求http://xxxx:8080?userId=1,返回如下格式:
{
	user_id:1,
	user_name:"tony",
	age:35
}

对应的Request与Response如下:

type GetUserInfoByUserIdRequest struct{
	UserId int `json:"user_id"`
}

type GetUserInfoByUserIdResponse struct{
	UserInfo
}
  • 请求http://xxxx:8081?age=30返回格式如下:
[	
{
	user_id:1,
	user_name:"tony",
	age:35
},
{
	user_id:2,
	user_name:"TEST",
	age:40
},
]

对应的Request与Response如下:

type GetUserInfoByMoreThanAgeRequest struct{
	Age int `json:"age"`
}

type GetUserInfoByMoreThanAgeResponse struct{
	UserInfos []UserInfo
}

定义核心业务逻辑函数

MyServer中定义核心业务逻辑。即如何根据业务逻辑的参数得到业务逻辑的返回值。
这里可能需要连接数据,可能需要从其他地方请求数据等等。
server.go:

package Myserver

import (
	"microservicetest/Model"
)

type IMyServer interface {
	GetUserById(userId int) Model.UserInfo
	GetUsersByMoreThanAge(age int) []Model.UserInfo
}

type Myserver struct {
}

func (s *Myserver) GetUserById(userId int) Model.UserInfo {
	return Model.UserInfo{
		UserId:   1,
		UserName: "tony",
		Age:      35,
	}
}

func (s *Myserver) GetUsersByMoreThanAge(age int) []Model.UserInfo {
	return []Model.UserInfo{
		Model.UserInfo{
			UserId:   1,
			UserName: "tony",
			Age:      35,
		},
		Model.UserInfo{
			UserId:   2,
			UserName: "TEST",
			Age:      40,
		},
	}
}

再回到Myendpoint中,调用Myserver中的业务逻辑,构造Endpoint

endpoint.go:

func MakeGetUserInfoByUserIdEndpoint(s Myserver.IMyServer) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		r, ok := request.(GetUserInfoByUserIdRequest)
		if !ok {
			return GetUserInfoByUserIdResponse{}, nil
		}

		return GetUserInfoByUserIdResponse{UserInfo: s.GetUserById(r.UserId)}, nil
	}
}

func MakeGetUserInfoByMoreThanAgeEndpoint(s Myserver.IMyServer) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		r, ok := request.(GetUserInfoByMoreThanAgeRequest)
		if !ok {
			return GetUserInfoByMoreThanAgeResponse{}, nil
		}

		return GetUserInfoByMoreThanAgeResponse{UserInfos: s.GetUsersByMoreThanAge(r.Age)}, nil
	}
}

最后Transport层

Transport层定义了如何从*http.Request中解析到我们需要的参数,以及通过http.ResponseWriter将最终的结果以什么样的格式和形式反馈出去.
transport.go:

package Mytransport

import (
	"context"
	"encoding/json"
	"microservicetest/Myendpoint"
	"net/http"
	"strconv"
)

func DecodeGetUserByIdRequest(c context.Context, request *http.Request) (interface{}, error) {
	userIdStr := request.URL.Query().Get("user_id")
	userId, err := strconv.Atoi(userIdStr)
	if err != nil {
		return nil, err
	}
	return Myendpoint.GetUserInfoByUserIdRequest{UserId: userId}, nil
}

func EncodeResponse(c context.Context, w http.ResponseWriter, response interface{}) error {
	return json.NewEncoder(w).Encode(response)
}

func DecodeGetUserByMoreThanAgeRequest(c context.Context, request *http.Request) (interface{}, error) {
	ageStr := request.URL.Query().Get("age")
	age, err := strconv.Atoi(ageStr)
	if err != nil {
		return nil, err
	}
	return Myendpoint.GetUserInfoByMoreThanAgeRequest{Age: age}, nil
}

最终使用

main.go:

package main

import (
	"fmt"
	"microservicetest/Myendpoint"
	"microservicetest/Myserver"
	"microservicetest/Mytransport"
	"net/http"

	kitHttp "github.com/go-kit/kit/transport/http"
)

func main() {
	s := &Myserver.Myserver{}

	getUserInfoByUserIdServer := Myendpoint.MakeGetUserInfoByUserIdEndpoint(s)

	getUserInfoByMoreThanAgeServer := Myendpoint.MakeGetUserInfoByMoreThanAgeEndpoint(s)

	s1 := kitHttp.NewServer(getUserInfoByUserIdServer, Mytransport.DecodeGetUserByIdRequest, Mytransport.EncodeResponse)
	s2 := kitHttp.NewServer(getUserInfoByMoreThanAgeServer, Mytransport.DecodeGetUserByMoreThanAgeRequest, Mytransport.EncodeResponse)

	go http.ListenAndServe(":8080", s1)
	go http.ListenAndServe(":8081", s2)

	fmt.Println("server is start")
	select {}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值