【go-kit教程】go-kit启动http服务
# 环境准备
- gokit工具集:
go get github.com/go-kit/kit
; - http请求路由组件:
go get github.com/gorilla/mux
;
# 快速上手
上代码
package main import ( "context" "encoding/json" "errors" "log" "net/http" "github.com/gorilla/mux" httptransport "github.com/go-kit/kit/transport/http" "github.com/go-kit/kit/endpoint" ) type MyService 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 } 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 MyService) 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 MyService) 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 } } func decodeFooRequest(_ context.Context, r *http.Request) (interface{}, error) { var req 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 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) } func main() { // Create a new service svc := myService{} // Create the endpoints fooEndpoint := makeFooEndpoint(svc) barEndpoint := makeBarEndpoint(svc) // Create the router and register the endpoints r := mux.NewRouter() r.Methods("POST").Path("/foo").Handler(httptransport.NewServer( fooEndpoint, decodeFooRequest, encodeResponse, )) r.Methods("POST").Path("/bar").Handler(httptransport.NewServer( barEndpoint, decodeBarRequest, encodeResponse, )) // Start the server log.Fatal(http.ListenAndServe(":8080", r)) }
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114执行命令
curl http://127.0.0.1:8080/foo -d '{"data":"111"}' -XPOST
响应{"str":"foo"}
# 代码分层
目录结构
. ├── endpoints │ └── my_endpoint.go ├── go.mod ├── go.sum ├── main.go ├── services │ └── my_service.go └── transports └── my_transport.go
1
2
3
4
5
6
7
8
9
10
11services/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 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24endpoints/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 } }
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
53transports/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 mux func MakeHttpHandler(ctx context.Context, fooEndpoint, barEndpoint endpoint.Endpoint) http.Handler { r := mux.NewRouter() options := []httptransport.ServerOption{ httptransport.ServerErrorEncoder(httptransport.DefaultErrorEncoder), } r.Methods("POST").Path("/foo").Handler(httptransport.NewServer( fooEndpoint, decodeFooRequest, encodeResponse, options..., )) r.Methods("POST").Path("/bar").Handler(httptransport.NewServer( barEndpoint, decodeBarRequest, encodeResponse, options..., )) return r }
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
62main.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) }
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
# 完整代码
- https://github.com/hellolib/go-kit-demo/tree/main/kit-demo
上次更新: 2023/04/16, 18:35:33