Saltar al contenido principal
eLearner.app
Módulo 5 · Lección 5 de 525/50 en el curso~10 min
Lecciones del módulo (5/5)

El patrón de constructor `New...`

Go no tiene constructor como palabra clave. La convención es una función de fábrica que devuelve un valor o puntero correctamente inicializado. Por su nombre, normalmente se llama NewT (o Newxxx).

Patrón básico: NuevoT

Go
type User struct {
    Name string
    Age  int
}

func NewUser(name string, age int) *User {
    return &User{Name: name, Age: age}
}

u := NewUser("Ada", 36)
fmt.Println(u.Name)

Ventajas sobre el literal directo &User{...}:

  • Centralizar validación y valores predeterminados.
  • Puedes tener campos no exportados y completarlos sólo desde el constructor.
  • Cambiar la implementación sin interrumpir a las personas que llaman.

Constructor con validación: (*T, error)

Cuando la inicialización pueda fallar, devuelva (*T, error):

Go
import "errors"

func NewUser(name string, age int) (*User, error) {
    if name == "" {
        return nil, errors.New("nome obbligatorio")
    }
    if age < 0 {
        return nil, errors.New("eta non valida")
    }
    return &User{Name: name, Age: age}, nil
}

u, err := NewUser("Ada", 36)
if err != nil {
    // gestisci...
}

Este es el patrón idiomático para cualquier constructor con Condiciones previas: conexión a la base de datos, identificador de archivos, configuración del servidor, etc.

Múltiples constructores

Si tiene varias "formas" de construir, utilice nombres descriptivos:

Go
func NewUser(name string) *User { ... }
func NewUserFromJSON(data []byte) (*User, error) { ... }
func NewAdmin() *User { ... }

Sin sobrecargas en Go: el nombre destaca.

Opciones funcionales (nota avanzada)

Cuando los parámetros son muchos y opcionales, el patrón idiomático es "opciones funcionales":

Go
type Option func(*Server)

func WithPort(p int) Option {
    return func(s *Server) { s.Port = p }
}

func WithTLS(cert, key string) Option {
    return func(s *Server) { s.Cert, s.Key = cert, key }
}

func NewServer(opts ...Option) *Server {
    s := &Server{Port: 8080} // default
    for _, opt := range opts {
        opt(s)
    }
    return s
}

s := NewServer(WithPort(9000), WithTLS("c.pem", "k.pem"))

Es más detallado que literal pero se adapta bien a muchos parámetros. opciones y mantiene la compatibilidad con versiones anteriores (agregue un nuevo Option no interrumpe a las personas que llaman existentes).

Cuando NO necesitas un constructor

Si el valor cero del tipo ya es útil, deje que la persona que llama use el literal directo. Ejemplo canónico: sync.Mutex no tiene constructor, var m sync.Mutex ya es un mutex listo. Lo mismo para bytes.Buffer.

Se aplica la regla: "Hacer útil el valor cero". Si lo logras nada constructor obligatorio.

Pruébalo tú mismo

Ejercicio#go.m5.l5.e1
Intentos: 0Cargando...

Escribe la función de fábrica NewUser(name string, age int) *Usuario que devuelve &User{Nombre: nombre, Edad: edad}.

Cargando editor...
Mostrar pista

Utilice el literal `&User{...}` para devolver un puntero.

Solución disponible después de 3 intentos

Ejercicio#go.m5.l5.e2
Intentos: 0Cargando...

Transforme NewUser en (cadena de nombre) (*Usuario, error): si nombre == '' devuelve nulo, errores.Nuevo('nombre requerido').

Cargando editor...
Mostrar pista

Si hay condiciones previas, devuelve (*T, error) y devuelve nil + error en caso de error.

Solución disponible después de 3 intentos

Cuestionario#go.m5.l5.e3
Listo

¿Cuál es la convención idiomática para los constructores en Go?

Go
// Quale firma è più idiomatica?
Opciones de respuesta

Resumen

  • Nada constructor: se utiliza una función NewT (o New dentro del paquete del mismo nombre).
  • Devuelve *T para el caso simple; (*T, error) con condiciones previas o validación.
  • En error: devuelve nil como puntero, el error explicativo como segundo valor.
  • Sin sobrecargas; utilice nombres descriptivos (NewUserFromJSON, NewAdmin).
  • "Hacer útil el valor cero": si lo consigues, el constructor es inútil.
  • Patrón avanzado para muchos parámetros opcionales: opciones funcionales.