متدها در زبان GoLang

با سلامزبان گولنگ یک زبان OOP نیست و مفهومی با عنوان کلاس(class) که در این زبان ها هست رو نداره اما میتوانیم برای انواع داده (type) متد تعریف کنیم.متد در زبان گو شباهت زیادی به فانکشن دارد، در واقع یک متد یک فانکشن با آرگومان receiver خاص هست.خب بهتره جهت یادآوری و هم درک بهتر موضوع رجوعی به بحث فانکش ها داشته باشیم.func avg(x, y float64) float64 { return (x + y) / 2 }یک فانکشن میتواند هیچ یا چند آرگومان داشته باشد و توجه داشته باشید که بعد از تعریف آرگومان ها می توانیم نوع خروجی رو رو هم مشخص می کنیم(اختیاری است) نوع آرگومان بعد از اسم آنها می‌آید و اگر مانند مثال بالا نوع همه آرگومان ها یکسان باشد می توانیم نوع را فقط برای آخرین مورد تعریف کنیم.فانکش ها در زبان گولنگ خصوصیات دیگری مانند مقدار خروجی نام گذاری شده و چند خروجی را دارند که با توجه به موضوع اصلی مقاله نیاز به بررسی این موارد رو نمی بینم. خب برگردیم به سراغ متد هانوع receiver که در بالا اشاره کردیم بین کلمه func و نام تابع(MethodName) قرار میگیرد. ریسیور یک نام و نوع دارد:func (receiver Type) MethodName(parameterList) (returnTypes) { }در مثال زیر متد show یک receiver از نوعauthor با نام a میگیرد و کارش این است که اطلاعات یک نویسنده رو نمایش دهند. package main import &quotfmt&quot // Author structure type author struct { name string branch string particles int salary int } // Method with a receive of author type func (a author) show() { fmt.Println(&quotAuthor's Name: &quot, a.name) fmt.Println(&quotBranch Name: &quot, a.branch) fmt.Println(&quotPublished articles: &quot, a.particles) fmt.Println(&quotSalary: &quot, a.salary) } // Main function func main() { // Initializing the values of the author structure res := author{ name: &quotSona&quot, branch: &quotCSE&quot, particles: 203, salary: 34000, } // Calling the method res.show() }توجه کنید که author از نوع struct می باشد. ما می توانیم برای انواع Non-Struct هم متد تعریف کنیم، در مثال زیر ما برای نوع سفارشی MyString که ساخته ایم یک متد به نام reverse برای معکوس کردن رشته مقادیر آن اضافه کردیم که به راحتی می توانیم آن را صدا بزنیم.package main import ( &quotfmt&quot ) type MyString string func (myStr MyString) reverse() string { s := string(myStr) runes := []rune(s) for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { runes[i], runes[j] = runes[j], runes[i] } return string(runes) } func main() { myStr := MyString(&quotOLLEH&quot) fmt.Println(myStr.reverse()) }شما میتوانید متدهایی با ورودی پوینتر(Pointer) تعریف کنید:// Method with pointer receiver func (receiver *Type) MethodName(parameterList) (returnTypes) { // code }با استفاده از آرگومان از نوع اشاره گر می توانید مقادیر receiver را تغییر دهید. در حالی که در حالت قبلی(value receiver) این امکان پذیر نبود و صرفا یک کپی از receiver به متد پاس داده می شد.به طور مثال اگر بخواهیم برای نوع author مثال قبلی یک متد برای تغییر ویژگی branch آن اضافه کنیم، بدین صورت عمل می کنیم:// Method with a receiver of author type func (a *author) changeBranch(branch string) { (*a).branch = branch }بر خلاف فانکشن ها، متدها می توانند هم آرگومان اشاره گر(Pointer) و هم مقدار(Value)را بپذیرند:همانطور که می دانیم در Go هنگامی که یک تابع دارای آرگومان مقدار(value) است، فقط مقادیری که به صورت value هستند را به عنوان پارامتر را می پذیرد و اگر بخواهید یک Pointer را به یک تابع Value منتقل کنید( یا برعکس)، آن را نمی پذیرد. اما یک متد Go می تواند مقادیر(Value) و اشاره گر(Pointer) را بپذیرد. همانطور که در مثال زیر نشان داده شده است:package main import &quotfmt&quot // Author structure type author struct { name string branch string } // Method with a pointer receiver of author type func (a *author) show_1(abranch string) { (*a).branch = abranch } // Method with a value receiver of author type func (a author) show_2() { a.name = &quotGourav&quot fmt.Println(&quotAuthor's name(Before) : &quot, a.name) } // Main function func main() { // Initializing the values of the author structure res := author{ name: &quotSona&quot, branch: &quotCSE&quot, } fmt.Println(&quotBranch Name(Before): &quot, res.branch) // Calling the show_1 method (pointer method) with value res.show_1(&quotECE&quot) fmt.Println(&quotBranch Name(After): &quot, res.branch) // Calling the show_2 method (value method) with a pointer (&res).show_2() fmt.Println(&quotAuthor's name(After): &quot, res.name) }خروجی:Branch Name(Before): CSE Branch Name(After): ECE Author's name(Before) : Gourav Author's name(After): Sonaدر مثال فوق می بینید که چطور آرگومان های دلخواه (از نوع value یا pointer) به متدها پاس داده می شوند.چرا از متدها به جای فانکشن ها استفاده کنیم ؟۱- متد ها به شما اجازه می دهند تا با استایل OOP در گولنگ کد بزنید، گو یک زبان برنامه نویسی شی گرا نیست و از کلاس ها پشتیبانی نمی کند. از این رو تعریف متدها بر روی typeها راهی برای دستیابی به رفتاری مشابه کلاس ها هستند. متدها به یک گروه بندی منطقی از رفتار مربوط به type شبیه کلاس ها اجازه می دهند. ۲- متد کال ها در خوانایی و درک آسان کد بهتر هستند، متدهای مختلف با نام یکسان را می توان در انواع مختلف type تعریف کرد در حالی که توابع هم نام مجاز نیستند. یک مثال ساده فرض کنیم که ما یک ساختار(struct) مربع(Square) و دایره(Circle) داریم. می توان متدهای هم نام Area را در مربع و دایره تعریف کرد.۳- علاوه بر این متد ها باعث جلوگیری از کانفلیکت نام گذاری می شوند. چون متد به یک نوع(type) وابسته شده، شما می توانید از همان متد بر روی نوع های مختلف داشته باشید۴- متد میتونه مقدار ریسیور رو که پوینتر بهش اشاره میکنه تغییر بدهد، اینطوری از کپی کردن مقدار(value) در هر فراخوانی خودداری میشوذ. اگر receiver یک استراکت بزرگ باشد ، این می تواند کارآمدتر(efficient) باشد.خب در این مقاله با متد ها و نحوه نوشتن آنها در گپلنگ آشنا شدیم و همینطور یادگرفتیم که متدها چه فرق هایی با فانکشن ها دارند.سخن پایانی: لطفا نظرات و انتقادات سازنده خودتون رو دریغ نکنید من حتما استقبال میکنم.