Fundamentos de Go para Web

Por: Artiko
gofundamentosstructssliceserrores

Fundamentos de Go para Web

Este capitulo cubre lo esencial de Go para seguir el tutorial. Si quieres profundizar, visita el tutorial completo de Go.

Variables y tipos basicos

// Declaracion corta (lo mas comun)
nombre := "Artiko"
edad := 30
activo := true

// Declaracion explicita
var contador int = 0
var mensaje string

Go es de tipado estatico: una vez que una variable tiene un tipo, no puede cambiar.

Los tipos basicos que usaremos:

TipoEjemploUso
string"hola"Textos, titulos de tareas
int42IDs, contadores
booltrueEstados (completado/pendiente)
float643.14Numeros decimales

Structs

Los structs son la forma de definir modelos de datos en Go. Son como clases pero sin herencia:

type Todo struct {
    ID          int
    Title       string
    Completed   bool
}

// Crear un todo
tarea := Todo{
    ID:        1,
    Title:     "Aprender Go",
    Completed: false,
}

// Acceder a campos
fmt.Println(tarea.Title) // "Aprender Go"
tarea.Completed = true

Slices

Un slice es una lista dinamica de elementos del mismo tipo:

// Crear un slice vacio
tareas := []Todo{}

// Agregar elementos
tareas = append(tareas, Todo{ID: 1, Title: "Comprar pan"})
tareas = append(tareas, Todo{ID: 2, Title: "Estudiar Go"})

// Acceder por indice
primera := tareas[0]

// Iterar
for _, tarea := range tareas {
    fmt.Println(tarea.Title)
}

// Longitud
fmt.Println(len(tareas)) // 2

Filtrar un slice

Go no tiene .filter() como JavaScript. Se usa un patron manual:

func filtrarCompletadas(tareas []Todo) []Todo {
    resultado := []Todo{}
    for _, t := range tareas {
        if t.Completed {
            resultado = append(resultado, t)
        }
    }
    return resultado
}

Maps

Un map asocia claves con valores. Util para busquedas rapidas por ID:

// Crear un map de ID -> Todo
todosMap := map[int]Todo{
    1: {ID: 1, Title: "Comprar pan"},
    2: {ID: 2, Title: "Estudiar Go"},
}

// Buscar por ID
tarea, existe := todosMap[1]
if existe {
    fmt.Println(tarea.Title)
}

// Agregar
todosMap[3] = Todo{ID: 3, Title: "Nueva tarea"}

// Eliminar
delete(todosMap, 2)

Funciones y multiples retornos

Las funciones en Go pueden retornar multiples valores. Esto es fundamental para el manejo de errores:

func buscarTodo(id int, todos []Todo) (Todo, bool) {
    for _, t := range todos {
        if t.ID == id {
            return t, true
        }
    }
    return Todo{}, false
}

// Uso
tarea, encontrada := buscarTodo(1, misTareas)
if !encontrada {
    fmt.Println("No existe")
}

Punteros

Un puntero es una referencia a la direccion de memoria de una variable. Se usan para modificar datos sin copiarlos:

// & obtiene la direccion
tarea := Todo{ID: 1, Title: "Original"}
puntero := &tarea

// * accede al valor apuntado
puntero.Title = "Modificado"
fmt.Println(tarea.Title) // "Modificado"

En el contexto web, los punteros son utiles para modificar datos en el store sin copiar structs completos:

func (s *Store) completarTodo(id int) {
    for i := range s.todos {
        if s.todos[i].ID == id {
            s.todos[i].Completed = true
            return
        }
    }
}

Manejo de errores

Go no tiene excepciones. Los errores son valores que se retornan y verifican explicitamente:

import "errors"

func crearTodo(title string) (Todo, error) {
    if title == "" {
        return Todo{}, errors.New("el titulo no puede estar vacio")
    }
    return Todo{ID: 1, Title: title}, nil
}

// Uso: SIEMPRE verificar el error
tarea, err := crearTodo("")
if err != nil {
    fmt.Println("Error:", err)
    return
}
fmt.Println(tarea.Title)

El patron if err != nil es el mas comun en Go. Lo veras en cada handler HTTP.

Packages e imports

Cada archivo Go pertenece a un package. El package main es el punto de entrada:

package main

import (
    "fmt"
    "net/http"
    "todo-htmx/handlers"  // package local
    "todo-htmx/models"    // package local
)

Reglas:

// models/todo.go
package models

type Todo struct {    // Publico: accesible desde otros packages
    ID    int
    Title string
}

type validador struct { // Privado: solo dentro de package models
    // ...
}

Resumen

ConceptoUso en el proyecto
StructsModelo Todo con ID, Title, Completed
SlicesLista de tareas []Todo
MapsBusqueda rapida por ID map[int]Todo
Multiples retornos(valor, error) en cada operacion
PunterosModificar tareas en el store
PackagesSeparar handlers, models, store, templates

Para un estudio mas profundo de Go, consulta el tutorial completo de Go.