Menu
Coddy logo textTech

Fundamentos de Incorporação de Structs

Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy — lição 35 de 107.

Incorporação de struct é o mecanismo do Go para incluir um tipo struct dentro de outro. Em vez de usar um nome de campo, você simplesmente especifica o tipo, e o Go promove os campos da struct incorporada para a struct externa.

Aqui está a sintaxe básica:

type Address struct {
    City    string
    Country string
}

type Person struct {
    Name string
    Address  // incorporado - sem nome de campo
}

Quando você incorpora Address em Person, você pode acessar os campos incorporados diretamente na struct externa:

func main() {
    p := Person{
        Name: "Alice",
        Address: Address{
            City:    "London",
            Country: "UK",
        },
    }
    
    fmt.Println(p.City)     // London - acesso direto
    fmt.Println(p.Country)  // UK - acesso direto
    fmt.Println(p.Address.City)  // também funciona
}

Observe como p.City funciona sem escrever explicitamente p.Address.City. O Go promove automaticamente os campos da struct incorporada, tornando-os acessíveis como se pertencessem à struct externa. Você ainda pode acessá-los através do nome do tipo incorporado quando necessário.

Isso difere de structs aninhadas regulares, onde você deve sempre usar o nome do campo para acessar os campos internos. A incorporação cria uma API mais plana e conveniente, mantendo o agrupamento lógico de dados relacionados.

challenge icon

Desafio

Fácil

Vamos construir um sistema de registro de veículos que utiliza incorporação de structs (struct embedding) para criar um modelo de dados limpo e organizado. Você separará as informações de contato dos detalhes do veículo, permitindo o acesso direto a todos os campos por meio da incorporação.

Você organizará seu código em dois arquivos:

  • vehicle.go: Crie duas structs que trabalham juntas por meio de incorporação:
    • Uma struct ContactInfo com os campos OwnerName e Phone (ambos strings)
    • Uma struct Vehicle que incorpora ContactInfo (sem um nome de campo) e adiciona seus próprios campos Make, Model e Year
    Crie também um método chamado Summary em Vehicle que retorna uma string formatada contendo todas as informações do veículo e de contato.
  • main.go: Leia os detalhes do veículo e do proprietário da entrada, crie uma instância de Vehicle com ContactInfo incorporado e demonstre o acesso aos campos incorporados tanto diretamente quanto através do nome do tipo incorporado. Imprima o resumo do veículo ao final.

As seguintes entradas serão fornecidas:

  • Linha 1: Nome do proprietário
  • Linha 2: Número de telefone
  • Linha 3: Marca do veículo
  • Linha 4: Modelo do veículo
  • Linha 5: Ano (inteiro)

Seu método Summary deve retornar uma string neste formato:

[Year] [Make] [Model] - Owner: [OwnerName], Phone: [Phone]

No seu arquivo principal, demonstre a promoção de campos (field promotion) imprimindo:

  1. O nome do proprietário acessado diretamente no Vehicle (ex: v.OwnerName)
  2. O telefone acessado através do tipo incorporado (ex: v.ContactInfo.Phone)
  3. O resumo completo do seu método Summary

Por exemplo, dados Alice Smith, 555-1234, Toyota, Camry e 2023, sua saída deve ser:

Alice Smith
555-1234
2023 Toyota Camry - Owner: Alice Smith, Phone: 555-1234

Observe como ambos os padrões de acesso funcionam — acesso direto por meio da promoção de campos e acesso explícito por meio do nome do tipo incorporado — oferecendo flexibilidade na forma como você trabalha com dados incorporados.

Folha de consulta

O encapsulamento de structs (struct embedding) permite incluir um tipo struct dentro de outro sem especificar um nome de campo. Os campos da struct incorporada são promovidos para a struct externa, tornando-os diretamente acessíveis.

Sintaxe Básica

type Address struct {
    City    string
    Country string
}

type Person struct {
    Name string
    Address  // embedded - no field name
}

Acessando Campos Incorporados

Você pode acessar campos incorporados de duas maneiras:

p := Person{
    Name: "Alice",
    Address: Address{
        City:    "London",
        Country: "UK",
    },
}

// Acesso direto (promoção de campo)
fmt.Println(p.City)     // London

// Através do nome do tipo incorporado
fmt.Println(p.Address.City)  // London

O Go promove automaticamente os campos da struct incorporada, permitindo o acesso direto como se eles pertencessem à struct externa. Você ainda pode acessá-los através do nome do tipo incorporado quando necessário.

Experimente você mesmo

package main

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

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

	// Lê o nome do proprietário
	ownerName, _ := reader.ReadString('\n')
	ownerName = strings.TrimSpace(ownerName)

	// Lê o número de telefone
	phone, _ := reader.ReadString('\n')
	phone = strings.TrimSpace(phone)

	// Lê a marca do veículo
	make, _ := reader.ReadString('\n')
	make = strings.TrimSpace(make)

	// Lê o modelo do veículo
	model, _ := reader.ReadString('\n')
	model = strings.TrimSpace(model)

	// Lê o ano
	yearStr, _ := reader.ReadString('\n')
	yearStr = strings.TrimSpace(yearStr)
	year, _ := strconv.Atoi(yearStr)

	// TODO: Criar uma instância de Vehicle com ContactInfo incorporado (embedded)
	// Use os valores lidos da entrada acima

	// TODO: Imprimir o nome do proprietário acessado diretamente no Vehicle (promoção de campo)
	// Exemplo: fmt.Println(v.OwnerName)

	// TODO: Imprimir o telefone acessado através do nome do tipo incorporado
	// Exemplo: fmt.Println(v.ContactInfo.Phone)

	// TODO: Imprimir o resumo completo usando o método Summary
	// Exemplo: fmt.Println(v.Summary())

	// Remova estas linhas assim que implementar a solução
	_ = ownerName
	_ = phone
	_ = make
	_ = model
	_ = year
}
quiz iconTeste seus conhecimentos

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