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) errorThe 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.
Uh oh!
There was an error while loading. Please reload this page.
-
I have some ideas, but I want to hear yours.
Beta Was this translation helpful? Give feedback.
All reactions