gRPC: definição com protobuf e geração de código
1. Introdução ao gRPC e Protocol Buffers no ecossistema Go
gRPC é um framework de chamada de procedimento remoto (RPC) de alto desempenho desenvolvido pelo Google, que utiliza HTTP/2 como transporte e Protocol Buffers como linguagem de definição de interface (IDL). No ecossistema Go, o gRPC se destaca por sua eficiência, tipagem forte e geração automática de código, eliminando a necessidade de escrever manualmente código de serialização e transporte.
O Protocol Buffers (protobuf) permite definir a estrutura dos dados e os contratos dos serviços em arquivos .proto. A partir dessas definições, ferramentas geram código Go com stubs de cliente e servidor, garantindo que ambos os lados sigam exatamente o mesmo contrato.
O fluxo de trabalho típico é: escrever a definição .proto → executar o compilador protoc com plugins Go → implementar a lógica do servidor e consumir os stubs do cliente.
2. Instalação e configuração do ambiente
Antes de começar, instale as ferramentas necessárias:
# Instalar protoc (compilador protobuf) - Linux/macOS
# Baixe de https://github.com/protocolbuffers/protobuf/releases
# Instalar plugins Go
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
# Verificar instalação
protoc --version
protoc-gen-go --version
protoc-gen-go-grpc --version
Em seguida, crie um módulo Go e adicione as dependências:
go mod init github.com/seu-usuario/grpc-exemplo
go get google.golang.org/grpc
go get google.golang.org/protobuf
3. Definindo serviços e mensagens com protobuf
Crie um arquivo proto/hello.proto:
syntax = "proto3";
package hello;
option go_package = "github.com/seu-usuario/grpc-exemplo/proto/hello";
message HelloRequest {
string name = 1;
int32 age = 2;
}
message HelloResponse {
string greeting = 1;
}
service Greeter {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
A declaração go_package define o caminho do pacote Go gerado. Campos escalares como string e int32 são mapeados automaticamente para tipos Go. Enumerações e campos repetidos (repeated) também são suportados.
4. Tipos avançados de RPC no protobuf
Além do RPC unário, o protobuf suporta três tipos de streaming:
service AdvancedService {
// Server-side streaming: servidor envia múltiplas respostas
rpc ServerStream(Request) returns (stream Response);
// Client-side streaming: cliente envia múltiplos requests
rpc ClientStream(stream Request) returns (Response);
// Bidirectional streaming: comunicação full-duplex
rpc BidirectionalStream(stream Request) returns (stream Response);
}
No Go, cada tipo gera interfaces específicas. Por exemplo, para streaming bidirecional, o servidor implementa um método que recebe um stream e pode chamar stream.Recv() e stream.Send() concorrentemente.
5. Geração de código Go a partir do protobuf
Execute o comando protoc para gerar os stubs:
protoc --go_out=. --go-grpc_out=. proto/hello.proto
Isso gera dois arquivos no diretório proto/hello/:
- hello.pb.go: tipos de mensagens (structs, getters, serialização)
- hello_grpc.pb.go: interfaces de serviço, clientes e servidores
A interface gerada para o servidor será algo como:
type GreeterServer interface {
SayHello(context.Context, *HelloRequest) (*HelloResponse, error)
mustEmbedUnimplementedGreeterServer()
}
Organize os arquivos em diretórios separados: proto/ para definições e código gerado, server/ e client/ para implementações.
6. Implementação do servidor gRPC em Go
Crie server/main.go:
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "github.com/seu-usuario/grpc-exemplo/proto/hello"
)
type server struct {
pb.UnimplementedGreeterServer
}
func (s *server) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) {
greeting := "Olá, " + req.Name + "!"
if req.Age > 0 {
greeting += " Você tem " + string(rune(req.Age)) + " anos."
}
return &pb.HelloResponse{Greeting: greeting}, nil
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("falha ao escutar: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
log.Println("Servidor gRPC ouvindo em :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("falha ao servir: %v", err)
}
}
O servidor implementa a interface GreeterServer, registra o serviço no grpc.Server e inicia a escuta. Use context.Context para propagar cancelamentos e deadlines.
7. Implementação do cliente gRPC em Go
Crie client/main.go:
package main
import (
"context"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "github.com/seu-usuario/grpc-exemplo/proto/hello"
)
func main() {
conn, err := grpc.Dial("localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatalf("falha ao conectar: %v", err)
}
defer conn.Close()
client := pb.NewGreeterClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
resp, err := client.SayHello(ctx, &pb.HelloRequest{Name: "Mundo", Age: 42})
if err != nil {
log.Fatalf("erro na chamada: %v", err)
}
log.Printf("Resposta: %s", resp.Greeting)
}
Para streams, use Recv() e Send():
stream, err := client.ServerStream(ctx, &pb.Request{})
for {
resp, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
log.Printf("Recebido: %v", resp)
}
8. Boas práticas e próximos passos
- Versionamento de protobufs: Use ferramentas como buf.build ou git submodules para gerenciar alterações nos contratos sem quebrar compatibilidade.
- Interceptors: Implemente logging, autenticação e métricas usando interceptors do gRPC, que permitem processar chamadas de forma transversal.
- Deadlines e timeouts: Sempre propague contextos com deadlines para evitar chamadas órfãs.
- Testes: Utilize o pacote
grpc/testingpara criar testes de integração com servidores em memória.
Este artigo é parte de uma série sobre Golang. Nos próximos artigos, exploraremos métricas com Prometheus, documentação com Swagger e streaming bidirecional avançado.
Referências
- Documentação oficial do gRPC em Go — Guia completo de instalação, tutoriais e referência da API Go.
- Protocol Buffers: Guia da linguagem proto3 — Documentação oficial sobre sintaxe, tipos e boas práticas de definição.
- Tutorial: gRPC com Go no site oficial — Exemplo prático passo a passo de servidor e cliente gRPC em Go.
- buf.build: Ferramenta de versionamento de protobufs — Gerenciamento de breaking changes, linting e geração de código com Buf.
- gRPC Interceptors em Go — Repositório com interceptors prontos para logging, autenticação, recuperação de panics e métricas.
- gRPC e streaming bidirecional em Go — Artigo técnico detalhado sobre implementação de streaming bidirecional com exemplos práticos.