Criando o primeiro servidor gRPC em Go

Resumen

Construir um servidor gRPC em Go envolve mais do que escrever funções: requer ligar o repositório, respeitar interfaces geradas pelo proto buffer e configurar o listener TCP correto. Aqui vais aprender a montar o teu primeiro StudentServiceServer passo a passo, ideal para quem já trabalha com bases de dados em Go e quer dar o salto para microsserviços.

Como estruturar a pasta server e o construtor do StudentServer?

O ponto de partida é organizar o código numa pasta dedicada. Cria uma pasta server e, dentro dela, um ficheiro server.go com o pacote server. A struct principal recebe o repositório como dependência, o que permite isolar a lógica de acesso a dados da lógica de transporte gRPC.

O construtor NewStudentServer aceita um repo do tipo repositório e devolve uma instância do servidor. Esta separação facilita testes e respeita o princípio de injeção de dependências.

¿Para que serve o construtor NewStudentServer? Recebe o repositório como parâmetro e devolve uma instância pronta para registar no gRPC, ligando a camada de dados à camada de serviço.

Um detalhe técnico importante [02:10]: renomeia a pasta gerada pelo proto buffer para studentPB, igual ao nome do pacote definido no ficheiro .proto. Assim, o Go importa-a sem conflitos.

Como implementar GetStudent e SetStudent no servidor gRPC?

Ambos os métodos seguem a assinatura definida no ficheiro .proto gerado. O servidor traduz pedidos gRPC em chamadas ao repositório e devolve respostas tipadas.

GetStudent: ler um aluno pelo id

O método recebe um context.Context e um *studentPB.GetStudentRequest. Para aceder ao identificador podes usar request.Id ou o getter request.GetId(), ambos válidos.

go func (s *Server) GetStudent(ctx context.Context, request *studentPB.GetStudentRequest) (*studentPB.Student, error) { student, err := s.repo.GetStudent(ctx, request.GetId()) if err != nil { return nil, err } return &studentPB.Student{ Id: student.Id, Name: student.Name, Age: student.Age, }, nil }

Repara num ponto crítico: a struct studentPB.Student e a struct do modelo de dados não são iguais. Uma vem do código gerado pelo proto, a outra do teu modelo interno. Tens de mapear os campos manualmente [04:20].

SetStudent: inserir um aluno

Aqui o pedido é um studentPB.Student completo, e a resposta é um SetStudentResponse que devolve apenas o id. Constrói a struct do modelo a partir do request, envia para o repositório e devolve a confirmação.

Qual é a diferença entre GetStudentRequest e Student como input? GetStudentRequest carrega só o id para leitura; Student carrega todos os campos para inserção ou atualização.

Como ligar o servidor gRPC com listener TCP e Reflection?

Na pasta server/student cria um main.go com package main. A função main precisa de quatro peças: o listener TCP, o repositório, a struct do servidor e o registo no gRPC.

O listener abre a porta com net.Listen("tcp", ":5060"). Se houver erro, log.Fatal encerra a aplicação. A porta 5060 é configurável, tal como a URL do PostgreSQL que injetas no NewPostgresRepository.

go lis, err := net.Listen("tcp", ":5060") if err != nil { log.Fatal(err) } repo, err := database.NewPostgresRepository(url) srv := server.NewStudentServer(repo) s := grpc.NewServer() studentPB.RegisterStudentServiceServer(s, srv) reflection.Register(s) s.Serve(lis)

Por que aparece o erro de interface não implementada?

Ao chamar RegisterStudentServiceServer, o Go espera uma interface StudentServiceServer completa. Se faltar algum método, o compilador reclama. A solução elegante é incorporar studentPB.UnimplementedStudentServiceServer dentro da tua struct Server.

Isto funciona porque o Go usa composição em vez de herança. Ao embeber a struct unimplemented, o teu servidor herda automaticamente todos os métodos exigidos pela interface, mesmo os que ainda não escreveste.

Para que serve Reflection no gRPC?

O reflection.Register(s) expõe metadados sobre os serviços disponíveis. Sem isto, ferramentas como o Postman não conseguem descobrir os métodos do teu servidor para testá-los.

¿O que é Reflection em gRPC? É um mecanismo que entrega metadados dos serviços ao cliente, permitindo que ferramentas como Postman explorem e invoquem métodos sem ter o ficheiro .proto localmente.

Chama reflection.Register antes de s.Serve(lis), caso contrário o servidor arranca sem expor essa informação.

Conceitos e habilidades que ficam contigo

  • Composição em Go com Unimplemented...Server para cumprir interfaces geradas [07:15].
  • Mapeamento entre structs do proto buffer e modelos internos da aplicação.
  • Configuração de listeners TCP na porta 5060 com net.Listen.
  • Uso de getters gerados (GetId, GetName, GetAge) versus acesso direto a campos.
  • Registo de serviços gRPC com RegisterStudentServiceServer e ativação de Reflection.

Na próxima aula vais testar tudo isto com Postman e validar as chamadas reais ao servidor. Se já experimentaste, conta nos comentários como correu a tua primeira ligação gRPC.