go-kit的架构如图分为三层结构:Transport层,Endpoint层,Service层。
Transport
层主要负责与传输协议HTTP,GRPC,THRIFT等相关的逻辑;
Endpoint
层主要负责request/response格式的转换,以及公用拦截器相关的逻辑;
Service
层则专注于业务逻辑,就是我们的业务类、接口等相关信息存放。
go-kit除了经典的分层架构外,还在endpoint层提供了很多公用的拦截器,如log,metric,tracing,circuitbreaker,rate-limiter等,来保障业务系统的可用性。
UserEndpoint.go:
package Services
import (
"context"
"github.com/go-kit/kit/endpoint"
)
type UserRequest struct {
Uid int `json:"uid"`
}
type UserResponse struct {
Result string `json:"result"`
}
func GenUserEndpoint(userService IUserService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(UserRequest)
result := userService.GetName(r.Uid)
return UserResponse{Result: result}, nil
}
}
UserService.go
package Services
type IUserService interface {
GetName(userid int) string
}
type UserService struct {
}
func (this UserService) GetName(userid int) string {
if userid == 101 {
return "jiang"
}
return "tao"
}
UserTransport.go
package Services
import (
"context"
"encoding/json"
"errors"
"net/http"
"strconv"
)
func DecodeUserRequest(c context.Context, r *http.Request) (interface{}, error) {
if r.URL.Query().Get("uid") != "" {
uid, _ := strconv.Atoi(r.URL.Query().Get("uid"))
return UserRequest{
Uid: uid,
}, nil
}
return nil, errors.New("参数错误")
}
func EncodeUserResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-type", "application/json")
return json.NewEncoder(w).Encode(response)
}
main.go
package main
import (
httptransport "github.com/go-kit/kit/transport/http"
"go-kit/Services"
"net/http"
)
func main() {
user := Services.UserService{}
endp := Services.GenUserEndpoint(user)
serverHandler := httptransport.NewServer(endp, Services.DecodeUserRequest, Services.EncodeUserResponse)
http.ListenAndServe(":8080", serverHandler)
}
go get -u github.com/gorilla/mux
main.go
package main
import (
httptransport "github.com/go-kit/kit/transport/http"
mymux "github.com/gorilla/mux"
"go-kit/Services"
"net/http"
)
func main() {
user := Services.UserService{}
endp := Services.GenUserEndpoint(user)
serverHandler := httptransport.NewServer(endp, Services.DecodeUserRequest, Services.EncodeUserResponse)
r := mymux.NewRouter()
//r.Handle(`/user/{uid:\d+}`, serverHandler)
r.Methods("GET").Path(`/user/{uid:\d+}`).Handler(serverHandler)
http.ListenAndServe(":8080", r)
}
UserTransport.go
package Services
import (
"context"
"encoding/json"
"errors"
mymux "github.com/gorilla/mux"
"net/http"
"strconv"
)
func DecodeUserRequest(c context.Context, r *http.Request) (interface{}, error) {
vars := mymux.Vars(r)
if uid, ok := vars["uid"]; ok {
uid, _ := strconv.Atoi(uid)
return UserRequest{
Uid: uid,
}, nil
}
return nil, errors.New("参数错误")
}
func EncodeUserResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-type", "application/json")
return json.NewEncoder(w).Encode(response)
}
main.go
package main
import (
httptransport "github.com/go-kit/kit/transport/http"
mymux "github.com/gorilla/mux"
"go-kit/Services"
"net/http"
)
func main() {
user := Services.UserService{}
endp := Services.GenUserEndpoint(user)
serverHandler := httptransport.NewServer(endp, Services.DecodeUserRequest, Services.EncodeUserResponse)
r := mymux.NewRouter()
//r.Handle(`/user/{uid:\d+}`, serverHandler)
r.Methods("GET", "DELETE").Path(`/user/{uid:\d+}`).Handler(serverHandler)
http.ListenAndServe(":8080", r)
}
UserTransport.go
package Services
import (
"context"
"encoding/json"
"errors"
mymux "github.com/gorilla/mux"
"net/http"
"strconv"
)
func DecodeUserRequest(c context.Context, r *http.Request) (interface{}, error) {
vars := mymux.Vars(r)
if uid, ok := vars["uid"]; ok {
uid, _ := strconv.Atoi(uid)
return UserRequest{
Uid: uid,
Method: r.Method,
}, nil
}
return nil, errors.New("参数错误")
}
func EncodeUserResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-type", "application/json")
return json.NewEncoder(w).Encode(response)
}
UserService.go
package Services
import "errors"
type IUserService interface {
GetName(userid int) string
DelUser(userid int) error
}
type UserService struct {
}
func (this UserService) GetName(userid int) string {
if userid == 101 {
return "jiang"
}
return "tao"
}
func (this UserService) DelUser(userid int) error {
if userid == 101 {
return errors.New("无权限")
}
return nil
}
UserEndpoint.go
package Services
import (
"context"
"fmt"
"github.com/go-kit/kit/endpoint"
)
type UserRequest struct {
Uid int `json:"uid"`
Method string
}
type UserResponse struct {
Result string `json:"result"`
}
func GenUserEndpoint(userService IUserService) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
r := request.(UserRequest)
result := "nothing"
if r.Method == "GET" {
result = userService.GetName(r.Uid)
} else if r.Method == "DELETE" {
err := userService.DelUser(r.Uid)
if err != nil {
result = err.Error()
} else {
result = fmt.Sprintf("userid为%d删除成功", r.Uid)
}
}
return UserResponse{Result: result}, nil
}
}