What does Go kit look like with generics? #1163
Replies: 3 comments
-
I am recently starting to use it, and i would like to have better support on the endpoints: Right now the req/res are plain naked interfaces, and with generics it can be easily improved: https://github.com/go-kit/kit/blob/master/endpoint/endpoint.go#L9
Can be
This can help add different endpoints, for the http endpoint would be:
This would allow the completion inside the proper endpoint, and if the current behavior is preserved just use any as type:
An example on how to use generics like this can be seen on swaggest/usecase project: https://github.com/swaggest/usecase/blob/master/generic_go1.18.go#L29 Don't know if this is still relevant, feel free to ignore if this is outdated, thanks for your time. |
Beta Was this translation helpful? Give feedback.
-
Has any work been done in this direction? I’d be happy to help to push this forward. |
Beta Was this translation helpful? Give feedback.
-
I've found that its pretty easy to convert existing go kit projects to support generics. Here is an example where I create my own NewServer function with its own Endpoint, DecodeRequestFunc and EncodeResposeFunc: func NewServer[Request any, Response any](
endpoint Endpoint[Request, Response],
decoder DecodeRequestFunc[Request],
encoder EncodeResponseFunc[Response],
options ...httptransport.ServerOption,
) *httptransport.Server {
return httptransport.NewServer(
func(ctx context.Context, r interface{}) (interface{}, error) { return endpoint(ctx, r.(Request)) },
func(ctx context.Context, r *http.Request) (interface{}, error) { return decoder(ctx, r) },
func(ctx context.Context, w http.ResponseWriter, response interface{}) error {
return encoder(ctx, w, response.(Response))
},
options...,
)
}
func EncodeJSONResponse[Res any](ctx context.Context, w http.ResponseWriter, response Res) error {
return httptransport.EncodeJSONResponse(ctx, w, response)
}
type Endpoint[Request any, Response any] func(context.Context, Request) (request Response, err error)
type DecodeRequestFunc[Request any] func(context.Context, *http.Request) (request Request, err error)
type EncodeResponseFunc[Response any] func(context.Context, http.ResponseWriter, Response) error The nice part is that it eliminates the need to create endpoints and of course type safety. Here is what it looks like using these functions: type Service interface {
GetAllRecords(context.Context, RecordsRequest) ([]Record, error)
}
type Record struct{}
type RecordRequest struct{}
type service struct{}
func DecodeRecordRequest(ctx context.Context, r *http.Request) (RecordRequest, error) {
// Do decoding here
return RecordRequest{}, nil
}
func (svc *service) GetAllRecords(ctx context.Context, req RecordsRequest) ([]Record, error) {
res := []Record{}
// do stuff here to get records
return res, nil
}
func MakeHandler(svc Service) http.Handler {
opts := []httptransport.ServerOption{}
return NewServer(
svc.GetAllRecords,
DecodeRecordRequest,
EncodeJSONResponse[[]Record],
opts...,
)
} |
Beta Was this translation helpful? Give feedback.
-
I have some ideas, but I want to hear yours.
Beta Was this translation helpful? Give feedback.
All reactions