Structs Aninhadas
Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 16 de 107.
Uma struct aninhada é uma struct que contém outra struct nomeada como um de seus campos. Isso permite modelar dados complexos e hierárquicos compondo tipos menores e reutilizáveis juntos.
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // struct aninhada
}Para acessar campos em uma struct aninhada, você encadeia os nomes dos campos com pontos.
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // BostonO aninhamento promove a reutilização de código. O tipo Address pode ser usado em múltiplas structs como Person, Company ou Order sem duplicar campos. Essa abordagem reflete relacionamentos do mundo real onde entidades contêm outras entidades.
type Company struct {
Name string
Employees int
Address Address // mesmo tipo Address reutilizado
}Você pode aninhar structs em vários níveis de profundidade, embora manter as hierarquias rasas melhore a legibilidade. Structs aninhadas são fundamentais para construir modelos de dados orientados a objetos em Go.
Desafio
FácilVamos construir um sistema de gerenciamento de funcionários que demonstra como structs aninhadas ajudam a modelar hierarquias do mundo real. Você criará uma estrutura onde os funcionários pertencem a departamentos, e os departamentos possuem informações de localização.
Você organizará seu código em dois arquivos:
models.go: Defina três structs que trabalham juntas:Locationcom os camposBuilding(string) eFloor(int)Departmentcom o campoName(string) e um campoLocationaninhadoEmployeecom os camposID(int),Name(string) e um campoDepartmentaninhado
main.go: Leia as informações do funcionário a partir da entrada, crie um Employee com as structs devidamente aninhadas e exiba o perfil completo do funcionário acessando os campos através da estrutura aninhada.
As seguintes entradas serão fornecidas:
- Linha 1: ID do funcionário (inteiro)
- Linha 2: Nome do funcionário
- Linha 3: Nome do departamento
- Linha 4: Nome do edifício
- Linha 5: Número do andar (inteiro)
Formato de saída:
Employee: [Name] (ID: [ID])
Department: [DepartmentName]
Location: [Building], Floor [Floor]Por exemplo, dados 101, Alice Chen, Engineering, Tower A e 5, sua saída deve ser:
Employee: Alice Chen (ID: 101)
Department: Engineering
Location: Tower A, Floor 5Acesse os campos aninhados usando a notação de ponto para encadear a hierarquia da struct (ex: employee.Department.Location.Building).
Folha de consulta
Uma struct aninhada é uma struct que contém outra struct nomeada como um de seus campos, permitindo modelar dados hierárquicos compondo tipos menores e reutilizáveis.
Definindo Structs Aninhadas
type Address struct {
Street string
City string
ZIP string
}
type Person struct {
Name string
Age int
Address Address // struct aninhada
}Acessando Campos Aninhados
Use a notação de ponto para encadear através da hierarquia da struct:
p := Person{
Name: "Alice",
Age: 30,
Address: Address{
Street: "123 Main St",
City: "Boston",
ZIP: "02101",
},
}
fmt.Println(p.Address.City) // BostonReutilizando Structs Aninhadas
O mesmo tipo de struct aninhada pode ser reutilizado em várias structs pai:
type Company struct {
Name string
Employees int
Address Address // mesmo tipo Address reutilizado
}Structs aninhadas promovem a reutilização de código e espelham relacionamentos do mundo real onde entidades contêm outras entidades. Você pode aninhar structs em vários níveis de profundidade, embora manter as hierarquias rasas melhore a legibilidade.
Experimente você mesmo
package main
import "fmt"
func main() {
// Ler informações do funcionário
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: Criar um Employee com structs devidamente aninhadas
// Use as structs Location, Department e Employee de models.go
// Inicialize todos os campos aninhados com os valores de entrada
// TODO: Imprimir o perfil do funcionário usando o formato:
// Employee: [Name] (ID: [ID])
// Department: [DepartmentName]
// Location: [Building], Floor [Floor]
// Acesse campos aninhados usando a notação de ponto (ex: employee.Department.Location.Building)
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de OOP em Go
Arquivos ExternosGo Workspace e MódulosPacotes e ImportaçõesNomes Exportados vs Não ExportadosIntrodução a OOP em GoStructs como ClassesDefinindo Métodos em StructsRecebedores de Ponteiro vs ValorInicialização de StructsFunções ConstrutorasRecapitulação - Calculadora Simples4Interfaces
Introdução a InterfacesImplementação ImplícitaInterface como ContratoInterface Vazia (any)Type AssertionType SwitchComposição de InterfacesInterfaces Stringer & ErrorRecapitulação - Calculadora de Formas7Encapsulamento
Campos Exportados vs Não ExportadosEncapsulamento em Nível de PacoteMétodos Getter e SetterOcultação de Informação em GoRecapitulação - Registros de Estudantes10Generics (Go 1.18+)
Introdução a GenericsParâmetros de TipoRestrições de TipoStructs GenéricasSolução Alternativa para Métodos GenéricosRecapitulação - Coleção Genérica2Mergulho Profundo em Tipos e Structs
Tipos Básicos e CompostosDefinições de Tipos PersonalizadosStruct TagsStructs AnônimasStructs AninhadasZero Values e PadrõesRecapitulação - Agenda de Contatos5Composição em vez de Herança
Por que Go não possui HerançaFundamentos de Incorporação de StructsPromoção de MétodosIncorporando Múltiplas StructsIncorporação vs AgregaçãoShadowing de Métodos IncorporadosRecapitulação - Hierarquia de Funcionários8Tratamento de Erros e OOP
A Interface errorTipos de Erro PersonalizadosError Wrapping (fmt.Errorf)Erros Sentinelaerrors.Is() e errors.As()Panic, Defer e RecoverRecapitulação - File Parser3Ponteiros e Memória
Fundamentos de Ponteiros em GoPonteiros para StructsPassagem por Valor vs ReferênciaA Função new()Garbage Collection em GoRecapitulação - Construtor de Lista Encadeada6Polimorfismo em Go
Polimorfismo via InterfacesDuck Typing em GoRegras de Satisfação de InterfaceColeções PolimórficasInjeção de DependênciaRecapitulação - Processador de Pagamentos9Concorrência e OOP
Fundamentos de GoroutinesCanais e ComunicaçãoCanais com Buffer vs. Sem BufferInstrução Selectsync.Mutex e sync.RWMutexsync.WaitGroupDesign de Structs Thread-SafeRecapitulação - Worker Pool