Menu
Coddy logo textTech

Fundamentos de Reflection

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy. Lección 83 de 107.

Reflexión permite que un programa examine y manipule su propia estructura en tiempo de ejecución. El paquete reflect de Go proporciona esta capacidad, lo que permite inspeccionar tipos, leer campos de estructuras y llamar a métodos dinámicamente.

Los dos tipos fundamentales de la reflexión son reflect.Type y reflect.Value. Los obtienes mediante reflect.TypeOf() y reflect.ValueOf():

import "reflect"

type Person struct {
    Name string
    Age  int
}

p := Person{Name: "Alice", Age: 30}

t := reflect.TypeOf(p)
v := reflect.ValueOf(p)

fmt.Println(t.Name())       // Person
fmt.Println(t.Kind())       // struct
fmt.Println(v.NumField())   // 2

Puedes iterar sobre los campos de una estructura para examinar sus nombres, tipos y valores:

for i := 0; i < t.NumField(); i++ {
    field := t.Field(i)
    value := v.Field(i)
    fmt.Printf("%s: %v\n", field.Name, value)
}
// Salida:
// Name: Alice
// Age: 30

La reflexión es potente, pero conlleva ciertas desventajas: omite la comprobación de tipos en tiempo de compilación, se ejecuta más lentamente que el acceso directo y hace que el código sea más difícil de entender. Úsala con moderación para tareas como la serialización JSON, la asignación ORM o la creación de utilidades genéricas cuando el tipo no se conoce en tiempo de compilación.

challenge icon

Desafío

Fácil

¡Construyamos un inspector de estructuras que use la reflexión para examinar cualquier estructura e informar sobre su estructura! Este es un caso de uso práctico de la reflexión: crear utilidades que funcionen con tipos desconocidos en tiempo de compilación.

Organizarás tu código en dos archivos:

  • inspector.go: Crea tu utilidad de inspección basada en la reflexión.

    Construye una función InspectStruct(v any) string que use el paquete reflect para examinar cualquier estructura que se le pase. Tu función debe devolver un informe con formato que contenga:

    • El nombre del tipo de la estructura
    • El tipo de la estructura (debería ser "struct")
    • El número de campos
    • Para cada campo: el nombre del campo, su tipo y su valor actual

    El formato de salida debe ser:

    Type: [TypeName]
    Kind: struct
    Fields: [count]
    - [FieldName] ([FieldType]): [Value]
    - [FieldName] ([FieldType]): [Value]
    ...

    Usa reflect.TypeOf() para obtener información del tipo y reflect.ValueOf() para acceder a los valores de los campos. Recorre los campos usando NumField(), Field(i) sobre el tipo para los metadatos y Field(i) sobre el valor para obtener los valores reales.

  • main.go: Define estructuras de ejemplo y usa tu inspector.

    Lee un tipo de estructura (product o employee) y los valores de sus campos; después, crea la estructura correspondiente e inspecciónala.

    Para product: Crea una estructura Product con campos Name (string), Price (float64) e InStock (bool). Lee el nombre, el precio y el estado de existencias.

    Para employee: Crea una estructura Employee con campos ID (int), Name (string) y Department (string). Lee el ID, el nombre y el departamento.

    Pasa la estructura creada a InspectStruct e imprime el resultado.

Se proporcionarán las siguientes entradas:

  • Línea 1: Tipo de estructura (product o employee)
  • Líneas siguientes: Valores de los campos para ese tipo de estructura

Por ejemplo, dada la siguiente entrada:

product
Laptop
999.99
true

Tu salida debe ser:

Type: Product
Kind: struct
Fields: 3
- Name (string): Laptop
- Price (float64): 999.99
- InStock (bool): true

Y dada la siguiente entrada:

employee
42
Alice Johnson
Engineering

Tu salida debe ser:

Type: Employee
Kind: struct
Fields: 3
- ID (int): 42
- Name (string): Alice Johnson
- Department (string): Engineering

Y dada la siguiente entrada:

product
Headphones
79.50
false

Tu salida debe ser:

Type: Product
Kind: struct
Fields: 3
- Name (string): Headphones
- Price (float64): 79.5
- InStock (bool): false

Observa cómo tu inspector funciona con distintos tipos de estructuras sin conocer su estructura de antemano. ¡Este es el poder de la reflexión! La misma función InspectStruct gestiona dinámicamente tanto las estructuras Product como las estructuras Employee.

Pruébalo tú mismo

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// Estructura Product con los campos Name, Price e InStock
type Product struct {
	Name    string
	Price   float64
	InStock bool
}

// Estructura Employee con los campos ID, Name y Department
type Employee struct {
	ID         int
	Name       string
	Department string
}

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Leer el tipo de struct
	structType, _ := reader.ReadString('\n')
	structType = strings.TrimSpace(structType)

	if structType == "product" {
		// Leer los campos del product
		name, _ := reader.ReadString('\n')
		name = strings.TrimSpace(name)

		priceStr, _ := reader.ReadString('\n')
		priceStr = strings.TrimSpace(priceStr)
		price, _ := strconv.ParseFloat(priceStr, 64)

		inStockStr, _ := reader.ReadString('\n')
		inStockStr = strings.TrimSpace(inStockStr)
		inStock, _ := strconv.ParseBool(inStockStr)

		// TODO: Crear un struct Product con los valores leídos
		// TODO: Llamar a InspectStruct con el product e imprimir el resultado

	} else if structType == "employee" {
		// Leer los campos del employee
		idStr, _ := reader.ReadString('\n')
		idStr = strings.TrimSpace(idStr)
		id, _ := strconv.Atoi(idStr)

		name, _ := reader.ReadString('\n')
		name = strings.TrimSpace(name)

		department, _ := reader.ReadString('\n')
		department = strings.TrimSpace(department)

		// TODO: Crear un struct Employee con los valores leídos
		// TODO: Llamar a InspectStruct con el employee e imprimir el resultado

	}
}
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

Practica por tu cuenta: Compilador de Go online