Patrones de diseño en Go: ejemplos y aplicación práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: Por qué los patrones de diseño son importantes en Go



Go (Golang) es un lenguaje compilado moderno, creado en Google para resolver problemas de sistemas de alta carga. A pesar de su simplicidad y concisión, el desarrollo en Go requiere comprensión de los patrones de diseño — soluciones probadas para problemas típicos. En este artículo analizaremos los patrones principales con ejemplos de código que te ayudarán a escribir un código más limpio, escalable y mantenible.



¿Por qué es importante? Go no soporta la POO clásica (herencia, sobrecarga de métodos), pero ofrece mecanismos potentes — interfaces, composición y gorutinas. Los patrones se adaptan a estas características, lo que los hace especialmente efectivos.



Patrones creacionales (Creational)



Los patrones creacionales gestionan el proceso de creación de objetos. En Go a menudo se implementan mediante funciones constructoras e interfaces.



1. Singleton (Singleton)



Garantiza que una clase tiene una única instancia y proporciona un punto de acceso global a ella. En Go esto es especialmente relevante para configuraciones, loggers y pools de conexiones.



package main

import ( "fmt" "sync")

type Config struct { Port int Host string}

var ( instance *Config once sync.Once)

func GetConfig() *Config { once.Do(func() { instance = &Config{ Port: 8080, Host: "localhost", } }) return instance}

func main() { cfg1 := GetConfig() cfg2 := GetConfig() fmt.Println(cfg1 == cfg2) // true}


Explicación: sync.Once garantiza que la inicialización ocurra solo una vez, incluso con acceso concurrente. Esta es la forma idiomática estándar de implementar Singleton en Go.



2. Factory Method (Método de fábrica)



Define una interfaz para crear un objeto, pero permite que las subclases alteren el tipo de objetos creados. En Go se implementa mediante funciones que devuelven una interfaz.



package main

import "fmt"

// Interfaz del productotype Transport interface { Deliver() string}

// Productos concretostype Truck struct{}func (t *Truck) Deliver() string { return "Entrega por tierra" }

type Ship struct{}func (s *Ship) Deliver() string { return "Entrega por mar" }

// Método de fábricafunc CreateTransport(transportType string) Transport { switch transportType { case "land": return &Truck{} case "sea": return &Ship{} default: return nil }}

func main() { transport := CreateTransport("sea") fmt.Println(transport.Deliver()) // Entrega por mar}


3. Builder (Constructor)



Permite crear objetos complejos paso a paso. Es ideal para objetos con múltiples parámetros opcionales.



package main

import "fmt"

type Pizza struct { Dough string Sauce string Toppings []string}

type PizzaBuilder struct { dough string sauce string toppings []string}

func NewPizzaBuilder() *PizzaBuilder { return &PizzaBuilder{}}

func (b *PizzaBuilder) SetDough(dough string) *PizzaBuilder { b.dough = dough return b}

func (b *PizzaBuilder) SetSauce(sauce string) *PizzaBuilder { b.sauce = sauce return b}

func (b *PizzaBuilder) AddTopping(topping string) *PizzaBuilder { b.toppings = append(b.toppings, topping) return b}

func (b *PizzaBuilder) Build() *Pizza { return &Pizza{ Dough: b.dough, Sauce: b.sauce, Toppings: b.toppings, }}

func main() { pizza := NewPizzaBuilder(). SetDough("fina"). SetSauce("tomate"). AddTopping("queso"). AddTopping("champiñones"). Build() fmt.Printf("Pizza: %+v", pizza)}


Pa

Blogs

Book Recommendations