
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.
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.
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
}
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.
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.
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
}
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.
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.
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
}
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.
Let’s consider a more realistic scenario where we model a Vehicle system with multiple types of vehicles.
🔹Example:
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
}
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.
Go তে, embedding এবং composition একটি শক্তিশালী উপায় যা আপনাকে সহজ ধরনের মাধ্যমে জটিল ধরনের তৈরি করতে সাহায্য করে। Embedding আপনাকে একটি struct-কে অন্য একটি struct এর মধ্যে অন্তর্ভুক্ত করতে দেয়, এবং composition হল এমন একটি ডিজাইন প্যাটার্ন যেখানে একটি ধরনের ভিতরে অন্য ধরনের উপাদান থাকে।
Go তে, আপনি একটি struct-কে অন্য struct এর মধ্যে অন্তর্ভুক্ত করতে পারেন, যা বাইরের struct-কে অন্তর্ভুক্ত struct এর field এবং method গুলি ব্যবহার করতে দেয়। অন্তর্ভুক্ত struct টি বাইরের struct এর অংশ হয় এবং আপনি সেটি সরাসরি নাম না দিয়ে ব্যবহার করতে পারেন।
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 সরাসরি ব্যবহার করা
}
Name: Alice
City: New York
State: NY
👉 এখানে, Person struct-টি Address কে embed করেছে, তাই আমরা city এবং state সরাসরি Person অবজেক্টের উপর অ্যাক্সেস করতে পারি। এটিকে struct composition বলা হয় embedding এর মাধ্যমে।
যখন একটি struct আরেকটি struct এর মধ্যে embedded থাকে, তখন embedded struct এর methods গুলি বাইরের struct এ "promote" হয়ে যায়। এর ফলে বাইরের struct embedded struct এর methods গুলি সরাসরি কল করতে পারে, যেমন সেগুলি তার নিজের methods।
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 কল করা
}
Full Address: Los Angeles, CA
👉 Person struct-টি Address এর fullAddress method অ্যাক্সেস করতে পারে কারণ এটি Address struct কে embed করেছে।
Composition একটি ডিজাইন প্যাটার্ন যেখানে একটি struct অন্য ধরনের field ধারণ করে। এটি আপনাকে বিভিন্ন সহজ ধরনের মিশিয়ে একটি জটিল ধরনের তৈরি করতে দেয়। যদিও embedding composition এর একটি উপায়, composition এর ধারণা আরো বিস্তৃত।
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 চলানো
}
Car Model: BMW
Engine started with 670 horsepower.
Moving with 4 wheels.
👉 এখানে, Car struct-টি Engine এবং Wheels struct কে composition করেছে, এবং এটি উভয়ের field এবং method ব্যবহার করতে সক্ষম।
ধরা যাক, আমরা একটি Vehicle সিস্টেম ডিজাইন করছি যেখানে বিভিন্ন ধরনের গাড়ি রয়েছে।
🔹উদাহরণ:
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 চলানো
}
Car Model: BMW
Starting the V8 engine.
Moving with 4 wheels.
👉 এখানে, আমরা Car struct কে Engine এবং Wheels struct থেকে তৈরি করেছি, যা দুটি struct এর field এবং method ব্যবহার করে।