Go-Kit 微服务基础功能演示

4 minute read

Go-Kit 微服务基础使用演示代码。

演示

发送GET请求到127.0.0.1:9000/calculate/add/9/8

1// Return
2{"result":17,"error":null}

main.go

 1package main
 2
 3import (
 4 "context"
 5 "fmt"
 6 "github.com/go-kit/kit/log"
 7 "net/http"
 8 "os"
 9 "os/signal"
10 "syscall"
11)
12
13func main() {
14 ctx := context.Background()
15 errChan := make(chan error)
16
17 logger := log.NewLogfmtLogger(os.Stderr)
18 logger = log.With(logger, "ts", log.DefaultTimestampUTC)
19 logger = log.With(logger, "caller", log.DefaultCaller)
20
21 // 三层服务
22 // Transports Layer 传输层  (数据转换)
23 // EndPoint Layer 端点层  (充当控制器,负责调用不同功能实现)
24 // Service Layer  服务层  (功能实现)
25 service := NewBaseService()
26 endpoint := NewEndpoint(service)
27 handler := NewTransports(ctx, endpoint, logger)
28
29 go func() {
30  logger.Log("Http Server start at port", 9000)
31  errChan <- http.ListenAndServe(":9000", handler)
32 }()
33
34 go func() {
35  c := make(chan os.Signal, 1)
36  signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
37  errChan <- fmt.Errorf("%s", <-c)
38 }()
39
40 <-errChan
41 logger.Log("Http Server status to", "Stop")
42}

transports.go

 1package main
 2
 3import (
 4 "context"
 5 "encoding/json"
 6 "errors"
 7 "github.com/go-kit/kit/endpoint"
 8 "github.com/go-kit/kit/log"
 9 kitHttp "github.com/go-kit/kit/transport/http"
10 "github.com/gorilla/mux"
11 "net/http"
12 "strconv"
13)
14
15var (
16 ErrorBadRequest = errors.New("invalid request parameter")
17)
18
19// MakeHttpHandler make http handler use mux
20func NewTransports(ctx context.Context, endpoint endpoint.Endpoint, logger log.Logger) http.Handler {
21 r := mux.NewRouter()
22
23 options := []kitHttp.ServerOption{
24  //kitHttp.ServerErrorHandler(),
25  kitHttp.ServerErrorEncoder(kitHttp.DefaultErrorEncoder),
26 }
27
28 r.Methods("GET").Path("/calculate/{type}/{a}/{b}").Handler(kitHttp.NewServer(
29  endpoint,
30  decodeRequest,
31  encodeResponse,
32  options...,
33 ))
34
35 return r
36}
37
38// decodeArithmeticRequest decode request params to struct
39func decodeRequest(_ context.Context, r *http.Request) (interface{}, error) {
40 vars := mux.Vars(r)
41 requestType, ok := vars["type"]
42 if !ok {
43  return nil, ErrorBadRequest
44 }
45
46 pa, ok := vars["a"]
47 if !ok {
48  return nil, ErrorBadRequest
49 }
50
51 pb, ok := vars["b"]
52 if !ok {
53  return nil, ErrorBadRequest
54 }
55
56 a, _ := strconv.Atoi(pa)
57 b, _ := strconv.Atoi(pb)
58
59 return ArithmeticRequest{
60  RequestType: requestType,
61  A:           a,
62  B:           b,
63 }, nil
64}
65
66// encodeArithmeticResponse encode response to return
67func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
68 w.Header().Set("Content-Type", "application/json;charset=utf-8")
69 return json.NewEncoder(w).Encode(response)
70}

endpoint.go

package main

import (
 "context"
 "errors"
 "github.com/go-kit/kit/endpoint"
 "strings"
)

// ArithmeticRequest define request struct
type ArithmeticRequest struct {
 RequestType string `json:"request_type"`
 A           int    `json:"a"`
 B           int    `json:"b"`
}

// ArithmeticResponse define response struct
type ArithmeticResponse struct {
 Result int   `json:"result"`
 Error  error `json:"error"`
}

var (
 ErrInvalidRequestType = errors.New("invalid request parameter")
)

// MakeArithmeticEndpoint make endpoint
func NewEndpoint(svc Service) endpoint.Endpoint {
 return func(ctx context.Context, request interface{}) (response interface{}, err error) {
  req := request.(ArithmeticRequest)

  var (
   res, a, b int
   calError  error
  )

  a = req.A
  b = req.B

  if strings.EqualFold(req.RequestType, "Add") {
   res = svc.Add(a, b)
  } else if strings.EqualFold(req.RequestType, "Substract") {
   res = svc.Subtract(a, b)
  } else if strings.EqualFold(req.RequestType, "Multiply") {
   res = svc.Multiply(a, b)
  } else if strings.EqualFold(req.RequestType, "Divide") {
   res, calError = svc.Divide(a, b)
  } else {
   return nil, ErrInvalidRequestType
  }

  return ArithmeticResponse{Result: res, Error: calError}, nil
 }
}

service.go

 1package main
 2
 3import "errors"
 4
 5// Service Define a service interface
 6type Service interface {
 7
 8 // Add calculate a+b
 9 Add(a, b int) int
10
11 // Subtract calculate a-b
12 Subtract(a, b int) int
13
14 // Multiply calculate a*b
15 Multiply(a, b int) int
16
17 // Divide calculate a/b
18 Divide(a, b int) (int, error)
19}
20
21//ArithmeticService implement Service interface
22type baseService struct {
23}
24
25func NewBaseService() *baseService {
26 return new(baseService)
27}
28
29// Add implement Add method
30func (s *baseService) Add(a, b int) int {
31 return a + b
32}
33
34// Subtract implement Subtract method
35func (s *baseService) Subtract(a, b int) int {
36 return a - b
37}
38
39// Multiply implement Multiply method
40func (s *baseService) Multiply(a, b int) int {
41 return a * b
42}
43
44// Divide implement Divide method
45func (s *baseService) Divide(a, b int) (int, error) {
46 if b == 0 {
47  return 0, errors.New("the dividend can not be zero!")
48 }
49
50 return a / b, nil
51}

go.mod

1module util
2
3go 1.15
4
5require (
6 github.com/go-kit/kit v0.10.0
7 github.com/gorilla/mux v1.7.4
8)