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

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

演示

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

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

main.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package main

import (
 "context"
 "fmt"
 "github.com/go-kit/kit/log"
 "net/http"
 "os"
 "os/signal"
 "syscall"
)

func main() {
 ctx := context.Background()
 errChan := make(chan error)

 logger := log.NewLogfmtLogger(os.Stderr)
 logger = log.With(logger, "ts", log.DefaultTimestampUTC)
 logger = log.With(logger, "caller", log.DefaultCaller)

 // 三层服务
 // Transports Layer 传输层  (数据转换)
 // EndPoint Layer 端点层  (充当控制器,负责调用不同功能实现)
 // Service Layer  服务层  (功能实现)
 service := NewBaseService()
 endpoint := NewEndpoint(service)
 handler := NewTransports(ctx, endpoint, logger)

 go func() {
  logger.Log("Http Server start at port", 9000)
  errChan <- http.ListenAndServe(":9000", handler)
 }()

 go func() {
  c := make(chan os.Signal, 1)
  signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
  errChan <- fmt.Errorf("%s", <-c)
 }()

 <-errChan
 logger.Log("Http Server status to", "Stop")
}

transports.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package main

import (
 "context"
 "encoding/json"
 "errors"
 "github.com/go-kit/kit/endpoint"
 "github.com/go-kit/kit/log"
 kitHttp "github.com/go-kit/kit/transport/http"
 "github.com/gorilla/mux"
 "net/http"
 "strconv"
)

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

// MakeHttpHandler make http handler use mux
func NewTransports(ctx context.Context, endpoint endpoint.Endpoint, logger log.Logger) http.Handler {
 r := mux.NewRouter()

 options := []kitHttp.ServerOption{
  //kitHttp.ServerErrorHandler(),
  kitHttp.ServerErrorEncoder(kitHttp.DefaultErrorEncoder),
 }

 r.Methods("GET").Path("/calculate/{type}/{a}/{b}").Handler(kitHttp.NewServer(
  endpoint,
  decodeRequest,
  encodeResponse,
  options...,
 ))

 return r
}

// decodeArithmeticRequest decode request params to struct
func decodeRequest(_ context.Context, r *http.Request) (interface{}, error) {
 vars := mux.Vars(r)
 requestType, ok := vars["type"]
 if !ok {
  return nil, ErrorBadRequest
 }

 pa, ok := vars["a"]
 if !ok {
  return nil, ErrorBadRequest
 }

 pb, ok := vars["b"]
 if !ok {
  return nil, ErrorBadRequest
 }

 a, _ := strconv.Atoi(pa)
 b, _ := strconv.Atoi(pb)

 return ArithmeticRequest{
  RequestType: requestType,
  A:           a,
  B:           b,
 }, nil
}

// encodeArithmeticResponse encode response to return
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
 w.Header().Set("Content-Type", "application/json;charset=utf-8")
 return json.NewEncoder(w).Encode(response)
}

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package main

import "errors"

// Service Define a service interface
type Service interface {

 // Add calculate a+b
 Add(a, b int) int

 // Subtract calculate a-b
 Subtract(a, b int) int

 // Multiply calculate a*b
 Multiply(a, b int) int

 // Divide calculate a/b
 Divide(a, b int) (int, error)
}

//ArithmeticService implement Service interface
type baseService struct {
}

func NewBaseService() *baseService {
 return new(baseService)
}

// Add implement Add method
func (s *baseService) Add(a, b int) int {
 return a + b
}

// Subtract implement Subtract method
func (s *baseService) Subtract(a, b int) int {
 return a - b
}

// Multiply implement Multiply method
func (s *baseService) Multiply(a, b int) int {
 return a * b
}

// Divide implement Divide method
func (s *baseService) Divide(a, b int) (int, error) {
 if b == 0 {
  return 0, errors.New("the dividend can not be zero!")
 }

 return a / b, nil
}

go.mod

1
2
3
4
5
6
7
8
module util

go 1.15

require (
 github.com/go-kit/kit v0.10.0
 github.com/gorilla/mux v1.7.4
)