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 ফাংশনগুলো প্রায়ই যে স্ট্রাক্টগুলো ইনিশিয়ালাইজ করে, তাদের একই প্যাকেজে ডিক্লেয়ার করা হয়, তাই এরা স্ট্রাক্টের প্রাইভেট ফিল্ডও ইনিশিয়ালাইজ করতে পারেএই টাইপ সম্পর্কে আরও গভীরে যেতে আপনি এই রিসোর্সগুলো দেখতে পারেন: Go by Example: Structs, A Tour of Go: Structs অথবা Structures in Go (structs)
new বিল্ট-ইনএকটি স্ট্রাক্টের নতুন ইনস্ট্যান্স তৈরি করার আরেকটি উপায় হলো new বিল্ট-ইনটি ব্যবহার করা:
s := new(Shape) // s will be of type *Shape (pointer to shape)
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: size: 0
এই উদাহরণে new স্ট্রাক্ট Shape-এর একটি ইনস্ট্যান্স তৈরি করে, যার সব মান তাদের টাইপের জিরো ভ্যালুতে ইনিশিয়ালাইজ করা থাকে, এবং এটির একটি পয়েন্টার রিটার্ন করে।
বেশিরভাগ ক্ষেত্রেই আপনি new বিল্ট-ইন দিয়ে তৈরি স্ট্রাক্টের নতুন ইনস্ট্যান্স দেখতে পাবেন না।
সবসময় স্ট্রাক্ট লিটারাল, কাস্টম New ফাংশন, বা প্যাকেজের দেওয়া অন্য যে-কোনো ফাংশন ব্যবহার করাই ভালো, যা একটি স্ট্রাক্ট তৈরি করতে সাহায্য করতে পারে।
শেষ উপায় হিসেবে স্ট্রাক্টের নতুন ইনস্ট্যান্স তৈরি করতে new বিল্ট-ইন ব্যবহার করুন।