Structs anidados
Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 16 de 107.
Una struct anidada es una struct que contiene otra struct con nombre como uno de sus campos. Esto te permite modelar datos complejos y jerárquicos mediante la composición de tipos más pequeños y reutilizables.
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // estructura anidada
}Para acceder a los campos en una estructura anidada, se encadenan los nombres de los campos con puntos.
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // BostonEl anidamiento promueve la reutilización de código. El tipo Address puede ser utilizado en múltiples estructuras como Person, Company o Order sin duplicar campos. Este enfoque refleja las relaciones del mundo real donde las entidades contienen otras entidades.
type Company struct {
Name string
Employees int
Address Address // se reutiliza el mismo tipo Address
}Puedes anidar structs a varios niveles de profundidad, aunque mantener las jerarquías poco profundas mejora la legibilidad. Los structs anidados son fundamentales para construir modelos de datos orientados a objetos en Go.
Desafío
FácilVamos a construir un sistema de gestión de empleados que demuestre cómo los structs anidados ayudan a modelar jerarquías del mundo real. Crearás una estructura donde los empleados pertenecen a departamentos, y los departamentos tienen información de ubicación.
Organizarás tu código en dos archivos:
models.go: Define tres structs que trabajen juntos:Locationcon los camposBuilding(string) yFloor(int)DepartmentconName(string) y un campo anidadoLocationEmployeeconID(int),Name(string), y un campo anidadoDepartment
main.go: Lee la información del empleado desde la entrada, crea un Employee con los structs anidados correctamente y muestra el perfil completo del empleado accediendo a los campos a través de la estructura anidada.
Se proporcionarán las siguientes entradas:
- Línea 1: ID del empleado (entero)
- Línea 2: Nombre del empleado
- Línea 3: Nombre del departamento
- Línea 4: Nombre del edificio
- Línea 5: Número de piso (entero)
Formato de salida:
Employee: [Name] (ID: [ID])
Department: [DepartmentName]
Location: [Building], Floor [Floor]Por ejemplo, dados 101, Alice Chen, Engineering, Tower A, y 5, tu salida debería ser:
Employee: Alice Chen (ID: 101)
Department: Engineering
Location: Tower A, Floor 5Accede a los campos anidados utilizando la notación de punto para encadenar a través de la jerarquía de structs (por ejemplo, employee.Department.Location.Building).
Pruébalo tú mismo
package main
import "fmt"
func main() {
// Leer la información del empleado
var id int
var name string
var deptName string
var building string
var floor int
fmt.Scanln(&id)
fmt.Scanln(&name)
fmt.Scanln(&deptName)
fmt.Scanln(&building)
fmt.Scanln(&floor)
// TODO: Crear un Employee con structs anidados correctamente
// Usar los structs Location, Department y Employee de models.go
// Inicializar todos los campos anidados con los valores de entrada
// TODO: Imprimir el perfil del empleado usando el formato:
// Employee: [Name] (ID: [ID])
// Department: [DepartmentName]
// Location: [Building], Floor [Floor]
// Acceder a los campos anidados usando la notación de puntos (por ejemplo, employee.Department.Location.Building)
}
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
1Fundamentos de POO en Go
Archivos externosEspacio de trabajo y módulos de GoPaquetes e importacionesNombres exportados vs. no exportadosIntroducción a la POO en GoStructs como clasesDefinición de métodos en structsReceptores de puntero vs. de valorInicialización de structsFunciones constructorasResumen - Calculadora simple4Interfaces
Introducción a las interfacesImplementación implícitaLa interfaz como contratoInterfaz vacía (any)Type AssertionType SwitchComposición de interfacesInterfaces Stringer y ErrorResumen: Calculadora de figuras7Encapsulamiento
Campos exportados vs. no exportadosEncapsulamiento a nivel de paqueteMétodos Getter y SetterOcultamiento de información en GoResumen - Registros de estudiantes10Genéricos (Go 1.18+)
Introducción a los GenéricosParámetros de tipoRestricciones de tipoStructs genéricosSolución alternativa para métodos genéricosResumen - Colección genérica13Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón Abstract FactoryPatrón ObserverPatrón Strategy2Inmersión profunda en Tipos y Structs
Tipos básicos y compuestosDefiniciones de tipos personalizadosEtiquetas de StructsStructs anónimosStructs anidadosValores cero y por defectoRepaso - Libreta de contactos5Composición sobre herencia
Por qué Go no tiene herenciaConceptos básicos de incrustación de structsPromoción de métodosIncrustación de múltiples structsIncrustación vs AgregaciónShadowing de métodos incrustadosResumen - Jerarquía de empleados8Manejo de Errores y OOP
La interfaz errorTipos de errores personalizadosEnvoltura de errores (fmt.Errorf)Errores centinelaerrors.Is() y errors.As()Panic, Defer y RecoverResumen - Analizador de archivos3Punteros y Memoria
Fundamentos de punteros en GoPunteros a StructsPaso por valor vs referenciaLa función new()Garbage Collection en GoResumen - Constructor de Linked List6Polimorfismo en Go
Polimorfismo mediante interfacesDuck Typing en GoReglas de satisfacción de interfacesColecciones polimórficasInyección de dependenciasResumen - Procesador de pagos9Concurrencia y POO
Fundamentos de GoroutinesChannels y comunicaciónChannels con buffer vs. sin bufferSentencia Selectsync.Mutex y sync.RWMutexsync.WaitGroupDiseño de estructuras Thread-SafeResumen - Worker Pool