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).
Hoja de referencia
Una struct anidada es una struct que contiene otra struct con nombre como uno de sus campos, lo que permite modelar datos jerárquicos mediante la composición de tipos más pequeños y reutilizables.
Definición de Structs Anidadas
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // struct anidada
}Acceso a Campos Anidados
Utiliza la notación de puntos para encadenar a través de la jerarquía de la struct:
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // BostonReutilización de Structs Anidadas
El mismo tipo de struct anidada se puede reutilizar en múltiples structs principales:
type Company struct {
Name string
Employees int
Address Address // el mismo tipo Address reutilizado
}Las structs anidadas promueven la reutilización de código y reflejan relaciones del mundo real donde las entidades contienen otras entidades. Puedes anidar structs en varios niveles de profundidad, aunque mantener las jerarquías poco profundas mejora la legibilidad.
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