gokit的理解

Posted lishuangquan1987

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 GetUserInfoByUserIdResponseUserInfo: 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 GetUserInfoByMoreThanAgeResponseUserInfos: 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.GetUserInfoByUserIdRequestUserId: 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.GetUserInfoByMoreThanAgeRequestAge: 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 


以上是关于gokit的理解的主要内容,如果未能解决你的问题,请参考以下文章

gokit的理解

Gokit:在传输层验证请求/有效负载

gokit学习

NUCLEO-L496ZG+Gokit3S+Rtthead+AT组件组网

机智云5.0推出IoT套件GoKit4.0 可实现物联网应用协同开发

通过Gokit玩转Echo语音控制开发技能