0:0012:50

Recursos

Resumen

¿Cómo crear un servidor gRPC en Go que implemente métodos reales de lectura y escritura? En esta guía aprenderás a construir tu primer servidor gRPC conectado a un repositorio de base de datos, implementar los métodos GetStudent y SetStudent, y registrarlo para que escuche conexiones TCP. Es ideal para quienes ya definieron su capa de datos y quieren dar el salto a la comunicación entre servicios.

Antes de tocar gRPC, ya habíamos definido a nivel de base de datos y de repositorio cómo insertar y leer estudiantes. Ahora toca lo interesante: darle vida al servidor.

Cómo defino la struct del servidor y su constructor

Todo empieza creando una carpeta nueva llamada server y dentro un archivo server.go con el paquete server. Ahí defines una struct que recibe un tipo repositorio como valor interno. Ese repositorio es la puerta de entrada a la base de datos.

Luego creas el constructor NewStudentServer, que recibe un repo de tipo repository y devuelve un servidor con ese repo adentro [00:38]. Con eso tienes la base lista para implementar las funciones.

¿Para qué sirve el constructor en un servidor gRPC en Go? Sirve para inyectar dependencias, como el repositorio de base de datos, dentro de la struct del servidor. Así el servidor puede leer y escribir datos sin crear esas conexiones por su cuenta.

Un detalle práctico: antes de importar el código generado por proto buffer, conviene renombrar esa carpeta con el mismo nombre del paquete, StudentPB. Así Go no tiene problemas identificándolo al importarlo [01:25].

Cómo implemento GetStudent y SetStudent en gRPC

Aquí es donde conectas el servidor con el archivo proto que generaste previamente. Cada método recibe un contexto y un request cuyo tipo viene directamente del proto.

Qué recibe y qué devuelve GetStudent

El método GetStudent recibe un contexto y un request de tipo StudentPB.GetStudentRequest, y devuelve un StudentPB.Student junto con un error [02:00]. Dentro, pides al repositorio el estudiante usando el contexto y el ID que viene en el request.

Tienes dos formas de leer ese ID: acceder directo a la propiedad id o usar el método GetId. Ambas hacen prácticamente lo mismo, así que elige la que te resulte más cómoda [02:38].

Si hay error, retornas un valor nulo y el error. Si todo sale bien, construyes un StudentPB.Student con tres propiedades:

  • El id, que viene del student id.
  • El nombre del estudiante.
  • La edad del estudiante.

Y aquí viene un punto clave: el Student que devuelves viene del paquete StudentPB, mientras que el que lees viene del modelo de datos que definiste. No son la misma estructura de datos, son diferentes [03:30]. Confundirlas es un error común al empezar.

Cómo funciona SetStudent al insertar datos

El SetStudent cambia respecto al anterior. Su request no es un GetStudentRequest, sino un StudentPB.Student, y en vez de devolver un estudiante devuelve un StudentPB.SetStudentResponse [04:10].

Primero construyes el estudiante que mandarás al repositorio, usando el modelo models.Student con id, name y age tomados del request mediante GetId, Name y GetAge. Luego llamas a SetStudent del repositorio pasando el contexto y el estudiante.

Si el error es distinto de nulo, lo devuelves. Si la inserción fue correcta, devuelves un SetStudentResponse con el id del estudiante y un valor nulo [05:30].

Cómo levanto el servidor gRPC con un listener TCP

Con los métodos listos, creas una carpeta server/student y dentro un main.go con package main y la función main. El primer paso real es abrir un listener de conexión TCP.

Para eso usas net.Listen, especificas que es tipo TCP y defines el puerto. En este ejemplo se usa el puerto 5060, aunque es totalmente configurable [06:30]. Si algo falla, un log.Fatal con el error finaliza el programa automáticamente.

Después traes el repositorio con NewPostgresRepository usando la misma URL de cursos previos, y creas el servidor con server.NewStudentServer pasando ese repositorio [07:10].

¿Qué hace grpc.NewServer en Go? Crea una nueva instancia de servidor gRPC capaz de recibir y procesar llamadas remotas. Sobre esa instancia registras tus servicios para exponer los métodos definidos en el proto.

Luego llamas a StudentPB.RegisterStudentServiceServer, pasando la conexión gRPC y el servidor que implementa los métodos definidos [08:00].

Por qué aparece el error de interfaz y cómo lo corrijo

Al registrar el servicio es probable que aparezca un error diciendo que fallas al implementar algo. El registro espera una interfaz StudentServiceServer que tu servidor todavía no cumple [08:20].

La solución está en la composición. Vas al archivo server.go y agregas dentro de la struct del servidor el campo StudentPB.UnimplementedServiceServer.

¿Por qué Go usa composición en vez de herencia? Porque Go no tiene herencia tradicional. Al embeber una struct dentro de otra, la externa adquiere todas las propiedades y métodos de la interna. Así tu servidor hereda la implementación base requerida por la interfaz.

Con ese embebido, tu servidor pasa a poseer todas esas propiedades y cumple la definición de StudentServiceServer. Al volver al main.go, el error desaparece [09:00].

Qué es Reflection y por qué activarlo antes de iniciar

Antes de levantar el servidor conviene agregar algo llamado Reflection. Su función es proveer metadata a los clientes sobre los servicios disponibles.

Esa metadata es justo lo que necesita una herramienta como Postman para testear tu API gRPC. Por eso es importante activarlo antes de inicializar el servidor [09:40].

Finalmente levantas todo con s.Serve, pasando el listener creado al inicio. Si el error es distinto de nulo, la aplicación termina [10:10]. Con esto ya tienes tu primer servidor de estudiantes implementando SetStudent y GetStudent.

Aún falta probarlo con Postman, igual que en cursos anteriores. ¿Te animas a dejar en los comentarios en qué puerto configuraste tu servidor y por qué?