3.【go-kit教程】go-kit集成gin启动服务
环境准备
- gokit工具集:
go get github.com/go-kit/kit
; - http请求路由组件:
go get github.com/gorilla/mux
; - gin框架安装:
go get -u github.com/gin-gonic/gin
;
go-kit集成gin
示例在 《go-kit启动http服务》代码示例上更改。
-
由于其灵活的设计, 通过使用 go-kit,开发者可以快速地构建出符合分布式系统要求的微服务应用,同时也能够方便地对已有的应用进行升级和维护。所以我们集成gin也是很方便的,只需要稍微改动transport层即可
/** * @date: 2023/2/18 * @desc: 传输层 http/rpc... */ package endpoints import ( "context" "encoding/json" "github.com/gin-gonic/gin" "github.com/go-kit/kit/endpoint" httptransport "github.com/go-kit/kit/transport/http" "kit-gin-demo/endpoints" "net/http" ) func decodeFooRequest(_ context.Context, r *http.Request) (interface{}, error) { var req endpoints.FooRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, err } return req, nil } func decodeBarRequest(_ context.Context, r *http.Request) (interface{}, error) { var req endpoints.BarRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, err } return req, nil } func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { return json.NewEncoder(w).Encode(response) } // MakeHttpHandler make http handler use mux func MakeHttpHandler(ctx context.Context, fooEndpoint, barEndpoint endpoint.Endpoint) http.Handler { //r := mux.NewRouter() r := gin.Default() // 使用gin框架路由 options := []httptransport.ServerOption{ httptransport.ServerErrorEncoder(httptransport.DefaultErrorEncoder), } fooHandler := httptransport.NewServer( fooEndpoint, decodeFooRequest, encodeResponse, options..., ) barHandler := httptransport.NewServer( barEndpoint, decodeBarRequest, encodeResponse, options..., ) r.POST("/foo", gin.WrapH(fooHandler)) r.POST("/bar", gin.WrapH(barHandler)) return r }
完整代码
-
services/my_service.go
/** * @date: 2023/2/18 * @desc: 服务层 业务具体实现 */ package endpoints import "context" type MyServicer interface { Foo(context.Context, string) (string, error) Bar(context.Context, int64) (bool, error) } type MyService struct{} func (s *MyService) Foo(ctx context.Context, str string) (string, error) { return "foo" + str, nil } func (s *MyService) Bar(ctx context.Context, n int64) (bool, error) { return n%2 == 0, nil }
-
endpoints/endpoint.go
/** * @date: 2023/2/18 * @desc: endpoints 层 */ package endpoints import ( "context" "github.com/go-kit/kit/endpoint" services "kit-demo/services" ) type FooRequest struct { Str string `json:"str"` } type FooResponse struct { Str string `json:"str"` Err string `json:"err,omitempty"` } type BarRequest struct { N int64 `json:"n"` } type BarResponse struct { Result bool `json:"result"` Err string `json:"err,omitempty"` } func MakeFooEndpoint(svc services.MyServicer) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(FooRequest) res, err := svc.Foo(ctx, req.Str) if err != nil { return FooResponse{res, err.Error()}, nil } return FooResponse{res, ""}, nil } } func MakeBarEndpoint(svc services.MyServicer) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(BarRequest) res, err := svc.Bar(ctx, req.N) if err != nil { return BarResponse{res, err.Error()}, nil } return BarResponse{res, ""}, nil } }
-
transports/my_transport.go
/** * @date: 2023/2/18 * @desc: 传输层 http/rpc... */ package endpoints import ( "context" "encoding/json" "github.com/go-kit/kit/endpoint" httptransport "github.com/go-kit/kit/transport/http" "github.com/gorilla/mux" "kit-demo/endpoints" "net/http" ) func decodeFooRequest(_ context.Context, r *http.Request) (interface{}, error) { var req endpoints.FooRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, err } return req, nil } func decodeBarRequest(_ context.Context, r *http.Request) (interface{}, error) { var req endpoints.BarRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { return nil, err } return req, nil } func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { return json.NewEncoder(w).Encode(response) } // MakeHttpHandler make http handler use gin func MakeHttpHandler(ctx context.Context, fooEndpoint, barEndpoint endpoint.Endpoint) http.Handler { //r := mux.NewRouter() r := gin.Default() options := []httptransport.ServerOption{ httptransport.ServerErrorEncoder(httptransport.DefaultErrorEncoder), } fooHandler := httptransport.NewServer( fooEndpoint, decodeFooRequest, encodeResponse, options..., ) barHandler := httptransport.NewServer( barEndpoint, decodeBarRequest, encodeResponse, options..., ) r.POST("/foo", gin.WrapH(fooHandler)) r.POST("/bar", gin.WrapH(barHandler)) return r }
-
main.go
package main import ( "context" "fmt" "kit-demo/endpoints" services "kit-demo/services" transports "kit-demo/transports" "net/http" "os" "os/signal" "syscall" ) func main() { errChan := make(chan error) // Create a new service svc := services.MyService{} ctx := context.Background() // Create the endpoints fooEndpoint := endpoints.MakeFooEndpoint(&svc) barEndpoint := endpoints.MakeBarEndpoint(&svc) r := transports.MakeHttpHandler(ctx, fooEndpoint, barEndpoint) go func() { fmt.Println("Http Server start at port:8080") handler := r errChan <- http.ListenAndServe(":8080", handler) }() go func() { c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) errChan <- fmt.Errorf("%s", <-c) }() fmt.Println(<-errChan) }