Maison  >  Article  >  développement back-end  >  GO et GRPC : Création de classes protobuff "à la volée"

GO et GRPC : Création de classes protobuff "à la volée"

PHPz
PHPzavant
2024-02-06 11:06:031266parcourir

GO 和 GRPC:“在飞行中”创建 protobuff 类

Contenu de la question

Je suis nouveau sur GRPC et je n'arrive pas à résoudre un problème. Est-il possible de créer un fichier protobuff lorsque l'application est déjà en cours d'exécution ? Par exemple, je reçois un json de l'utilisateur comme ceci :

"protobuf_file": "protobuf.proto", // File will be also recieved from user
"service_name": "Unary",
"method_name": "GetServerResponse",
"request_data_serializer_name": "MessageRequest",
"body": "grpc_request_data.json", // File will be also recieved from user

Ici, j'ai un .proto fichier, un nom de service, une méthode et un message, et un autre json avec des données pour remplir le message. Je dois maintenant ouvrir la connexion et appeler la méthode requise avec les données fournies.

TY!

PS .proto Le fichier (extrait du Guide d'instructions d'obtention) sera :

syntax = "proto3";

package protobuf_all_modes;

service Unary {
 rpc GetServerResponse(MessageRequest) returns (MessageResponse) {}
}

message MessageRequest {
 string message = 1;
}

message MessageResponse {
 string message = 1;
 int32 random_int32 = 2;
}

Le deuxième json sera :

{
    "message": "hello World!"
}

Je ne sais pas où chercher une solution. Toutes les suggestions seraient grandement appréciées


Réponse correcte


Si quelqu'un a le même problème, il existe une très bonne bibliothèque - https://pkg.go.dev/github.com/jhump/[ email protégé] /dynamic et un sous-packagehttps://pkg.go.dev/github. com/jhump/[email protégé]/dynamic/grpcdynamic L'extrait de code serait : parser

func NewGrpcObject(operation *BaseOperation) *GrpcObject {
    fns, err := protoparse.ResolveFilenames([]string{"./"}, operation.ProtoFile) // prase .proto file
    if err != nil {
        log.Error(err)
    }

    parser := protoparse.Parser{}
    fds, err := parser.ParseFiles(fns...)
    if err != nil {
        log.Error(err)
    }
    descriptor := fds[0] // In my case there will be only one .proto
    pkg := descriptor.GetPackage()
    serviceDescriptor := descriptor.FindService(pkg + "." + operation.ServiceName) // name of service descriptor will be with package name first
    methodDescriptor := serviceDescriptor.FindMethodByName(operation.MethodName)
    requestDescriptor := methodDescriptor.GetInputType() // You can get types for request and response
    responseDescriptor := methodDescriptor.GetOutputType()

    return &GrpcObject{
        RequestDesc: requestDescriptor,
        MethodDesc: methodDescriptor,
        ResponseDesc: responseDescriptor,
    }
}

caller

// connect 
        conn, _ := grpc.Dial(operation.Host, grpc.WithTransportCredentials(credentials.NewTLS(c.TLSClientConfig.NewTLSConfig())))
        stub = grpcdynamic.NewStub(conn)

// call
    message := dynamic.NewMessage(operation.GrpcObject.RequestDesc) // from parser
    message.UnmarshalJSON(operation.Body) // here a JSON to fill message

    resp, err := stub.InvokeRpc(ctx, operation.GrpcObject.MethodDesc, message)
    if err != nil {
        // handle err
    }
    respMessage := dynamic.NewMessage(operation.GrpcObject.ResponseDesc) // descriptor from parser
    respMessage.ConvertFrom(resp) // convert message from raw response

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer