خبر و ترفند روز

خبر و ترفند های روز را اینجا بخوانید!

مقدمه ای بر Concurrency in Go

بیاموزید که چگونه گوروتین ها و کانال ها همزمانی کارآمد را در برنامه های Go شما فعال می کنند.

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

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

همزمانی در Go

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

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

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

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

مطلب مرتبط:   NodeJS Google Authentication با استفاده از Passport و Express

نحوه استفاده از گوروتین برای اجرای همزمان کد

زمان اجرا Go گوروتین ها را مدیریت می کند. گوروتین ها پشته خود را دارند و به آنها اجازه می دهد ردپایی سبک وزن با اندازه اولیه پشته چند کیلوبایتی داشته باشند.

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

ایجاد گوروتین ها ساده است. شما از کلمه کلیدی go و به دنبال آن یک تابع فراخوانی برای اعلام گوروتین ها استفاده خواهید کرد.

func main() {
    go function1() // Create and execute goroutine for function1
    go function2() // Create and execute goroutine for function2

    // ...
}

func function1() {
    // Code for function1
}

func function2() {
    // Code for function2
}

هنگامی که برنامه با کلمه کلیدی go ()function1 و function2() را فراخوانی می کند، زمان اجرا Go توابع را همزمان به صورت گوروتین اجرا می کند.

در اینجا نمونه ای از استفاده از گوروتین است که متن را در کنسول چاپ می کند:

package main

import (
    "fmt"
    "time"
)

func printText() {
    for i := 1; i <= 5; i++ {
        fmt.Println("Printing text", i)
        time.Sleep(1 * time.Second)
    }
}

func main() {
    go printText() // Start a goroutine to execute the printText function concurrently

    // Perform other tasks in the main goroutine
    for i := 1; i <= 5; i++ {
        fmt.Println("Performing other tasks", i)
        time.Sleep(500 * time.Millisecond)
    }

    // Wait for the goroutine to finish
    time.Sleep(6 * time.Second)
}

تابع printText به طور مکرر متنی را با یک حلقه for در کنسول چاپ می کند که پنج بار پس از یک ثانیه تاخیر بین هر دستور با بسته زمانی اجرا می شود.

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

مطلب مرتبط:   ChatGPT در مقابل Google Bard: کدام ربات چت هوش مصنوعی در کدنویسی بهتر است؟

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

نتیجه چاپ متن با گوروتین است

استفاده از کانال ها برای ارتباط و همگام سازی

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

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

شما از اپراتور <- برای ارسال و دریافت داده ها از طریق کانال ها استفاده خواهید کرد.

در اینجا یک مثال برای نشان دادن استفاده اساسی از کانال ها برای ارتباط بین دو گوروتین آورده شده است:

func main() {
    // Create an unbuffered channel of type string
    ch := make(chan string)

    // Goroutine 1: Sends a message into the channel
    go func() {
        ch <- "Hello, Channel!"
    }()

    // Goroutine 2: Receives the message from the channel
    msg := <-ch
    fmt.Println(msg) // Output: Hello, Channel!
}

کانال در تابع main یک کانال بافر نشده به نام ch است که با تابع make() ایجاد شده است. اولین گوروتین پیام “سلام، کانال!” با استفاده از عملگر <- وارد کانال می شود و گوروتین دوم با استفاده از همان عملگر پیام را از کانال دریافت می کند. در نهایت تابع main پیام دریافتی را روی کنسول چاپ می کند.

نتیجه چاپ پیام ارسال شده از طریق کانال

می توانید کانال های تایپ شده را تعریف کنید. در هنگام ایجاد، نوع کانال را مشخص خواهید کرد. در اینجا مثالی وجود دارد که استفاده از انواع مختلف کانال را نشان می دهد:

func main() {
    // Unbuffered channel
    ch1 := make(chan int)

    // Buffered channel with a capacity of 3
    ch2 := make(chan string, 3)

    // Sending and receiving values from channels
    ch1 <- 42 // Send a value into ch1
    value1 := <-ch1 // Receive a value from ch1

    ch2 <- "Hello" // Send a value into ch2
    value2 := <-ch2 // Receive a value from ch2
}

تابع اصلی دو کانال ایجاد می کند: ch1 یک کانال عدد صحیح بدون بافر است، در حالی که ch2 یک کانال رشته ای بافر با ظرفیت 3 است. می توانید با استفاده از عملگر <- مقادیر را به و از این کانال ها ارسال و دریافت کنید (مقادیر باید برابر باشند. نوع مشخص شده).

مطلب مرتبط:   Thymeleaf چیست و چگونه می توانید از آن در برنامه های بوت بهار استفاده کنید؟

می‌توانید از کانال‌ها به‌عنوان مکانیزم‌های همگام‌سازی برای هماهنگی اجرای گوروتین با اعمال نفوذ در ماهیت مسدود کردن عملیات کانال استفاده کنید.

func main() {
    ch := make(chan bool)

    go func() {
        fmt.Println("Goroutine 1")
        ch <- true // Signal completion
    }()

    go func() {
        <-ch // Wait for the completion signal from Goroutine 1
        fmt.Println("Goroutine 2")
    }()

    <-ch // Wait for completion signal from Goroutine 2
    fmt.Println("Main goroutine")
}

کانال ch بولی است. دو گوروتین به طور همزمان در تابع اصلی اجرا می شوند. Goroutine 1 با ارسال یک مقدار واقعی به کانال ch سیگنال تکمیل آن را می دهد. Goroutine 2 با دریافت مقداری از کانال منتظر سیگنال تکمیل می شود. در نهایت، گروتین اصلی منتظر سیگنال تکمیل از گوروتین دو است.

شما می توانید برنامه های وب را در Go با جین بسازید

می‌توانید همزمان با استفاده از ویژگی‌های همزمانی Go، برنامه‌های وب با کارایی بالا را در Go با Gin بسازید.

می‌توانید از Gin برای مدیریت کارآمد مسیریابی HTTP و میان‌افزار استفاده کنید. با استفاده از گوروتین ها و کانال ها برای کارهایی مانند جستارهای پایگاه داده، تماس های API یا سایر عملیات مسدود کردن، از پشتیبانی همزمان داخلی Go بهره ببرید.