Menu
Coddy logo textTech

Interfaces Stringer y Error

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 32 de 107.

La biblioteca estándar de Go define dos interfaces que usarás constantemente: fmt.Stringer y error. Ambas son interfaces sencillas de un solo método que otorgan a tus tipos una potente integración con la funcionalidad integrada de Go.

La interfaz Stringer reside en el paquete fmt y requiere solo un método:

type Stringer interface {
    String() string
}

Cuando implementas String() en tu tipo, funciones como fmt.Println lo usan automáticamente para mostrar tu valor:

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)  // Alice (30 años)
}

La interfaz error es igualmente sencilla, ya que requiere un método Error() que devuelve una cadena:

type error interface {
    Error() string
}

Cualquier tipo con un método Error() puede ser utilizado como un valor de error en Go. Esto permite crear tipos de error personalizados con contexto adicional:

type ValidationError struct {
    Field   string
    Message string
}

func (e ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func main() {
    err := ValidationError{Field: "email", Message: "invalid format"}
    fmt.Println(err)  // email: invalid format
}

Estas dos interfaces demuestran la filosofía de Go: interfaces pequeñas y enfocadas que desbloquean un comportamiento potente a través de la implementación implícita.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de monitoreo de temperatura que utiliza las interfaces Stringer y error para proporcionar una salida legible y un manejo de errores significativo.

Organizarás tu código en dos archivos:

  • temperature.go: Crea una estructura Temperature con los campos Value (float64) y Unit (string). Implementa el método String() para que, al imprimirse, muestre la temperatura en un formato legible para humanos. También crea una estructura TemperatureError con los campos Temp (float64) y Reason (string), e implementa el método Error() para proporcionar mensajes de error descriptivos.
  • main.go: Crea una función llamada ValidateTemperature que reciba una Temperature y devuelva un error si la temperatura no es válida. Una temperatura no es válida si está por debajo del cero absoluto (-273.15 para Celsius, -459.67 para Fahrenheit). Si es válida, la función devuelve nil. Lee los datos de temperatura de la entrada, crea una Temperature, valídala e imprime la salida apropiada.

Se proporcionarán las siguientes entradas:

  • Línea 1: Valor de la temperatura (float)
  • Línea 2: Unidad (C para Celsius o F para Fahrenheit)

Tu método String() debe devolver el formato:

[Value] degrees [Unit]

Donde Unit es la palabra completa "Celsius" o "Fahrenheit" basada en la entrada.

Tu método Error() debe devolver el formato:

invalid temperature [Temp]: [Reason]

Si la temperatura es válida, imprime la Temperature usando fmt.Println (que utilizará tu método String()). Si no es válida, imprime el error (que utilizará tu método Error()).

Por ejemplo, dados 25.5 y C, tu salida debería ser:

25.5 degrees Celsius

Dados -500 y F, tu salida debería ser:

invalid temperature -500: below absolute zero

Usa "below absolute zero" como la razón (reason) cuando la temperatura sea demasiado baja.

Hoja de referencia

La biblioteca estándar de Go define dos interfaces esenciales: fmt.Stringer y error.

La interfaz Stringer

La interfaz Stringer del paquete fmt requiere un método:

type Stringer interface {
    String() string
}

Cuando implementas String() en tu tipo, funciones como fmt.Println lo utilizan automáticamente:

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)  // Alice (30 years old)
}

La interfaz error

La interfaz error requiere un método Error() que devuelve una cadena:

type error interface {
    Error() string
}

Cualquier tipo con un método Error() puede ser utilizado como un valor de error, permitiendo tipos de error personalizados con contexto adicional:

type ValidationError struct {
    Field   string
    Message string
}

func (e ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func main() {
    err := ValidationError{Field: "email", Message: "invalid format"}
    fmt.Println(err)  // email: invalid format
}

Pruébalo tú mismo

package main

import (
	"fmt"
)

// ValidateTemperature comprueba si una temperatura es válida
// Devuelve un error si la temperatura es inferior al cero absoluto
// Cero absoluto: -273.15 para Celsius, -459.67 para Fahrenheit
func ValidateTemperature(t Temperature) error {
	// TODO: Implementar la lógica de validación
	// Comprobar si la temperatura es inferior al cero absoluto según la unidad
	// Devolver un TemperatureError si no es válida, nil si es válida
	return nil
}

func main() {
	var value float64
	var unit string
	fmt.Scanln(&value)
	fmt.Scanln(&unit)

	// TODO: Crear una estructura Temperature con los valores de entrada

	// TODO: Validar la temperatura usando ValidateTemperature

	// TODO: Si hay un error, imprimir el error
	// De lo contrario, imprimir la temperatura (que usará el método String())
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos