Embedding and Composition in Go

List Topics
February 17, 2025
No Comments
7 min read

In Go, embedding and composition are powerful ways to build complex types by combining simpler ones. Embedding allows one struct to include another struct, and composition refers to the design pattern where types are made up of other types.

1️⃣ Embedding

In Go, you can embed one struct within another, which allows the outer struct to access the fields and methods of the embedded struct. The embedded struct is "owned" by the outer struct but can be used directly without needing to refer to it by name.

🔹Example:

Go
package main

import "fmt"

// Define a struct
type Address struct {
    city  string
    state string
}

// Define another struct with Address embedded
type Person struct {
    name    string
    age     int
    Address // Embedded struct
}

func main() {
    p := Person{name: "Alice", age: 30, Address: Address{city: "New York", state: "NY"}}
    fmt.Println("Name:", p.name)
    fmt.Println("City:", p.city) // Accessing the field from the embedded struct directly
    fmt.Println("State:", p.state) // Accessing the field from the embedded struct directly
}

🔹Output:

Bash
Name: Alice
City: New York
State: NY

👉 In this example, Person embeds Address, so we can access city and state directly on a Person object. This is known as struct composition via embedding.

2️⃣ Methods on Embedded Types

When a struct is embedded inside another, methods of the embedded type are "promoted" to the outer type. This allows the outer struct to call methods of the embedded struct as if they are its own.

🔹Example:

Go
package main

import "fmt"

// Define the Address struct
type Address struct {
    city  string
    state string
}

// Method for Address struct
func (a Address) fullAddress() string {
    return a.city + ", " + a.state
}

// Define the Person struct with Address embedded
type Person struct {
    name    string
    age     int
    Address // Embedded struct
}

func main() {
    p := Person{name: "Bob", age: 25, Address: Address{city: "Los Angeles", state: "CA"}}
    fmt.Println("Full Address:", p.fullAddress()) // Calling method of embedded struct
}

🔹Output:

Bash
Full Address: Los Angeles, CA

👉 The Person struct has access to the fullAddress method of the embedded Address struct, and you can call it directly on the Person object.

3️⃣ Composition

Composition is a design pattern where one struct contains fields of other types. This allows you to compose a complex type by combining simpler types. While embedding provides a simpler way to achieve composition, the concept of composition extends beyond just struct embedding.

🔹Example:

Go
package main

import "fmt"

// Define a struct
type Engine struct {
    horsepower int
}

// Method for Engine
func (e Engine) start() {
    fmt.Println("Engine started with", e.horsepower, "horsepower.")
}

// Define another struct with Engine as a field
type Car struct {
    model  string
    Engine // Composition: Car has an Engine
}

func main() {
    c := Car{model: "Tesla Model S", Engine: Engine{horsepower: 670}}
    fmt.Println("Car Model:", c.model)
    c.start() // Calling the start method of Engine
}

🔹Output:

Bash
Car Model: Tesla Model S
Engine started with 670 horsepower.

👉 In this example, Car contains an Engine field, and the Car can use the methods of Engine through composition.

4️⃣ Differences Between Embedding and Composition

  • Embedding is a specific feature in Go where one struct is directly included in another. The embedded struct’s fields and methods are promoted to the outer struct.
  • Composition is a broader concept where one type (struct) contains other types as fields. In Go, embedding is one way to implement composition.

5️⃣ Practical Example of Composition:

Let’s consider a more realistic scenario where we model a Vehicle system with multiple types of vehicles.

🔹Example:

Go
package main

import "fmt"

// Define a struct for Engine
type Engine struct {
    typeOfEngine string
}

// Method for Engine
func (e Engine) start() {
    fmt.Println("Starting the", e.typeOfEngine, "engine.")
}

// Define a struct for Wheels
type Wheels struct {
    numberOfWheels int
}

// Method for Wheels
func (w Wheels) move() {
    fmt.Println("Moving with", w.numberOfWheels, "wheels.")
}

// Define a struct for Car with Composition
type Car struct {
    model  string
    Engine // Composition: Car has an Engine
    Wheels // Composition: Car has Wheels
}

func main() {
    c := Car{model: "BMW", Engine: Engine{typeOfEngine: "V8"}, Wheels: Wheels{numberOfWheels: 4}}
    fmt.Println("Car Model:", c.model)
    c.start()  // Start the engine
    c.move()   // Move the car
}

🔹Output:

Bash
Car Model: BMW
Starting the V8 engine.
Moving with 4 wheels.

👉 In this example, we composed the Car struct from the Engine and Wheels structs, allowing it to leverage both the properties and methods of each.

Summary:

  • Embedding allows a struct to include another struct directly, giving the outer struct access to the fields and methods of the embedded struct.
  • Composition is a design principle where complex types are made from simpler, smaller types. It can be achieved through embedding or by using fields directly.
  • Go supports both embedding and composition, and these features help in building flexible, reusable types and behaviors.

Go তে Embedding এবং Composition

Go তে, embedding এবং composition একটি শক্তিশালী উপায় যা আপনাকে সহজ ধরনের মাধ্যমে জটিল ধরনের তৈরি করতে সাহায্য করে। Embedding আপনাকে একটি struct-কে অন্য একটি struct এর মধ্যে অন্তর্ভুক্ত করতে দেয়, এবং composition হল এমন একটি ডিজাইন প্যাটার্ন যেখানে একটি ধরনের ভিতরে অন্য ধরনের উপাদান থাকে।

1️⃣ Embedding

Go তে, আপনি একটি struct-কে অন্য struct এর মধ্যে অন্তর্ভুক্ত করতে পারেন, যা বাইরের struct-কে অন্তর্ভুক্ত struct এর field এবং method গুলি ব্যবহার করতে দেয়। অন্তর্ভুক্ত struct টি বাইরের struct এর অংশ হয় এবং আপনি সেটি সরাসরি নাম না দিয়ে ব্যবহার করতে পারেন।

🔹উদাহরণ:

Go
package main

import "fmt"

// Address নামে একটি struct সংজ্ঞায়িত করুন
type Address struct {
    city  string
    state string
}

// Person নামে একটি struct যা Address কে embedding করবে
type Person struct {
    name    string
    age     int
    Address // Embedded struct
}

func main() {
    p := Person{name: "Alice", age: 30, Address: Address{city: "New York", state: "NY"}}
    fmt.Println("Name:", p.name)
    fmt.Println("City:", p.city) // Embedded struct থেকে city field সরাসরি ব্যবহার করা
    fmt.Println("State:", p.state) // Embedded struct থেকে state field সরাসরি ব্যবহার করা
}

🔹আউটপুট:

Bash
Name: Alice
City: New York
State: NY

👉 এখানে, Person struct-টি Address কে embed করেছে, তাই আমরা city এবং state সরাসরি Person অবজেক্টের উপর অ্যাক্সেস করতে পারি। এটিকে struct composition বলা হয় embedding এর মাধ্যমে।

2️⃣ Embedded Types এর উপর Methods

যখন একটি struct আরেকটি struct এর মধ্যে embedded থাকে, তখন embedded struct এর methods গুলি বাইরের struct এ "promote" হয়ে যায়। এর ফলে বাইরের struct embedded struct এর methods গুলি সরাসরি কল করতে পারে, যেমন সেগুলি তার নিজের methods।

🔹উদাহরণ:

Go
package main

import "fmt"

// Address নামে একটি struct সংজ্ঞায়িত করুন
type Address struct {
    city  string
    state string
}

// Address struct এর একটি method
func (a Address) fullAddress() string {
    return a.city + ", " + a.state
}

// Person নামে একটি struct যা Address কে embedding করবে
type Person struct {
    name    string
    age     int
    Address // Embedded struct
}

func main() {
    p := Person{name: "Bob", age: 25, Address: Address{city: "Los Angeles", state: "CA"}}
    fmt.Println("Full Address:", p.fullAddress()) // Embedded struct এর method কল করা
}

🔹আউটপুট:

Bash
Full Address: Los Angeles, CA

👉 Person struct-টি Address এর fullAddress method অ্যাক্সেস করতে পারে কারণ এটি Address struct কে embed করেছে।

3️⃣ Composition

Composition একটি ডিজাইন প্যাটার্ন যেখানে একটি struct অন্য ধরনের field ধারণ করে। এটি আপনাকে বিভিন্ন সহজ ধরনের মিশিয়ে একটি জটিল ধরনের তৈরি করতে দেয়। যদিও embedding composition এর একটি উপায়, composition এর ধারণা আরো বিস্তৃত।

🔹উদাহরণ:

Go
package main

import "fmt"

// Engine নামে একটি struct সংজ্ঞায়িত করুন
type Engine struct {
    horsepower int
}

// Engine struct এর একটি method
func (e Engine) start() {
    fmt.Println("Engine started with", e.horsepower, "horsepower.")
}

// Wheels নামে একটি struct সংজ্ঞায়িত করুন
type Wheels struct {
    numberOfWheels int
}

// Wheels struct এর একটি method
func (w Wheels) move() {
    fmt.Println("Moving with", w.numberOfWheels, "wheels.")
}

// Car নামে একটি struct যা Engine এবং Wheels কে composition করবে
type Car struct {
    model  string
    Engine // Composition: Car এর মধ্যে Engine রয়েছে
    Wheels // Composition: Car এর মধ্যে Wheels রয়েছে
}

func main() {
    c := Car{model: "BMW", Engine: Engine{horsepower: 670}, Wheels: Wheels{numberOfWheels: 4}}
    fmt.Println("Car Model:", c.model)
    c.start()  // Engine শুরু করা
    c.move()   // Car চলানো
}

🔹আউটপুট:

Bash
Car Model: BMW
Engine started with 670 horsepower.
Moving with 4 wheels.

👉 এখানে, Car struct-টি Engine এবং Wheels struct কে composition করেছে, এবং এটি উভয়ের field এবং method ব্যবহার করতে সক্ষম।

4️⃣ Embedding এবং Composition এর মধ্যে পার্থক্য

  • Embedding হল Go এর একটি বিশেষ বৈশিষ্ট্য যেখানে একটি struct অন্য একটি struct এর মধ্যে সরাসরি অন্তর্ভুক্ত থাকে। Embedded struct এর field এবং method গুলি বাইরের struct এ "promote" হয়ে যায়।
  • Composition হল একটি ডিজাইন প্যাটার্ন, যেখানে একটি complex type তৈরি করতে অন্য ধরনের field ব্যবহার করা হয়। Go তে, embedding হল composition এর একটি উপায়।

5️⃣ Composition এর একটি বাস্তব উদাহরণ:

ধরা যাক, আমরা একটি Vehicle সিস্টেম ডিজাইন করছি যেখানে বিভিন্ন ধরনের গাড়ি রয়েছে।

🔹উদাহরণ:

Go
package main

import "fmt"

// Engine নামে একটি struct সংজ্ঞায়িত করুন
type Engine struct {
    typeOfEngine string
}

// Engine struct এর একটি method
func (e Engine) start() {
    fmt.Println("Starting the", e.typeOfEngine, "engine.")
}

// Wheels নামে একটি struct সংজ্ঞায়িত করুন
type Wheels struct {
    numberOfWheels int
}

// Wheels struct এর একটি method
func (w Wheels) move() {
    fmt.Println("Moving with", w.numberOfWheels, "wheels.")
}

// Car নামে একটি struct যা Engine এবং Wheels কে composition করবে
type Car struct {
    model  string
    Engine // Composition: Car এর মধ্যে Engine রয়েছে
    Wheels // Composition: Car এর মধ্যে Wheels রয়েছে
}

func main() {
    c := Car{model: "BMW", Engine: Engine{typeOfEngine: "V8"}, Wheels: Wheels{numberOfWheels: 4}}
    fmt.Println("Car Model:", c.model)
    c.start()  // Engine শুরু করা
    c.move()   // Car চলানো
}

🔹আউটপুট:

Bash
Car Model: BMW
Starting the V8 engine.
Moving with 4 wheels.

👉 এখানে, আমরা Car struct কে Engine এবং Wheels struct থেকে তৈরি করেছি, যা দুটি struct এর field এবং method ব্যবহার করে।

সারাংশ:

  • Embedding Go তে একটি struct-কে অন্য struct এর মধ্যে অন্তর্ভুক্ত করতে সাহায্য করে, যার ফলে বাইরের struct ওই embedded struct এর field এবং method অ্যাক্সেস করতে পারে।
  • Composition হল একটি ডিজাইন প্যাটার্ন যেখানে complex type তৈরি করতে একাধিক type এর field ব্যবহার করা হয়। এটি embedding এর মাধ্যমে বা সরাসরি field ব্যবহার করে করা যেতে পারে।
  • Go তে embedding এবং composition উভয়ই ব্যবহার করে আপনি ফ্লেক্সিবল এবং পুনরায় ব্যবহারযোগ্য type এবং behavior তৈরি করতে পারেন।

©2025 Linux Bangla | Developed & Maintaind by Linux Bangla.