I am currently playing around with grpc on golang and trying to figure out the best way to make an extensible 'thin' api that i can use to pass all requests to their relevant services.
I currently have the structure of:
- Service 1
- routes.go
- rpc.go
- Service 2
- routes.go
- rpc.go
Within the routes files, it creates a new routeGroup that i then register in main, then each handler for a route parses any params etc into a protobuf request and calls a function within RPC:
func showFeed(c *gin.Context) {
message, err := RpcFeedGet(&social.ShowRequest{LocationId: 1})
resp := http.HttpResponse{c, "feed", err, message}
http.ParseResponse(&resp) //Checks if there is an error and handles response headers etc.
}
Now within rpc im currently defining the below for each service which seems to be really inefficient to me as there is a lot of code reuse, how would i optimize/reduce the code reuse within this method
func connect() (*grpc.ClientConn, pb.Service1Client) {
//Consul is being used for discovery, this just gets the address to dial
consul := discovery.Init()
service, err := consul.Lookup("service1", "")
if err != nil {
log.Fatalf("Unable to get service definition: %w", err)
}
//Dial the connection to the service
conn, err := grpc.Dial(service.Address(), grpc.WithInsecure())
if err != nil {
log.Fatalf("Unable to connect to client service: %v", err)
}
//Creates the service client (service1) and returns it
client := pb.NewService1Client(conn)
return conn, client
}
func RpcFeedGet(data *pb.ShowRequest) (string, error) {
conn, client := connect()
defer conn.Close()
//This line calls the protobuf GetFeed rpc service
resp, err := client.GetFeed(context.Background(), data)
return rpcHelp.CheckResponse(resp, err) //Handles any errors returned
}
Is there a way i can pass a function to a sub function that calls the connect/defer within the Rpc function and also normalise the connect()
method so i dont have to redeclare it for each service? bearing in mind it returns a different client on each instance?