service.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type Service interface {
  Status(ctx context.Context) (string, error)
}

type statusService struct{}

func NewService() Service {
  return statusService{}
}

func (statusService) Status(ctx context.Context) (string, error) {
  return "ok", nil
}

endpoints.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
type statusRequest struct{}

type statusResponse struct {
  Status string `json:"status"`
}

type Endpoints struct {
  StatusEndpoint        endpoint.Endpoint
}

func MakeStatusEndpoint(svc Service) endpoint.Endpoint {
  return func(ctx context.Context, request interface{}) (interface{}, error) {
    _ = request.(statusRequest)
    s, err := svc.Status(ctx)
    if err != nil {
      return statusResponse{s}, err
    }
    return statusResponse{s}, nil
  }
}

transport.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
func decodeStatusRequest(ctx context.Context, r *http.Request) (interface{}, error) {
	var req statusRequest
	return req, nil
}

type errorer interface {
	error() error
}

func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
	err, ok := response.(errorer)
	if ok && err.error() != nil {
		encodeError(ctx, w, err.error())
		return nil
	}
	w.Header().Set("Content-Type", "application/json;charset=utf-8")
	return json.NewEncoder(w).Encode(response)
}

func encodeError(ctx context.Context, w http.ResponseWriter, err error) {
	if err == nil {
		panic("encodeError with nil error")
	}
	w.Header().Set("Content-Type", "application/json;charset=utf-8")
	json.NewEncoder(w).Encode(map[string]interface{}{
		"error": err.Error(),
	})
}

server.gofunc

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
NewHTTPServer(ctx context.Context, endpoints Endpoints) *gin.Engine {
	router := gin.Default()
	router.Use(commonMiddlewar())
	disk := router.Group("/disks")
	{
		v1 := disk.Group("/v1")
		{
			v1.GET("/status", func(ctx *gin.Context) {
				httptransport.NewServer(endpoints.StatusEndpoint,
					decodeStatusRequest, encodeResponse)
			})
		}
	}

	return router
}

func commonMiddlewar() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		ctx.Writer.Header().Add("Context-Type", "application/json")
	}
}

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
func main() {
	ctx := context.Background()
	srv := NewService()

	errChan := make(chan error)

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

	eps := Endpoints{
		StatusEndpoint:        MakeStatusEndpoint(srv),
	}

	go func() {
		gin.SetMode(gin.ReleaseMode)
		errChan <- NewHTTPServer(ctx, eps).Run(":10087")
	}()

	log.Fatalln(<-errChan)
}

转载:https://www.zhihu.com/question/323548694/answer/874485111