Hola, lectores, esta vez les quiero mostrar cómo implementar el clásico ejemplo Hello World con gRPC, pero con un pequeño cambio: en lugar de enviar un Name como parámetro, vamos a modificar la definición del protocol buffer y el código generado para que el cliente envíe un Nickname y el servidor lo devuelva en la respuesta. Vamos a usar el mismo tipo de entorno que utilicé en mi publicación anterior sobre Container Runtimes, esta vez ejecutando todo dentro de un playground de Ubuntu en Killercoda y un contenedor de golang.
Esta publicación se va a enfocar en:
- Configurar un entorno de desarrollo con gRPC + Protoc en Go.
- Modificar el ejemplo oficial de Hello World de grpc-go para usar un campo Nickname.
- Ejecutar el servidor gRPC e invocarlo desde un proceso cliente.
Qué vas a aprender
- Preparar el entorno para gRPC y Protoc
Implementar un servicio gRPC
- Clonar y modificar el ejemplo de Hello World de grpc-go
- Regenerar el código de protobuf/gRPC en Go
- Ejecutar el servidor gRPC
- Invocar un servicio gRPC desde un cliente
Entorno
Para este ejercicio vamos a usar el playground de Ubuntu en Killercoda, que nos da una máquina Ubuntu desechable con Docker ya disponible. Como referencia, estoy siguiendo la guía oficial de inicio rápido de gRPC para Go y adaptándola a este escenario personalizado.
Enunciado
Implementar el ejemplo Hello World de gRPC para que acepte un Nickname (en lugar de Name) como parámetro, e invocarlo desde un proceso cliente, similar al ejemplo del sitio oficial de gRPC.
Preparar el entorno para gRPC y Protoc
1. Dentro del playground de Ubuntu en Killercoda, crear un contenedor usando la imagen oficial de Go:
docker run -it golang:1.25-bookworm /bin/bash
2. Preparar el entorno de gRPC ejecutando los siguientes comandos dentro del contenedor:
apt-get update;apt-get install unzip;apt-get install nano vim -y go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest apt-get update;apt install protobuf-compiler -y
Estos comandos instalan:
- unzip, nano, vim: utilidades básicas para descomprimir archivos y editar código.
- protoc-gen-go: el plugin de Go para el compilador de protobuf.
- protoc-gen-go-grpc: el plugin de Go que genera el código del servicio gRPC.
- protobuf-compiler (protoc): el compilador en sí, usado para generar código Go a partir de archivos .proto.
Implementar un servicio gRPC
1. Clonar el repositorio grpc-go y eliminar los archivos de protobuf pregenerados, ya que los vamos a regenerar después de nuestros cambios:
git clone -b v1.77.0 --depth 1 https://github.com/grpc/grpc-go cd grpc-go/examples/helloworld rm helloworld/helloworld.pb*
2. Modificar SayHello para que use un parámetro Nickname en lugar de Name. Necesitamos tocar tres archivos:
- helloworld/helloworld.proto: cambiar el mensaje HelloRequest para usar nickname en lugar de name.
- greeter_server/main.go: actualizar la función SayHello para leer y registrar (log) el campo Nickname.
- greeter_client/main.go: actualizar las declaraciones const y var para usar nickname (dejar la llamada final a GetMessage como GetMessage, ya que forma parte del mensaje HelloReply, no del request).
El archivo helloworld/helloworld.proto debería quedar así:
syntax = "proto3";
option go_package = "google.golang.org/grpc/examples/helloworld/helloworld";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the nickname.
message HelloRequest {
string nickname = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
En greeter_server/main.go, actualizar la implementación de SayHello para leer in.GetNickname() y registrarlo:
// server is used to implement helloworld.GreeterServer.
type server struct {
pb.UnimplementedGreeterServer
}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Printf("Nickname Received: %s", in.GetNickname())
return &pb.HelloReply{Message: "Hello " + in.GetNickname()}, nil
}
En greeter_client/main.go, actualizar las constantes y flags para usar nickname en lugar de name:
const (
address = "localhost:50051"
defaultNickname = "Linus"
)
var nickname = flag.String("nickname", defaultNickname, "Nickname to send")
Y al invocar SayHello, enviar el campo Nickname pero seguir leyendo la respuesta a través de GetMessage, ya que el mensaje de respuesta no fue modificado:
r, err := c.SayHello(ctx, &pb.HelloRequest{Nickname: *nickname})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Nickname: %s", r.GetMessage())
3. Recompilar la definición de protobuf para que las estructuras de Go y los stubs de gRPC coincidan con nuestros cambios:
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
helloworld/helloworld.proto
4. Ejecutar el servidor:
go run greeter_server/main.go
Esperar hasta ver una salida similar a esta:
2026/01/21 22:05:25 server listening at [::]:50051
Invocar un servicio gRPC desde un cliente
5. Abrir una nueva terminal y acceder al mismo contenedor en ejecución usando docker exec. Una vez dentro, ejecutar el cliente pasando un valor de nickname:
cd grpc-go/examples/helloworld go run greeter_client/main.go --nickname=linus2026
Resultados esperados
Resultado esperado en el lado del servidor:
Nickname Received: linus2026
Resultado esperado en el lado del cliente (o similar):
2026/01/23 22:12:27 Nickname: linus2026
Conclusión sobre gRPC Hello World
Este pequeño ejercicio muestra lo fácil que es adaptar el ejemplo oficial de Hello World de gRPC a un caso de uso diferente, simplemente editando el archivo .proto, regenerando los stubs con protoc, y actualizando la lógica del servidor y del cliente. Entender este flujo básico (definición del proto → generación de código → implementación del servidor → invocación del cliente) es la base para construir servicios gRPC más complejos en Go y en otros lenguajes.
¡Gracias por leer! Por último, nos vemos en mi próxima publicación.