Go-তে, একটি struct হলো নামযুক্ত এলিমেন্টের একটি ক্রম, যাদের ফিল্ড বলা হয়; প্রতিটি ফিল্ডের একটি নাম ও একটি টাইপ থাকে।
একটি স্ট্রাক্টের মধ্যে একটি ফিল্ডের নাম অনন্য হতে হবে।
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং প্যারাডাইমে স্ট্রাক্টকে ক্লাস-এর সাথে তুলনা করা যায়।
আপনি type ও struct কিওয়ার্ড ব্যবহার করে একটি নতুন স্ট্রাক্ট তৈরি করেন, এবং ফিল্ডগুলোর নাম ও টাইপ স্পষ্টভাবে ডিফাইন করেন।
যেমন, এখানে আমরা Shape স্ট্রাক্টটি ডিফাইন করি, যেখানে একটি আকৃতির নাম ও তার আকার রাখা হয়:
type Shape struct {
name string
size int
}
স্ট্রাক্টের ফিল্ডের নাম Go-র কনভেনশন অনুসরণ করে: যে ফিল্ডের নাম ছোট হাতের অক্ষর দিয়ে শুরু হয়, তা কেবল একই প্যাকেজের কোড থেকে দেখা যায়, আর যে ফিল্ডের নাম বড় হাতের অক্ষর দিয়ে শুরু হয়, তা অন্য প্যাকেজ থেকেও দেখা যায়।
একবার struct ডিফাইন করে ফেললে, আপনি ফিল্ডের নাম ব্যবহার করে যেকোনো ক্রমে ফিল্ডগুলো উল্লেখ করে একটি নতুন ইনস্ট্যান্স তৈরি করতে পারেন:
s := Shape {
name: "Square",
size: 25,
}
ইনস্ট্যান্সের ফিল্ড পড়তে বা পরিবর্তন করতে, . নোটেশন ব্যবহার করুন:
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
যে ফিল্ডগুলোর কোনো প্রাথমিক মান অ্যাসাইন করা হয় না, সেগুলো তাদের শূন্য মান পায়। যেমন:
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
আপনি ফিল্ডের নাম ব্যবহার না করেও একটি struct-এর ইনস্ট্যান্স তৈরি করতে পারেন, যদি আপনি ফিল্ডগুলো ক্রম অনুযায়ী উল্লেখ করেন:
s := Shape {
"Oval",
20,
}
তবে এই সিনট্যাক্সকে ভঙ্গুর কোড ধরা হয়, কারণ কোনো ফিল্ড যোগ করা হলে এটি ভেঙে পড়তে পারে, বিশেষ করে যখন নতুন ফিল্ডটি ভিন্ন টাইপের হয়।
পরের উদাহরণে আমরা Shape-এ একটি অতিরিক্ত ফিল্ড যোগ করি:
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
মাঝে মাঝে এমন ফাংশন থাকলে ভালো হয়, যেগুলো আমাদের স্ট্রাক্টের ইনস্ট্যান্স তৈরি করতে সাহায্য করে।
কনভেনশন অনুযায়ী, এই ফাংশনগুলোকে সাধারণত New বলা হয় বা তাদের নাম New দিয়ে শুরু হয়, কিন্তু যেহেতু এগুলো নিছক সাধারণ ফাংশন, আপনি চাইলে এদের যেকোনো নাম দিতে পারেন।
এগুলো আপনাকে অন্য ভাষার কনস্ট্রাক্টরদের কথা মনে করিয়ে দিতে পারে, কিন্তু Go-তে এগুলো কেবল সাধারণ ফাংশন।
পরের উদাহরণে, এই New ফাংশনগুলোর একটি ব্যবহার করে Shape-এর একটি নতুন ইনস্ট্যান্স তৈরি করা হয় এবং আকৃতির size-এর জন্য স্বয়ংক্রিয়ভাবে একটি ডিফল্ট মান সেট করা হয়:
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
New ফাংশন ব্যবহার করলে নিচের সুবিধাগুলো পাওয়া যায়:
New ফাংশনগুলো প্রায়ই যে স্ট্রাক্টগুলো ইনিশিয়ালাইজ করে, তাদের একই প্যাকেজে ডিক্লেয়ার করা হয়, তাই এগুলো স্ট্রাক্টের প্রাইভেট ফিল্ডও ইনিশিয়ালাইজ করতে পারেএই অনুশীলনীতে আপনি নানা ধরনের রিমোট কন্ট্রোলড গাড়ির মধ্যে রেস আয়োজন করবেন। প্রতিটি গাড়ির নিজস্ব স্পিড ও ব্যাটারি ড্রেনের বৈশিষ্ট্য থাকে।
গাড়িগুলো শুরু করে পুরো (১০০%) ব্যাটারি নিয়ে। রিমোট কন্ট্রোল দিয়ে যতবার আপনি গাড়িটি চালাবেন, ততবার এটি গাড়ির স্পিডের সমান মিটার এগিয়ে যায় এবং অবশিষ্ট ব্যাটারির শতাংশ তার ব্যাটারি ড্রেনের পরিমাণ কমিয়ে দেয়।
কোনো গাড়ির ব্যাটারি যদি তার ব্যাটারি ড্রেনের শতাংশের চেয়ে কম হয়, তাহলে আপনি আর সেই গাড়ি চালাতে পারবেন না।
প্রতিটি রেস ট্র্যাকের নিজস্ব দূরত্ব থাকে। ব্যাটারি শেষ না করে গাড়িটি ট্র্যাক শেষ করতে পারে কি না, তা যাচাই করে গাড়িগুলোকে পরীক্ষা করা হয়।
নিচের int টাইপের ফিল্ডগুলো নিয়ে একটি Car স্ট্রাক্ট ডিফাইন করুন:
NewCar নামের একটি ফাংশন ডিফাইন করে রিমোট কন্ট্রোলড গাড়ি তৈরি করা যাবে।
ফাংশনটি প্যারামিটার হিসেবে নেয় গাড়ির স্পিড (মিটারে) এবং ব্যাটারি ড্রেনের শতাংশ (দুটোই int টাইপের), আর রিটার্ন করে একটি Car ইনস্ট্যান্স:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
// => Car{speed: 5, batteryDrain: 2, battery:100, distance: 0}
integer টাইপের distance ফিল্ড নিয়ে Track নামে আরেকটি স্ট্রাক্ট টাইপ ডিফাইন করুন।
NewTrack নামের একটি ফাংশন ডিফাইন করে রেস ট্র্যাক তৈরি করা যাবে।
ফাংশনটি একমাত্র প্যারামিটার হিসেবে নেয় ট্র্যাকের দূরত্ব (মিটারে), যা int টাইপের:
distance := 800
track := NewTrack(distance)
// => Track{distance: 800}
Drive ফাংশনটি ইমপ্লিমেন্ট করুন, যা গাড়ির স্পিড অনুযায়ী অতিক্রান্ত মিটারের সংখ্যা হালনাগাদ করে এবং ব্যাটারি ড্রেন অনুযায়ী ব্যাটারি কমিয়ে দেয়।
আরেকবার চালানোর মতো যথেষ্ট ব্যাটারি না থাকলে গাড়িটি নড়বে না:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car = Drive(car)
// => Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}
রেস শেষ করতে হলে গাড়িটিকে রেসের দূরত্ব অতিক্রম করতে সক্ষম হতে হবে।
অর্থাৎ ফিনিশ লাইন পেরোনোর আগে তার ব্যাটারি শেষ হয়ে যাওয়া চলবে না।
CanFinish ফাংশনটি ইমপ্লিমেন্ট করুন, যা প্যারামিটার হিসেবে একটি Car ও একটি Track ইনস্ট্যান্স নেয় এবং গাড়িটি রেস শেষ করতে পারলে true রিটার্ন করে; নাহলে false রিটার্ন করে।
ধরে নিন, আপনি এখন রেসের শুরুর লাইনে আছেন এবং রেসের জন্য গাড়ির ইঞ্জিন চালু করছেন। খেয়াল রাখুন, রেস শুরু করার সময় গাড়ির ব্যাটারি পুরোপুরি চার্জ করা নাও থাকতে পারে:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
distance := 100
track := NewTrack(distance)
CanFinish(car, track)
// => true
Exercism-এ সাইন আপ করুন, Go ট্র্যাকের 34টি কনসেপ্ট165টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।