فهرست مطالب
اگر از زبانهایی مثل پایتون، جاوا یا سیشارپ وارد گو شدهاید، اولین چیزی که جلب توجه میکند نبود کلمه کلیدی class است. در گو خبری از وراثت سلسلهمراتبی یا وراثت چندگانه کلاسها نیست. وقتی میخواهید دادههای مرتبط با یک موجودیت، مثل نام، سن و ایمیل کاربر را یکجا جمع کنید، با ابزار اصلی زبان یعنی struct کار میکنید.
استراکت یک ساختار داده سفارشی شامل مجموعهای از فیلدهای نامگذاریشده با تایپ مشخص است. گو برای پیادهسازی مفاهیم شیءگرایی به جای کلاس، از ترکیب استراکت، متدها و اینترفیسها بهره میبرد.
ساختار struct در Go و نحوه تعریف آن
طبق مستندات رسمی Go، استراکت مجموعهای از فیلدها با تایپ مشخص است که برای گروهبندی دادهها و ساخت رکوردهای منطقی استفاده میشود. برای نمونه، تعریف یک کاربر یا فرد به شکل زیر انجام میشود:
gotype person struct {
name string
age int
}
برای نمونهسازی از این ساختار چند شیوه وجود دارد:
۱. مقداردهی بر اساس ترتیب فیلدها: person{"Bob", ۲۰}
۲. مقداردهی صریح با نام فیلد: person{name: "Alice", age: ۳۰}
۳. مقداردهی ناقص: اگر فیلدی مثل age نوشته نشود، گو مقدار پیشفرض آن فیلد (Zero value، مثلاً عدد صفر برای int) را در نظر میگیرد.
تفاوت اصلی struct با کلاس در شیءگرایی مرسوم
در زبانهای کلاسمحور سنتی، کلاس قالبی است که دادهها، توابع درونی (Constructor) و سلسلهمراتب ارثبری را همزمان تعریف میکند. تفاوتهای بنیادین استراکت در گو با کلاس عبارتند از:
- نبود کلمه کلیدی class: در گو موجودیتی به نام کلاس تعریف نشده است؛ دادهها درون struct تعریف میشوند و متدها بیرون از آن به ساختار متصل میگردند.
- نبود ارثبری (Inheritance): گو وراثت کلاسی با کلیدواژههایی چون
extendsندارد. به جای آن از ترکیب (Composition) و جایگذاری استراکت در استراکت دیگر (Embedding) استفاده میشود. - سازندههای اختصاصی (Constructor): گو متد سازنده پیشفرض شبیه
__init__یا نام همنام کلاس ندارد. به شکل متداول، یک تابع کمکی مثلnewPersonتعریف میشود که اشارهگری به شیء تازه میسازد.
کد کامل تعریف و کار با struct در Go
کد زیر نحوه ساخت نمونه، مقداردهی، ویرایش فیلدها، ایجاد استراکت بینام (Anonymous struct) و بازگرداندن اشارهگر از تابع را نشان میدهد:
gopackage main
import "fmt"
// تعریف ساختار داده person
type person struct {
name string
age int
}
// تابع سازنده که اشارهگر به ساختار جدید برمیگرداند
func newPerson(name string) *person {
p := person{name: name}
p.age = ۴۲
return &p
}
func main() {
// ساخت با مقادیر ترتیبی
fmt.Println(person{"Bob", ۲۰})
// ساخت با تعیین نام فیلدها
fmt.Println(person{name: "Alice", age: ۳۰})
// فیلدهای نوشتهنشده مقدار صفر منطقی میگیرند
fmt.Println(person{name: "Fred"})
// ساخت مستقیم اشارهگر
fmt.Println(&person{name: "Ann", age: ۴۰})
// فراخوانی تابع سازنده
fmt.Println(newPerson("Jon"))
// دسترسی و تغییر فیلد با عملگر دات
s := person{name: "Sean", age: ۵۰}
fmt.Println(s.name)
s.age = ۵۱
fmt.Println(s)
// اشارهگرها به صورت خودکار خوانده میشوند
sp := &s
sp.age = ۵۲
fmt.Println(sp.age)
// استراکت بینام برای کاربردهای موقت مانند آزمونها
dog := struct {
name string
isGood bool
}{"Rex", true}
fmt.Println(dog)
}
خروجی اجرای کد بالا:
text{Bob ۲۰}
{Alice ۳۰}
{Fred ۰}
&{Ann ۴۰}
&{Jon ۴۲}
Sean
{Sean ۵۱}
۵۲
{Rex true}
یک خطای رایج هنگام کار با استراکتها
یکی از خطاهای متداول در گو، اشتباه گرفتن مقدار کپیشده با اشارهگر است. استراکتها در گو Value Type هستند. وقتی یک متغیر استراکت را به تابعی پاس میدهید، کپی کاملی از فیلدهای آن ارسال میشود:
gofunc birthday(p person) {
p.age++ // تنها کپی محلی تغییر میکند
}
در این سناریو، سن در استراکت اصلی تغییر نمیکند. برای تغییر شیء اصلی، باید گیرنده یا پارامتر تابع را به شکل اشارهگر (*person) بنویسید. خوشبختانه نیازی به Dereference دستی با علامت ستاره نیست؛ گو خود عملگر . را روی اشارهگر باز میکند.
گام بعدی برای یادگیری عمیقتر
اکنون که با پایههای استراکت، فیلدها و تفاوت آن با کلاس آشنا شدید، گام بعدی یادگیری تعریف Receiver Function (متدهای متصل به استراکت) و استفاده از Composition به جای وراثت است. برای فراگیری اصولی این مفاهیم و توسعه پروژههای واقعی به زبان گو، میتوانید سرفصلهای دوره گو از صفر تا برنامهنویس را بررسی کنید.




نظرها
اولین نفری باشید که نظر میدهدسؤالتان را بپرسید یا تجربهتان را بنویسید تا نویسندهی مطلب پاسخ بدهد.