侧边栏壁纸
博主头像
Tony's Blog博主等级

行动起来,coding

  • 累计撰写 83 篇文章
  • 累计创建 58 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

gokit的理解

Tony
2024-02-21 / 0 评论 / 0 点赞 / 22 阅读 / 8493 字

本文链接: https://blog.csdn.net/lishuangquan1987/article/details/127247654

版权

理解的流程图如下所示:

1-cfdv.png

现更加具体示例来理解。

示例目的

新建两个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,不过不影响,只不过是名称而已

2-ywxw.png

初始化包管理器

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,但是连接数据的信息没有包含,业务逻辑层的处理函数可能会使用到这些。

简单来讲,就是如下的一个转换过程:

3-pwiw.png

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

评论区