توابع در زبان گو؛ ساده ترین آموزش برای شروع کار با توابع Golang

توابع در زبان گو؛ ساده ترین آموزش برای شروع کار با توابع Golang

نوشته شده توسط: تیم فنی نیک آموز
تاریخ انتشار: ۳۰ شهریور ۱۴۰۳
آخرین بروزرسانی: ۲۴ آبان ۱۴۰۳
زمان مطالعه: 16 دقیقه
۵
(۱)

توابع در زبان گو از اهمیت بالایی برخوردار هستند و با استفاده از آن‌ها می‌توان مزایای بی شماری را در اختیار داشت. شاید آماده‌سازی و به کار بردن یک تابع در زبان گو زمان زیادی از شما نگیرد، اما با این روش صرفه‌جویی زمانی زیادی را در آینده به دست می‌آورید. در زمان توسعه یک برنامه در این زبان، روتین‌های بسیاری وجود دارند که به‌راحتی می‌توانید آن‌ها را در توابع گو پیاده‌ سازی کنید. استفاده از این توابع بسیار آسان است؛ پس اگر قبلاً با توابع زبان گو آشنا نبوده‌اید، اصلاً نگران نباشید. در این مقاله ساده‌ترین روش ورود به دنیای توابع در این زبان برنامه‌نویسی را در اختیار شما قرار خواهیم داد. 

تعریف و ساختار توابع در زبان گو

در کل، توابع را در تمامی زبان‌های برنامه‌نویسی مدرن در اختیار دارید. این توابع ورودی‌هایی دارند و براساس یک سری تعاریف، خروجی مورد نیاز را ارائه خواهند داد. البته، شاید ورودی برای یک تابع تعریف نشود و شاید هم شما تصمیم داشته باشید خروجی را دقیقا براساس ورودی‌های چندگانه دریافت کنید. 

این یکی از مزایای اساسی و جذاب توابع در زبان گو است که دست شما را برای شخصی سازی‌های هر چه بیشتر باز می‌گذارد. دقت در این امر حائز اهمیت است که زبان گو ساده‌ترین روش تعریف تابع را ارائه می‌دهد که در چند خط می‌توانید آن را تعریف کرده و در بخش‌های مختلف کد خود از آن استفاده کنید. قبل از شروع به کار با توابع بهتر است زبان گو و ابزارهای مورد نیاز را روی سیستم ویندوزی خود نصب کنیم تا در بخش‌های بعدی به صورت عملی کار با توابع را انجام دهیم. اگر ابزارهای مورد نیاز برای اجرای کدهای گو را روی سیستم خود دارید، می‌توانید از این بخش رد شوید. 

زبان برنامه نویسی go را با جدیدترین متد و آسان بیاموزید!

نصب ابزارهای مورد نیاز زبان گو

در کل، ۴ ابزار برای اجرای هر چه بهتر کدهای Go روی ویندوز نیاز است. در ۱۰ دقیقه می‌توانید این ابزارها را دریافت کرده و روی سیستم خود نصب کنید:

نصب زبان گو روی ویندوز

  • در مرحله اول بهتر است به سایت https://go.dev/dl مراجعه کرده و زبان Go را دانلود کنید. این بسته نرم افزاری در حدود ۶۰ مگابایت حجم دارد و پس از دانلود فایل زیر را در اختیار دارید:

نصب زبان Go

  • این فایل را اجرا کنید تا صفحه زیر را در اختیار داشته باشید؛ روی کلید Next کلیک کنید:

نصب زبان Go

  • در این مرحله تیک قوانین را فعال کرده و روی کلید Next کلیک کنید:

نصب زبان Go

  • بهتر است محل نصب گو روی ویندوز به حالت پیش‌فرض باقی بماند؛ در نهایت روی کلید Next کلیک کنید تا وارد مرحله بعدی شوید:

نصب زبان Go

  • با کلیک روی کلید Install مرحله نصب شروع خواهد شد:

شروع نصب زبان Go

  • مرحله نصب به صورت زیر است؛ نصب نرم‌افزار گو شاید ۲ یا ۳ دقیقه زمان طول بکشد:

مراحل نصب زبان Go

  • پس از نصب این زبان و پیکربندی ENV روی ویندوز، خروجی زیر را در اختیار دارید:

نصب زبان Go

نصب VSCode برای اجرای توابع در زبان گو

با نصب فایل‌های زبان گو، بهتر است یک ادیتور قدرتمند مانند VSCode نیز روی ویندوز نصب کنیم. با مراجعه به https://code.visualstudio.com می‌توانید این ابزار را دانلود کرده و نصب کنید. در نهایت، تصویر زیر را پس از نصب این ادیتور در اختیار دارید:

نصب VS Code

  • به بخش Extensions این ادیتور مراجعه کرده و پشتیبان گو را نیز نصب کنید:

نصب اکستنشن Go

  • برای رسیدن به تجربه کدنویسی بهتر، Snippetهای این زبان را هم نصب کنید:

نصب اکستنشن Golang

  • کار نصب برای اجرای توابع در زبان گو تمام است. یک فولدر بسازید و در فایل ۱.go کد زیر را کپی کنید:
package main
import "fmt"
func main() {
    fmt.Println("Hello, World!")
}
  • پس از کلیک روی گزینه Play در این ادیتور، خروجی را در ترمینال در اختیار دارید:

خروجی کد بالا

انواع توابع در زبان گو

در زبان برنامه‌نویسی Go توابع مختلفی وجود دارند که می‌توانید از آن‌ها استفاده کنید. تسلط روی هر یک از این توابع در زبان گو مزایای بسیاری را در اختیار شما قرار می‌دهد که در این بخش با آن‌ها آشنا خواهیم شد:

توابع ساده

توابع ساده یا همان Simple Functions توابعی هستند که می‌توان آن‌ها را به سرعت ایجاد کرد. این توابع می‌توانند ورودی داشته باشند و مقداری را باز گردانند؛ در مثال زیر، دو مقدار به تابع add برده می‌شوند تا خروجی حاصل از جمع آن‌ها را به دست آوریم:

package main
import "fmt"
// تعریف تابع ساده
func add(a int, b int) int {
    return a + b
}
func main() {
    // فراخوانی تابع ساده
    result := add(3, 4)
    fmt.Println("Simple Function Output:", result) // خروجی: ۷
}
  • با کلیک روی کلید Play می‌توان خروجی را به صورت زیر در اختیار داشت:

خروجی کد بالا

توابع گمنام Anonymous

شاید جذاب‌ترین انواع تابع در زبان گو توابع بدون نام باشند. این توابع را می‌توان داخل main یا هر تابع دیگری به صورت ترکیبی تعریف کرد. در تکه کد زیر تابع add به صورت گمنام تعریف شده است که می‌توان آن را به صورت مستقیم داخل main تعریف و فراخوانی کرد:

package main
import "fmt"
func main() {
    // تعریف و فراخوانی تابع ناشناس
    sum := func(a int, b int) int {
        return a + b
    }
    result := sum(5, 6)
    fmt.Println("Anonymous Function Output:", result) // خروجی: ۱۱
}
  • با اجرای این کد خروجی را به صورت زیر در اختیار خواهید داشت:

خروجی کد بالا

توابع بازگشتی 

توابع در زبان گو یک مدل خاص و جذاب دیگر نیز دارند. این مدل با عنوان توابع بازگشتی نامیده می‌شوند که قدرت فراخوانی خود را دارند. یکی از بهترین کاربردهای توابع بازگشتی در زبان گو محاسبه فاکتوریل اعداد است:

package main
import "fmt"
// تعریف تابع بازگشتی برای محاسبه فاکتوریل
func factorial(n int) int {
    if n == 0 {
        return 1
    }
    return n * factorial(n-1)
}
func main() {
    // فراخوانی تابع بازگشتی
    result := factorial(5)
    fmt.Println("Recursive Function Output:", result) // خروجی: ۱۲۰
}
  •  می‌توانید این کد را اجرا کنید تا به خروجی زیر برسید:

خروجی کد بالا

توابع با چند مقدار بازگشتی 

جالب است تا بدانید توابع در زبان گو قدرت باز گرداندن چند مقدار را نیز دارند. یک کاربرد جذاب این نوع توابع استفاده برای باز گرداندن خطاهای احتمالی ناشی از محاسبات است. 

کد زیر را تصور کنید که نیاز است ۲ عدد برای تقسیم شدن وارد یک تابع شوند. با این کار، می‌توان خطای احتمالی ناشی از تقسیم بر صفر را نیز در خروجی دریافت کرد:

package main
import (
    "fmt"
    "errors"
)
// تعریف تابع با چندین مقدار بازگشتی
func divide(a int, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}
func main() {
    // فراخوانی تابع و دریافت چندین مقدار بازگشتی
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Multiple Return Values Output:", result) // خروجی: ۵
    }
}
  • با اجرای این کد خروجی زیر را در اختیار دارید:

خروجی کد بالا

  • اگر به جای عدد ۲ ورودی ۰ را به تابع دهیم، خطای تقسیم بر صفر را دریافت خواهیم کرد:

خظای تقسیم بر صفر

توابع تغییر پذیر

توابعی که با نام Variadic Functions در این زبان شناخته می‌شوند، مزایای بسیاری را در اختیار شما قرار خواهند داد. این توابع در زبان گو قابلیت اعمال چندین ورودی به تابع را فراهم می‌کنند. در شرایطی که نمی‌دانید چه تعداد از ورودی‌ها به تابع وارد خواهند شد، استفاده از توابع تغییر پذیر پیشنهاد می‌شود؛ در مثال زیر چندین ورودی به تابع جمع وارد می‌شود تا در نهایت جمع حاصل از این ورودی‌ها را مشاهده کنیم:

package main
import "fmt"
// تعریف تابع تغییرپذیر
func sum(numbers ...int) int {
    total := 0
    for _, number := range numbers {
        total += number
    }
    return total
}
func main() {
    // فراخوانی تابع تغییرپذیر با تعداد مختلف آرگومان
    result := sum(1, 2, 3, 4, 5)
    fmt.Println("Variadic Function Output:", result) // خروجی: ۱۵
}
  • خروجی زیر را پس از اجرای کد دریافت می‌کنید:

خروجی کد بالا

توابع به عنوان مقادیر 

مفهوم Functions as Values را در سایر زبان‌های کدنویسی نیز در اختیار داریم. به این صورت توابع را می‌توان به متغیرها اختصاص داد و پس از فراخوانی آن، نتیجه را به خروجی برد؛ مثال زیر دو عدد را با استفاده از این روش جمع می‌کند:

package main
import "fmt"
func main() {
    // تعریف و اختصاص تابع به متغیر
    var add func(int, int) int
    add = func(a int, b int) int {
        return a + b
    }
    // فراخوانی تابع از طریق متغیر
    result := add(8, 7)
    fmt.Println("Function as Value Output:", result) // خروجی: ۱۵
}
  • می‌توانید این تکه کد را در زبان گو اجرا کنید تا خروجی مورد نظر را دریافت کنید:

خروجی کد بالا

توابع مرتبه بالاتر

زبان‌های مدرنی مانند Go قابلیت‌های ویژه‌ای در اختیار توسعه‌دهندگان و مهندسان نرم‌افزار قرار می‌دهند. یکی از این قابلیت‌ها امکان تعریف توابع مرتبه بالاتر است که در آن توابعی توابع دیگر را به عنوان ورودی خواهند گرفت؛ همچنین با این قابلیت، توابع در زبان گو می‌توانند توابع دیگر را برگردانند. مثال زیر کاربرد عملی این قابلیت در Golang است:

package main
import "fmt"
// تعریف تابع مرتبه بالاتر
func applyOperation(a int, b int, operation func(int, int) int) int {
    return operation(a, b)
}
func main() {
    // تعریف تابع برای ضرب
    multiply := func(x, y int) int {
        return x * y
    }
    // فراخوانی تابع مرتبه بالاتر
    result := applyOperation(5, 7, multiply)
    fmt.Println("Higher-order Function Output:", result) // خروجی: ۳۵
}
  • خروجی حاصل از ضرب دو عدد ورودی به صورت زیر است:

خروجی کد بالا

توابع کلوسور

در اصل، یک کلوسور (Closure) تابعی است که محیطی که در آن ایجاد شده را ضبط و به خاطر می‌سپارد؛ به عبارت دیگر، کلوسور قدرت بسته‌بندی متغیرها و نگه‌داری آن‌ها را دارد. این متغیرها حتی پس از این که تابع تعریف‌کننده آن به پایان رسید، قابل دسترس هستند. در مثال زیر، متغیر i را می‌توان با این توابع در زبان Go افزایش داد. در هر بار افزایش، برنامه حالت قبلی متغیر را به خاطر دارد:

package main
import "fmt"
// تعریف تابع کلوسور
func incrementer() func() int {
    i := 0
    return func() int {
        i++
        return i
    }
}
func main() {
    // فراخوانی کلوسور
    inc := incrementer()
    fmt.Println("Closure Output 1:", inc()) // خروجی: ۱
    fmt.Println("Closure Output 2:", inc()) // خروجی: ۲
    fmt.Println("Closure Output 3:", inc()) // خروجی: ۳
}
  • خروجی زیر را با اجرای این کد دریافت می‌کنید:

خروجی کد بالا

تفاوت توابع در زبان گو با سایر زبان‌ها

بعضی از ویژگی‌های ساختاری و طراحی در زبان گو وجود دارد که آن را از سایر زبان‌های برنامه‌نویسی متمایز خواهد کرد. این تفاوت‌ها در مورد بحث توابع نیز مشهود است که در ادامه با چند مورد از این تفاوت‌ها آشنا خواهیم شد.

  • انتقال تابع به یک تابع دیگر: در زبان گو توابع به عنوان First-Class تلقی می‌شوند و این به معنی آن است که می‌توانید آن‌ها را به عنوان آرگومان به سایر توابع منتقل کنید. 
  • نبود try catch: در زبان گو روش بدون استثنا No Exception و try catch وجود ندارد که در بسیاری از زبان‌های دیگر آن‌ها را مشاهده می‌کنید. در عوض، مکانیزم‌های جایگزین برای مدیریت خطاها در گولنگ وجود دارد. 
  • بازگشت چندگانه: با استفاده از توابع در زبان گو می‌توان برگشت چندگانه مقادیر را نیز انجام داد. به این صورت، شما می‌توانید در کنار مقادیر، ارورهای ناشی از اجرای توابع را نیز برگردانید. 
  • توابع ناشناس: در گو می‌توان توابع را به صورت ناشناس تعریف کرد. این توابع می‌توانند در همان محلی که تعریف می‌شوند، اجرا شوند (به عنوان “inline” function) یا به یک متغیر اختصاص داده شوند.

مدیریت خطا با استفاده از توابع

مدیریت خطا در زبان برنامه‌نویسی Go با استفاده از توابع بسیار رایج و مهم است. در Go، تابعی که خطا تولید می‌کند معمولاً مقدار error را به همراه نتیجه باز می‌گرداند؛ در ادامه دو مثال کاربردی از مدیریت خطا با استفاده از توابع ارائه می‌شود.

مثال یک: مدیریت خطا با شرط if else برای توابع در زبان گو

استفاده از شرط if else یک روش رایج برای مدیریت خطاها در این زبان است. در مثال زیر کاربرد این روش را مشاهده می‌کنید:

package main
import (
    "fmt"
    "errors"
)
// تابع برای تقسیم دو عدد
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("cannot divide by zero")
    }
    return a / b, nil
}
func main() {
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result:", result) // خروجی: ۵
    }
    result, err = divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err) // خروجی: cannot divide by zero
    } else {
        fmt.Println("Result:", result)
    }
}

با اجرای این کد خروجی اول را به صورت ۵ و خروجی حاصل از تقسیم ۱۰ بر صفر را به صورت پیام خطا در اختیار دارید:

خروجی کد بالا

مثال ۲: مدیریت خطا در زمان خواندن فایل 

در این مثال، تابعی برای خواندن محتوای یک فایل ایجاد می‌شود که خطای عدم وجود فایل را مدیریت می‌کند.

package main
import (
    "fmt"
    "io/ioutil"
    "os"
)
// تابع برای خواندن فایل
func readFile(filename string) (string, error) {
    content, err := ioutil.ReadFile(filename)
    if err != nil {
        if os.IsNotExist(err) {
            return "", fmt.Errorf("file %s does not exist", filename)
        }
        return "", err
    }
    return string(content), nil
}
func main() {
    content, err := readFile("error-handling-types/error-handling-2/existing_file.txt")
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("File Content:", content)
    }
    content, err = readFile("error-handling-types/error-handling-2/non_existing_file.txt")
    if err != nil {
        fmt.Println("Error:", err) // خروجی: file non_existing_file.txt does not exist
    } else {
        fmt.Println("File Content:", content)
    }
}

با اجرای این کد خروجی به صورت زیر در ترمینال چاپ خواهد شد:

خروجی کد بالا

مثال ۳ : استفاده از روش مشابه try catch برای مدیریت خطاهای توابع در زبان گو

در زبان برنامه‌نویسی Go، مکانیزم try-catch مشابه آنچه در زبان‌هایی مانند جاوا یا سی‌شارپ وجود دارد، پشتیبانی نمی‌شود؛ اما در عوض Go از مکانیزم‌های دیگری برای مدیریت خطا استفاده می‌کند که یکی از آن‌ها ترکیبی از panic و recover است. این روش به شما اجازه می‌دهد تا بتوانید در زمان وقوع یک خطای بحرانی برنامه را از وضعیت panic به حالت طبیعی بازگردانید.

در این مثال، تابعی برای محاسبه فاکتوریل تعریف می‌شود. اگر ورودی تابع عددی منفی باشد، از panic برای ایجاد یک وضعیت بحرانی استفاده می‌شود و سپس با استفاده از recover خطا مدیریت می‌شود.

package main
import "fmt"
// تابع برای محاسبه فاکتوریل
func factorial(n int) int {
    if n < 0 {
        panic("cannot calculate factorial of a negative number")
    }
    if n == 0 {
        return 1
    }
    return n * factorial(n-1)
}
// تابعی برای اجرای محاسبه فاکتوریل با مدیریت خطا
func safeFactorial(n int) (result int, err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("recovered from panic: %v", r)
        }
    }()
    result = factorial(n)
    return result, nil
}
func main() {
    // محاسبه فاکتوریل یک عدد مثبت
    result, err := safeFactorial(5)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Factorial Result:", result) // خروجی: ۱۲۰
    }
    // محاسبه فاکتوریل یک عدد منفی (باعث ایجاد panic)
    result, err = safeFactorial(-5)
    if err != nil {
        fmt.Println("Error:", err) // خروجی: recovered from panic: cannot calculate factorial of a negative number
    } else {
        fmt.Println("Factorial Result:", result)
    }
}

این کد را اجرا کنید تا به خروجی زیر در ترمینال برسید:

خروجی کد بالا

نکات و بهترین شیوه های نوشتن توابع در زبان گو

برای نوشتن توابع موثر و کارآمد در زبان Go، بهتر است به بعضی از نکات دقت داشته باشید. با استفاده از این روش‌ها می‌توان کدهایی بهینه با قابلیت نگهداری آسان توسعه داد. 

۱.نام مناسب برای توابع

برای رسیدن به بهترین بازدهی و ساده‌سازی توسعه کدها، بهتر است نام‌های مناسب و قابل درکی برای توابع انتخاب کنید. شاید در قدم‌های ابتدایی این کار اهمیت زیادی نداشته باشد. با این حال، پس از پیچیده شدن برنامه با استفاده از این نام‌ها می‌توان توابع را به راحتی شناسایی کرده و عملیات مورد نظر را انجام داد. 

۲.ساده و کوچک نگه داشتن توابع

بهتر است توابع در زبان گو را ساده و تا حد امکان کوچک نگه دارید؛ برای مثال، توابع را در چند خط خلاصه کنید تا در شرایط مختلف سرعت اجرای توابع بالا باشد. 

۳.مدیریت خطاها با روش های مطمئن

زبان گو نیز مانند سایر زبان‌ها روش‌هایی را برای مدیریت خطاها پیشنهاد می‌دهد؛ بنابراین، در بخش‌های مختلف کد و داخل توابع از این روش‌های مدیریت خطا استفاده کنید تا در آینده بهینه‌سازی برنامه‌تان را به حداکثر مقدار خود برسانید. 

سخن پایانی

توابع در زبان گو از جمله بهترین مزایای این زبان برنامه‌نویسی هستند که با استفاده از آن می‌توانید به سرعت عملیات روتین را انجام دهید. این توابع زبان گو به چند نوع تقسیم‌بندی می‌شوند و پس از تعریف می‌توان در بخش‌های مختلف برنامه از آن‌ها استفاده کرد. در صورتی که در برنامه یک سری عملیات روتین قرار است اتفاق بیفتد، بهترین کار مدیریت آن با توابع است. پس از تسلط به مفاهیم توابع در گو می‌‌توانید صرفه‌جویی بالایی در زمان و سایز برنامه به دست آورید. ما در بخش نظرات همین مقاله، نیک آموز میزبان دیدگاه و تجربه شما هستیم.

 

چه رتبه ای می‌دهید؟

میانگین ۵ / ۵. از مجموع ۱

اولین نفر باش

title sign
معرفی نویسنده
تیم فنی نیک آموز
مقالات
402 مقاله توسط این نویسنده
محصولات
0 دوره توسط این نویسنده
تیم فنی نیک آموز
title sign
دیدگاه کاربران