Certificado de Programación con Go

20h 0m

Curso de Programación Go con certificado de superación. Domina desde la sintaxis, programación orientada a objetos y técnicas de concurrencia y comunicación HTTP en GoLang.

Accede GRATIS y certifícate

Introducción y entorno

Introducción a Go

Go, también conocido como Golang, es un lenguaje de programación desarrollado por Google que ha ganado popularidad en los últimos años gracias a su eficiencia y facilidad para manejar concurrencia. En este curso de backend con Go, exploraremos cómo este lenguaje se ha convertido en una herramienta esencial para el desarrollo backend moderno.

Historia y filosofía de Go

Go fue creado en 2009 por Robert Griesemer, Rob Pike y Ken Thompson, con el objetivo de combinar la eficiencia y seguridad de lenguajes como C++ con la simplicidad y productividad de lenguajes como Python. Su diseño se centra en la simplicidad, la legibilidad y la eficiencia, lo que lo convierte en una opción ideal para desarrollar aplicaciones backend robustas y escalables.

Usos de Go en la actualidad

En la actualidad, Go es utilizado por empresas de renombre como Google, Uber y Dropbox para construir sistemas que requieren alto rendimiento y una gestión eficaz de la concurrencia. Su capacidad para compilar código nativo y su amplio soporte para la programación concurrente lo hacen especialmente adecuado para el desarrollo de servicios web, APIs y aplicaciones de red.

Comparativa de Go con otros lenguajes de programación

A diferencia de lenguajes interpretados como Python o JavaScript, Go es un lenguaje compilado que ofrece un rendimiento cercano al de C y C++. Sin embargo, su sintaxis simplificada y características modernas lo hacen más accesible y productivo. Go se destaca por su gestión de concurrencia nativa y un sistema de tipos robusto que ayuda a prevenir errores comunes durante el desarrollo backend.

Instalación y primer programa de Go

Para comenzar a desarrollar con Go, es esencial configurar el entorno de desarrollo adecuadamente.

Estructura básica de un programa Go

Un programa en Go se estructura en paquetes. El paquete main es fundamental, ya que contiene la función main(), punto de entrada de cualquier aplicación ejecutable. Este enfoque facilita la organización y reutilización del código en proyectos de backend.

Compilación y ejecución

Go proporciona herramientas integradas para compilar y ejecutar programas de manera eficiente. Con el comando go run, se puede compilar y ejecutar un programa en un solo paso, lo que agiliza el proceso de desarrollo y prueba en entornos backend.

El paquete main y la función main

El paquete main y la función main() son esenciales en cualquier aplicación Go ejecutable. La función main() actúa como punto de inicio, y desde allí se pueden llamar a otras funciones y paquetes para construir aplicaciones backend complejas.

Paquetes e importaciones

Go utiliza paquetes para organizar el código. Los paquetes se importan utilizando la palabra clave import, lo que permite acceder a funcionalidades diversas, desde paquetes estándar hasta terceros, ampliando las capacidades de las aplicaciones backend.

Sintaxis

Tipos de datos, variables y constantes

Go es un lenguaje fuertemente tipado, lo que contribuye a la detección temprana de errores y a un código más seguro en aplicaciones backend.

Declaración y asignación de variables

Las variables en Go pueden declararse de manera explícita o implícita. La declaración explícita especifica el tipo de dato, mientras que la implícita utiliza := para que el compilador infiera el tipo.

var mensaje string = "Hola, Go"
contador := 1

Tipos de datos primitivos

Go soporta tipos como enteros (int), flotantes (float64), booleanos (bool) y cadenas (string), fundamentales para manejar datos en aplicaciones backend.

Uso de constantes con la palabra clave const

Las constantes se declaran con const y representan valores que no cambian durante la ejecución del programa, lo que es útil para definir configuraciones en servicios backend.

const puertoDefecto = 8080

Operadores y expresiones

Los operadores permiten realizar operaciones matemáticas y lógicas, esenciales en la lógica de negocio del backend.

Operadores aritméticos, lógicos y relacionales

Go incluye operadores como +, -, *, / para operaciones aritméticas, y &&, ||, ! para operaciones lógicas, facilitando la implementación de algoritmos en el backend.

Precedencia y asociatividad de operadores

La precedencia determina el orden en que se evalúan las expresiones. Comprender esto es vital para evitar errores en cálculos y condiciones en código backend.

Conversión y casting de tipos

Go requiere una conversión explícita de tipos, lo que aumenta la seguridad y claridad del código.

var entero int = 42
var flotante float64 = float64(entero)

Cadenas de texto y manipulación

La manipulación de cadenas es frecuente en el desarrollo backend, especialmente al procesar datos de entrada y generar respuestas.

Operaciones básicas con cadenas

Se pueden concatenar cadenas utilizando el operador + y obtener su longitud con la función len().

mensaje := "Hola, " + "mundo"
longitud := len(mensaje)

Uso del paquete strings

El paquete strings ofrece funciones para manipular y analizar cadenas, como Contains, Split y ToUpper, facilitando tareas comunes en el backend.

Formateo y construcción de cadenas con fmt

El paquete fmt permite formatear cadenas con funciones como Sprintf, útil para generar mensajes y logs en aplicaciones backend.

Estructuras de control

Las estructuras de control son esenciales para dirigir el flujo del programa.

Sentencias if, else if, else

Estas sentencias permiten ejecutar bloques de código basados en condiciones, fundamentales en la toma de decisiones en el backend.

if usuarioAutenticado {
    // Acceso permitido
} else {
    // Acceso denegado
}

Uso de switch y case

El switch simplifica la evaluación de múltiples condiciones, lo que mejora la legibilidad en código backend complejo.

switch metodoHTTP {
case "GET":
    // Manejar GET
case "POST":
    // Manejar POST
default:
    // Método no soportado
}

Control de flujo y estructuras de bucle

Uso del bucle for en sus distintas formas

El bucle for es la única estructura de bucle en Go, pero es muy flexible. Puede usarse como bucle tradicional, infinito o como iterador.

for i := 0; i < 10; i++ {
    // Código
}

Iteración sobre colecciones con range

El range simplifica la iteración sobre arrays, slices y mapas, común al procesar datos en el backend.

for indice, valor := range listaUsuarios {
    // Código
}

Control de bucles con break y continue

Estas instrucciones permiten controlar el flujo dentro de los bucles, lo que es útil para optimizar procesos en aplicaciones backend.

Funciones

Las funciones son bloques reutilizables que encapsulan lógica, esenciales para organizar el código en el backend.

Definición y llamada de funciones

Se definen con la palabra clave func y pueden llamarse desde otras partes del código.

func calcularSuma(a int, b int) int {
    return a + b
}

Parámetros, argumentos y valores de retorno

Las funciones pueden recibir parámetros y devolver valores, lo que permite modularizar y reutilizar código.

Valores de retorno múltiples y nombrados

Go permite que las funciones devuelvan múltiples valores, lo que es útil para retornar resultados y posibles errores.

func dividir(a, b float64) (resultado float64, err error) {
    if b == 0 {
        err = fmt.Errorf("división por cero")
        return
    }
    resultado = a / b
    return
}

Estructuras de datos

Arrays y slices

El manejo de colecciones de datos es fundamental en el desarrollo backend.

Declaración y uso de arrays

Los arrays tienen una longitud fija y almacenan elementos del mismo tipo.

var numeros [5]int

Introducción y manejo de slices

Los slices son más flexibles que los arrays y permiten trabajar con secuencias dinámicas.

clientes := []string{"Ana", "Luis", "María"}

Operaciones comunes: agregar, copiar, segmentar

Con funciones como append, se pueden agregar elementos a un slice, lo que es frecuente en operaciones de manipulación de datos en el backend.

Mapas

Los mapas asocian claves a valores y son útiles para representar relaciones en datos.

Creación y manipulación de mapas

Se crean utilizando make o literales de mapa.

edades := map[string]int{
    "Carlos": 30,
    "Laura":  25,
}

Acceso y modificación de elementos

Se puede acceder y modificar valores utilizando las claves.

edadCarlos := edades["Carlos"]
edades["Laura"] = 26

Detección de claves y eliminación de pares

Es posible comprobar si una clave existe y eliminar pares clave-valor.

if edad, existe := edades["Pedro"]; existe {
    // Código si existe
}
delete(edades, "Carlos")

Punteros y referencias

Los punteros permiten referenciar ubicaciones en memoria, lo que es útil para gestionar datos eficientemente en el backend.

Concepto de punteros en Go

Un puntero almacena la dirección de memoria de una variable.

var numero int = 42
var puntero *int = &numero

Operadores & (dirección) y * (indirección)

El operador & obtiene la dirección de una variable, y * accede al valor apuntado por un puntero.

Punteros a tipos y seguridad de memoria

Go maneja punteros de manera segura, evitando errores comunes como punteros nulos o accesos indebidos.

Programación orientada a objetos

Aunque Go no tiene clases, utiliza structs y métodos para implementar conceptos similares a la programación orientada a objetos, útiles en la organización de código backend.

Estructuras structs

Los structs agrupan campos y representan entidades.

Definición y uso de structs

type Usuario struct {
    Nombre  string
    Correo  string
    Activo  bool
}

Campos anónimos y composición

La composición se logra incrustando structs dentro de otros, promoviendo la reutilización.

type Empleado struct {
    Usuario
    IDEmpleado int
}

Comparación con clases en otros lenguajes

En lugar de herencia, Go utiliza composición, lo que facilita la creación de estructuras más flexibles en el backend.

Métodos con receptores por valor y por puntero

Asociar métodos a tipos definidos

Se pueden definir métodos asociados a un struct.

func (u Usuario) Saludar() {
    fmt.Println("Hola,", u.Nombre)
}

Receptores por valor y por puntero

Los métodos pueden tener receptores por valor o por puntero, lo que afecta si se modifica el estado del objeto.

func (u *Usuario) Activar() {
    u.Activo = true
}

Encapsulación y acceso a datos

El uso de mayúsculas determina la visibilidad de campos y métodos, permitiendo controlar el acceso desde otros paquetes.

Modificación de estado en métodos

Los receptores por puntero permiten modificar los valores del struct, esencial en operaciones de actualización en el backend.

Polimorfismo a través de interfaces

Cómo definir e implementar interfaces en Go

Las interfaces declaran métodos que un tipo debe implementar.

type Notificador interface {
    EnviarNotificacion(mensaje string) error
}

Polimorfismo basado en interfaces

Permite que diferentes tipos sean tratados de la misma manera si cumplen con la misma interfaz, lo que es útil al diseñar sistemas extensibles en el backend.

Uso de interfaces vacías (interface{}) y su aplicación

La interfaz vacía puede contener cualquier tipo, pero su uso debe ser cuidadoso para mantener la claridad del código.

Composición de structs en lugar de herencia

Incrustación de structs y reutilización de código

La composición se logra incrustando un struct dentro de otro, lo que promueve la reutilización sin los problemas de la herencia múltiple.

Ejemplos de composición vs herencia clásica

La composición permite crear estructuras más flexibles y modulares, lo que facilita el mantenimiento y la evolución de aplicaciones backend.

Cómo la composición promueve la flexibilidad

Al evitar la rigidez de la herencia, la composición facilita la adaptación del código a nuevas necesidades sin reestructuraciones significativas.

Generics

Cómo definir funciones y tipos genéricos

Los generics permiten crear funciones y tipos que pueden trabajar con cualquier tipo de dato.

func Filtrar[T any](datos []T, criterio func(T) bool) []T {
    var resultado []T
    for _, item := range datos {
        if criterio(item) {
            resultado = append(resultado, item)
        }
    }
    return resultado
}

Restricciones de tipos mediante type constraints

Se pueden definir restricciones para especificar qué tipos son aceptables en los generics.

Ejemplos de uso de generics

Los generics simplifican el código y evitan la duplicación, lo que mejora la eficiencia en el desarrollo backend.

Manejo de errores y excepciones

El manejo adecuado de errores es esencial para crear aplicaciones backend fiables y robustas.

Manejo explícito de errores

En Go, los errores se manejan de manera explícita, lo que fuerza al desarrollador a considerar y tratar las posibles fallas.

Retorno de tipo error en funciones

Las funciones suelen devolver un valor y un error.

func leerArchivo(nombre string) ([]byte, error) {
    datos, err := os.ReadFile(nombre)
    if err != nil {
        return nil, err
    }
    return datos, nil
}

Propagación de errores

Es común propagar errores hacia arriba para ser manejados en un nivel superior, manteniendo así la claridad en el flujo de errores.

Evitar el manejo de errores silencioso

Ignorar errores puede llevar a comportamientos inesperados, por lo que siempre se deben manejar o propagar.

Errores personalizados y wrapping para mejorar la trazabilidad

Creación de errores personalizados

Se pueden crear errores con mensajes específicos que aporten contexto.

err := fmt.Errorf("fallo al conectar con la base de datos: %v", errOriginal)

Cómo envolver errores con fmt.Errorf

El wrapping de errores ayuda a mantener la información original del error mientras se añade contexto adicional, esencial en la depuración de aplicaciones backend.

Uso de errors.Is y errors.As

Estas funciones permiten comparar y extraer información de errores envueltos.

Casos prácticos de wrapping de errores

El uso adecuado de wrapping mejora la capacidad para diagnosticar y resolver problemas.

Mantener la trazabilidad

Proporcionar información detallada en errores facilita el mantenimiento y mejora la calidad del software backend.

Comunicación por HTTP

La comunicación por HTTP es fundamental en aplicaciones backend modernas.

Métodos HTTP con net/http

El paquete net/http facilita la creación de clientes y servidores HTTP.

Realizar peticiones HTTP GET

Para obtener recursos de un servidor.

resp, err := http.Get("https://api.ejemplo.com/datos")

Realizar peticiones HTTP POST

Para enviar datos al servidor.

resp, err := http.Post("https://api.ejemplo.com/crear", "application/json", cuerpo)

Realizar peticiones HTTP PUT y PATCH

Para actualizar recursos existentes.

Realizar peticiones HTTP DELETE

Para eliminar recursos.

API REST con net/http

Se pueden crear APIs REST sin necesidad de frameworks adicionales.

Configurar una API REST JSON sin framework

Definiendo handlers y utilizando el paquete encoding/json para manejar datos JSON.

Recibir peticiones GET y POST

Manejando diferentes rutas y métodos HTTP para crear endpoints funcionales.

Concurrencia y paralelismo

Go destaca por su manejo eficiente de la concurrencia, lo que es crucial para aplicaciones backend de alto rendimiento.

Goroutines y concurrencia básica

Cómo crear y manejar goroutines

Las goroutines son funciones que se ejecutan concurrentemente, facilitando la ejecución de tareas en paralelo.

go procesarSolicitud(solicitud)

Uso de WaitGroup para gestionar ciclos de vida

Los WaitGroup permiten esperar a que un conjunto de goroutines finalice antes de continuar.

var wg sync.WaitGroup
wg.Add(1)
go func() {
    defer wg.Done()
    // Código
}()
wg.Wait()

Ejemplos de ejecución concurrente

La concurrencia mejora la capacidad de respuesta y el rendimiento en aplicaciones backend que manejan múltiples conexiones o tareas.

Canales y comunicación entre goroutines

Creación y uso de canales

Los canales permiten la comunicación segura entre goroutines.

canal := make(chan string)

Cómo enviar y recibir datos entre goroutines

Se pueden enviar y recibir datos a través de canales, sincronizando la ejecución.

canal <- "mensaje"
mensaje := <-canal

Patrones comunes: productor-consumidor y Fan-in/Fan-out

Estos patrones optimizan el procesamiento de tareas y mejoran la escalabilidad.

Condiciones de carrera

Qué es una condición de carrera

Ocurre cuando varias goroutines acceden y modifican una variable compartida sin la debida sincronización.

Cómo detectar condiciones de carrera

Go proporciona la herramienta -race para detectar condiciones de carrera.

go run -race main.go

Cómo solucionar condiciones de carrera

Utilizando mutexes o canales para sincronizar el acceso a recursos compartidos.

Selectores y mutexes: concurrencia y exclusión mutua

Uso del select para gestionar múltiples canales

El select permite esperar en múltiples operaciones de canal, lo que es útil para manejar múltiples fuentes de datos concurrentemente.

select {
case msg := <-canal1:
    // Manejar msg de canal1
case alerta := <-canal2:
    // Manejar alerta de canal2
}

Uso de mutexes para sincronización explícita

Los mutexes protegen secciones críticas, asegurando que solo una goroutine acceda a una sección de código a la vez.

var mu sync.Mutex
mu.Lock()
// Sección crítica
mu.Unlock()

Ejemplos de patrones concurrentes

Implementar correctamente la concurrencia es esencial para desarrollar aplicaciones backend eficientes y libres de errores.

Empezar curso GRATIS

Tutoriales de programación en este certificado

Completa estas lecciones de programación para obtener tu certificado de superación

Ejercicios de programación de Programación con Go

Completa estos ejercicios de programación para obtener tu certificado de superación

Otros cursos de programación con certificado

Supera todos los retos de Programación con Go y obtén estos certificados de superación para mejorar tu currículum y tu empleabilidad.

Tecnologías que aprenderás

Programación con Go

Al finalizar este curso obtendrás

Certificado de superación en Programación con Go

Certificado de superación en Programación con Go

Tras completar todas las lecciones y ejercicios del curso Programación con Go se te genera un enlace con tu certificado para que lo puedas descargar o compartir directamente en cualquier plataforma, siempre accesible.

Accede GRATIS a las certificaciones