下面让我来们建立一个很是精简的 Go kit 服务
业务逻辑逻辑
服务(Service)是从业务逻辑开始的,在 Go kit 中,咱们将服务以 interface 做为模型
1
2
3
4
5
|
// StringService provides operations on strings.
type
StringService
interface
{
Uppercase
(
string
)
(
string
,
error
)
Count
(
string
)
int
}
|
这个 interface 须要有一个“实现”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
type
stringService
struct
{
}
func
(
stringService
)
Uppercase
(
s
string
)
(
string
,
error
)
{
if
s
==
""
{
return
""
,
ErrEmpty
}
return
strings
.
ToUpper
(
s
)
,
nil
}
func
(
stringService
)
Count
(
s
string
)
int
{
return
len
(
s
)
}
// ErrEmpty is returned when input string is empty
var
ErrEmpty
=
errors
.
New
(
"Empty string"
)
|
请求和响应
在 Go kit 中,主要的消息模式是 RPC。所以,接口( interface )的每个方法都会被模型化为远程过程调用(RPC)。对于每个方法,咱们都定义了请求和响应的结构体,捕获输入、输出各自的全部参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
type
uppercaseRequest
struct
{
S
string
`
json
:
"s"
`
}
type
uppercaseResponse
struct
{
V
string
`
json
:
"v"
`
Err
string
`
json
:
"err,omitempty"
`
// errors don't define JSON marshaling
}
type
countRequest
struct
{
S
string
`
json
:
"s"
`
}
type
countResponse
struct
{
V
int
`
json
:
"v"
`
}
|
端点 (endpoint)
Go kit 经过 endpoint 提供了很是丰富的功能。
一个端点表明一个RPC,也就是咱们服务接口中的一个函数。咱们将编写简单的适配器,将咱们的服务的每个方法转换成端点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
import
(
"golang.org/x/net/context"
"github.com/go-kit/kit/endpoint"
)
func
makeUppercaseEndpoint
(
svc
StringService
)
endpoint
.
Endpoint
{
return
func
(
ctx
context
.
Context
,
request
interface
{
}
)
(
interface
{
}
,
error
)
{
req
:
=
request
.
(
uppercaseRequest
)
v
,
err
:
=
svc
.
Uppercase
(
req
.
S
)
if
err
!=
nil
{
return
uppercaseResponse
{
v
,
err
.
Error
(
)
}
,
nil
}
return
uppercaseResponse
{
v
,
""
}
,
nil
}
}
func
makeCountEndpoint
(
svc
StringService
)
endpoint
.
Endpoint
{
return
func
(
ctx
context
.
Context
,
request
interface
{
}
)
(
interface
{
}
,
error
)
{
req
:
=
request
.
(
countRequest
)
v
:
=
svc
.
Count
(
req
.
S
)
return
countResponse
{
v
}
,
nil
}
}
|
传输(Transports)
如今咱们须要将服务暴露给外界,这样它们才能被调用。对于服务如何与外界交互,你的组织可能已经有了定论。可能你会使用 Thrift、基于 HTTP 的自定义 JSON。Go kit支持多种开箱即用的 传输 方式。(Adding support for new ones is easy—just 对新方式的支持是很是简单的。参见 这里
针对咱们如今的这个微型的服务例子,咱们使用基于 HTTP 的 JSON。Go kit 中提供了一个辅助结构体,在 transport/http 中。
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
|
import
(
"encoding/json"
"log"
"net/http"
"golang.org/x/net/context"
httptransport
"github.com/go-kit/kit/transport/http"
)
func
main
(
)
{
ctx
:
=
context
.
Background
(
)
svc
:
=
stringService
{
}
uppercaseHandler
:
=
httptransport
.
NewServer
(
ctx
,
makeUppercaseEndpoint
(
svc
)
,
decodeUppercaseRequest
,
encodeResponse
,
)
countHandler
:
=
httptransport
.
NewServer
(
ctx
,
makeCountEndpoint
(
svc
)
,
decodeCountRequest
,
encodeResponse
,
)
http
.
Handle
(
"/uppercase"
,
uppercaseHandler
)
http
.
Handle
(
"/count"
,
countHandler
)
log
.
Fatal
(
http
.
ListenAndServe
(
":8080"
,
nil
)
)
}
func
decodeUppercaseRequest
(
_
context
.
Context
,
r *
http
.
Request
)
(
interface
{
}
,
error
)
{
var
request
uppercaseRequest
if
err
:
=
json
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
amp
;
request
)
;
err
!=
nil
{
return
nil
,
err
}
return
request
,
nil
}
func
decodeCountRequest
(
_
context
.
Context
,
r *
http
.
Request
)
(
interface
{
}
,
error
)
{
var
request
countRequest
if
err
:
=
json
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
amp
;
request
)
;
err
!=
nil
{
return
nil
,
err
}
return
request
,
nil
}
func
encodeResponse
(
_
context
.
Context
,
w
http
.
ResponseWriter
,
response
interface
{
}
)
error
{
return
json
.
NewEncoder
(
w
)
.
Encode
(
response
)
}
|