Hoja de referencia de Golang

Comandos y construcciones útiles de Go

Índice

Aquí tienes la estructura básica de un programa Go, patrones de manejo de errores y comparación entre canales y goroutines.

bunnies around golang sign

Cheatsheet del lenguaje Go

Sintaxis básica

Declaración del paquete

package main

Importar paquetes

import "fmt"
import (
    "fmt"
    "math"
)

Función principal

func main() {
    // Tu código aquí
}

Variables y tipos

Declaración de variable

var name string
var age int = 25
x := 10 // Declaración corta

Tipos básicos

  • bool
  • string
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • float32, float64
  • complex64, complex128

Estructuras de control

Instrucción if

if x > 0 {
    // código
} else if x < 0 {
    // código
} else {
    // código
}

Bucle for

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

Bucle range

for index, value := range collection {
    // código
}

Instrucción switch

switch variable {
case value1:
    // código
case value2:
    // código
default:
    // código
}

Funciones

Declaración de función

func functionName(param1 type1, param2 type2) returnType {
    // código
    return value
}

Valores de retorno múltiples

func divideAndRemainder(x, y int) (int, int) {
    return x / y, x % y
}

Estructuras de datos

Arreglos

var numbers int
numbers := int{1, 2, 3, 4, 5}

Rebanadas (slices)

slice := []int{1, 2, 3}
slice := make([]int, 3, 5)

Mapas

m := make(map[string]int)
m["key"] = value

Estructuras

type Person struct {
    Name string
    Age  int
}
p := Person{Name: "Alice", Age: 30}

Métodos

Declaración de método

func (r Rectangle) Area() float64 {
    return r.width * r.height
}

Interfaces

Declaración de interfaz

type Shape interface {
    Area() float64
}

Concurrencia

Goroutines

go functionName()

Canales

ch := make(chan int)
ch <- value  // Enviar
value := <-ch  // Recibir

Manejo de errores

Verificación de errores

if err != nil {
    // Manejar el error
}

Defer

defer file.Close()

Pruebas

Función de prueba

func TestFunction(t *testing.T) {
    // Código de prueba
}

Este cheat sheet cubre las construcciones y comandos más esenciales del lenguaje Go. Incluye sintaxis básica, estructuras de control, funciones, estructuras de datos, métodos, interfaces, primitivas de concurrencia y manejo de errores. Recuerda que Go enfatiza la simplicidad y la legibilidad, por lo que estas construcciones forman la base para escribir código Go eficiente y claro.

Manejo de errores en Go

El manejo de errores en Go es directo y explícito, enfatizando la claridad y la robustez. Aquí tienes las técnicas clave para manejar errores en Go:

  1. Devolver errores como valores: Las funciones que pueden fallar deben devolver un error como su último valor de retorno. Por ejemplo:
func Hello(name string) (string, error) {
    if name == "" {
        return "", errors.New("nombre vacío")
    }
    message := fmt.Sprintf("Hola, %v. Bienvenido!", name)
    return message, nil
}
  1. Siempre verificar errores: Después de llamar a una función que devuelve un error, verificar inmediatamente si el error no es nulo. Por ejemplo:
result, err := SomeFunction()
if err != nil {
    // Manejar el error
    log.Fatal(err)
}
  1. Usar el envoltorio de errores: Al propagar errores hacia arriba en la pila de llamadas, envuélvelos para añadir contexto usando fmt.Errorf() con el verbo %w. Por ejemplo:
f, err := os.Open(path)
if err != nil {
    return nil, fmt.Errorf("fallo al abrir: %w", err)
}
  1. Utilizar defer para limpieza: Usa defer para asegurarte de que los recursos se cierren o limpien correctamente, incluso si ocurre un error.

  2. Crear tipos de error personalizados: Implementa la interfaz error para tipos de error personalizados para proporcionar información de error más detallada.

  3. Usar el paquete errors: Aprovecha funciones como errors.New() para crear mensajes de error simples, y errors.Is() o errors.As() para comprobación y conversión de tipos de error.

  4. Evitar el uso de panic: Reserva panic para situaciones verdaderamente irrecoverables. El manejo normal de errores debe usar valores de retorno.

  5. Proporcionar información de error explícita: Haz que los mensajes de error sean claros e informativos para ayudar en la depuración y solución de problemas.

Siguiendo estas prácticas, puedes crear programas Go robustos que manejen errores de manera efectiva y mantengan la claridad del código.

Mejores prácticas para goroutines y canales en Go

Uso eficiente de goroutines

  1. Evitar la creación excesiva de goroutines: Crea goroutines con juicio, considerando la naturaleza de la tarea y si realmente se beneficia de la ejecución paralela.

  2. Sincronización adecuada: Usa mecanismos de sincronización como canales o grupos de espera para gestionar eficazmente las goroutines y evitar el desperdicio de recursos.

  3. Considerar la naturaleza de la tarea: Evalúa si una tarea realmente se beneficia de la ejecución concurrente antes de usar goroutines.

Uso efectivo de canales

  1. Elegir el tipo de canal adecuado: Usa canales no缓冲 para sincronización y canales缓冲 cuando necesites desacoplar las operaciones de envío y recepción.

  2. Capacidad del buffer: Cuando uses canales缓冲, considera cuidadosamente el tamaño del buffer para equilibrar el rendimiento y el uso de recursos.

  3. Cerrar canales correctamente: Asegúrate de cerrar los canales cuando ya no se enviarán más datos para evitar bloqueos y fugas de recursos.

Patrones de concurrencia

  1. Patrón de piscina de trabajadores: Implementa piscinas de trabajadores usando goroutines y canales para una distribución eficiente de tareas y recolección de resultados.

  2. Patrón productor-consumidor: Usa goroutines como productores y consumidores, con canales facilitando el flujo de datos entre ellos.

Manejo de errores y gestión de recursos

  1. Usar defer para limpieza: Emplea declaraciones defer para asegurar una limpieza adecuada de recursos, incluso en presencia de errores.

  2. Manejar panics: Implementa recover() en goroutines de larga duración para evitar que todo el programa se detenga debido a un panic en una sola goroutine.

Comunicación y sincronización

  1. Preferir canales sobre memoria compartida: Usa canales para la comunicación entre goroutines para evitar condiciones de carrera y simplificar la sincronización.

  2. Usar select para múltiples canales: Emplea la instrucción select para manejar operaciones de múltiples canales concurrentemente.

Consideraciones de rendimiento

  1. Limitar operaciones concurrentes: Usa semáforos o piscinas de trabajadores para limitar el número de operaciones concurrentes y evitar el agotamiento de recursos.

  2. Evitar la optimización prematura: Analiza tu código para identificar cuellos de botella antes de aplicar optimizaciones de concurrencia.

Pruebas y depuración

  1. Usar el detector de carreras: Ejecuta regularmente tus pruebas con la bandera -race para detectar carreras de datos.

  2. Escribir pruebas concurrentes: Crea pruebas que ejerzan específicamente tus rutas de código concurrente para asegurar su fiabilidad.

Siguiendo estas mejores prácticas, puedes aprovechar eficazmente el modelo de concurrencia de Go, haciendo que tus programas sean más eficientes, mantenibles y menos propensos a problemas comunes relacionados con la concurrencia.

Ver otros artículos del blog técnico.

Actualizar golang en Linux

  1. Ve y descarga la nueva versión: https://go.dev/doc/install
  2. Elimina la antigua:
sudo rm -rf /usr/local/go
  1. Instala la nueva:
cd Downloads
sudo tar -C /usr/local -xzf go1.24.3.linux-amd64.tar.gz

Enlaces útiles