<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های رامتین قبادی</title>
        <link>https://virgool.io/feed/@ramtin_ghobadi</link>
        <description>رامتین قبادی هستم. در حدود ۱۷ سال هست در حوزه نرم افزار کار میکنم . دوست دارم در محیط ویرگول یکسری مطالب آموزشی منتشر کنم.</description>
        <language>fa</language>
        <pubDate>2026-06-16 22:06:21</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/2811723/avatar/ceZkZE.jpg?height=120&amp;width=120</url>
            <title>رامتین قبادی</title>
            <link>https://virgool.io/@ramtin_ghobadi</link>
        </image>

                    <item>
                <title>ساخت یک مرورگر Headless بخش اول</title>
                <link>https://virgool.io/@ramtin_ghobadi/%D8%B3%D8%A7%D8%AE%D8%AA-%DB%8C%DA%A9-%D9%85%D8%B1%D9%88%D8%B1%DA%AF%D8%B1-headless-%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-d8wmlmceznxs</link>
                <description>مرورگرهای Headless در سال‌های اخیر به یکی از ابزارهای اصلی توسعه‌دهندگان تبدیل شده‌اند. این نوع مرورگرها بدون رابط گرافیکی اجرا می‌شوند و امکاناتی مانند رندر صفحات وب، اجرای جاوااسکریپت، پیمایش، اسکرین‌شات و تعامل با DOM را در اختیار برنامه‌های سمت سرور قرار می‌دهند. در این مقاله، نحوه ساخت یک مرورگر Headless ساده با استفاده از زبان Go و کتابخانه Chromedp بررسی می‌شود و در نهایت یک API کاربردی برای گرفتن اسکرین‌شات ارائه خواهد شد.در اصل پیش زمینه ای برای ساختن مرورگرهای ابری روی سرور فراهم میآورند و بدون داشتن صفحه مرورگر اطلاعات وب سایت و ... را پردازش میکنند.۱. معرفی Chromedpکتابخانهٔ Chromedp یک ابزار قدرتمند برای تعامل برنامه‌نویسی با مرورگر Google Chrome از طریق Chrome DevTools Protocol است. این کتابخانه امکان انجام عملیات‌هایی مانند موارد زیر را فراهم می‌کند:باز کردن صفحات وباجرای اسکریپت‌های جاوااسکریپتاستخراج داده از DOMاسکرول، کلیک و شبیه‌سازی رفتار کاربرگرفتن اسکرین‌شات در اندازه کامل یا بخش خاصی از صفحهتبدیل صفحه به PDFChromedp کاملاً در Go نوشته شده و نیاز به نصب selenium یا webdriver ندارد.۲. ساخت ساختار اصلی مرورگربرای مدیریت یک مرورگر Headless ابتدا یک ساختار معرفی می‌شود که context و تابع لغو (cancel) را نگه‌داری می‌کند:type BrowserInstance struct {
    ctx    context.Context
    cancel context.CancelFunc
}
وظیفه‌ی این ساختارctx مسئول نگه‌داری اطلاعات Session مرورگر و کانال ارتباطی با DevTools است.cancel امکان متوقف‌سازی و آزادسازی منابع مرورگر را فراهم می‌کند.۳. ایجاد یک نمونه از مرورگربا استفاده از تابع chromedp.NewContext یک مرورگر Headless ساخته می‌شود:func NewBrowserInstance() (*BrowserInstance, error) {
    ctx, cancel := chromedp.NewContext(context.Background())

    return &amp;BrowserInstance{
        ctx:    ctx,
        cancel: cancel,
    }, nil
}
مراحل انجام‌شده در این تابعساخت context پایه (context.Background)ساخت context اختصاصی مرورگر و آغاز به‌کار Chrome Headlessبازگرداندن ساختار مدیریت‌کننده مرورگر۴. بارگذاری یک URL در مرورگربرای باز کردن یک آدرس اینترنتی از تابع زیر استفاده می‌شود:func (b *BrowserInstance) LoadURL(url string) error {
    err := chromedp.Run(b.ctx,
        chromedp.Navigate(url),
        chromedp.WaitReady(&quot;body&quot;, chromedp.ByQuery),
    )
    return err
}
توضیح مراحلNavigate آدرس موردنظر را در مرورگر باز می‌کند.WaitReady تا زمانی که تگ &lt;body&gt; آماده باشد صبر می‌کند و از رندر کامل محتوای صفحه مطمئن می‌شود.۵. گرفتن اسکرین‌شات از صفحهتابع زیر محتوای صفحه را به‌صورت PNG باز می‌گرداند:func (b *BrowserInstance) Screenshot() ([]byte, error) {
    var buf []byte
    err := chromedp.Run(b.ctx,
        chromedp.CaptureScreenshot(&amp;buf),
        chromedp.Sleep(500*time.Millisecond),
    )
    return buf, err
}
نکاتCaptureScreenshot تصویر کامل صفحه را گرفته و در متغیر buf ذخیره می‌کند.Sleep برای اطمینان از رندر کامل عناصر پویا استفاده می‌شود.۶. ساخت یک API برای دریافت اسکرین‌شاتدر این مرحله یک هندلر HTTP معرفی می‌شود که با گرفتن یک URL از کاربر، تصویر صفحه را بازگردانی می‌کند.کد Handler:func screenshotHandler(w http.ResponseWriter, r *http.Request) {
    url := r.URL.Query().Get(&quot;url&quot;)
    if url == &quot;&quot; {
        http.Error(w, &quot;url is required&quot;, http.StatusBadRequest)
        return
    }

    browser, err := NewBrowserInstance()
    if err != nil {
        http.Error(w, &quot;failed to create browser&quot;, http.StatusInternalServerError)
        return
    }
    defer browser.Close()

    if err := browser.LoadURL(url); err != nil {
        http.Error(w, &quot;failed to load url&quot;, http.StatusInternalServerError)
        return
    }

    img, err := browser.Screenshot()
    if err != nil {
        http.Error(w, &quot;failed to capture screenshot&quot;, http.StatusInternalServerError)
        return
    }

    w.Header().Set(&quot;Content-Type&quot;, &quot;image/png&quot;)
    w.Write(img)
}
۷. اجرای سرورfunc main() {
    http.HandleFunc(&quot;/screenshot&quot;, screenshotHandler)
    fmt.Println(&quot;Server running at :8081&quot;)
    http.ListenAndServe(&quot;:8081&quot;, nil)
}
۸. نحوهٔ استفادهپس از اجرای برنامه:http://localhost:8081/screenshot?url=https://example.com
مرورگر Headless:صفحهٔ example.com را باز می‌کندآن را کامل رندر می‌کند.یک تصویر PNG بازمی‌گردانددر بخش بعدی به توسعه کامل تر میپردازیم و کدهای نوشته شده در یک مخزن گیت نگهداری میکنیم.</description>
                <category>رامتین قبادی</category>
                <author>رامتین قبادی</author>
                <pubDate>Mon, 08 Dec 2025 16:17:50 +0330</pubDate>
            </item>
                    <item>
                <title>الگوریتم سه‌رنگ (Tricolor) در Garbage Collector زبان Go — یک راهنمای کامل و ساده</title>
                <link>https://virgool.io/@ramtin_ghobadi/%D8%A7%D9%84%DA%AF%D9%88%D8%B1%DB%8C%D8%AA%D9%85-%D8%B3%D9%87-%D8%B1%D9%86%DA%AF-tricolor-%D8%AF%D8%B1-garbage-collector-%D8%B2%D8%A8%D8%A7%D9%86-go-%E2%80%94-%DB%8C%DA%A9-%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7%DB%8C-%DA%A9%D8%A7%D9%85%D9%84-%D9%88-%D8%B3%D8%A7%D8%AF%D9%87-tvgps9q4m9b3</link>
                <description>Garbage Collector یا همان بازیافت‌کنندهٔ حافظه یکی از مهم‌ترین بخش‌های زبان Go است؛ بخشی که به‌طور خودکار حافظهٔ بلااستفاده را آزاد می‌کند تا برنامه‌ها سریع، مطمئن و بدون نشت حافظه اجرا شوند. با اینکه Go یک زبان مدرن و سطح بالا است، اما در پشت صحنه از یکی از پیچیده‌ترین و کارآمدترین تکنیک‌های جمع‌آوری زباله یعنی الگوریتم سه‌رنگ (Tricolor Mark-and-Sweep) استفاده می‌کند.در این مطلب، این الگوریتم را به زبانی ساده، کاربردی و مناسب برنامه‌نویسان Go بررسی می‌کنیم؛ الگوریتمی که بدون دانستن آن هم می‌توانید کدنویسی کنید، اما با دانستن آن کدهای بهینه‌تر، پایدارتر و سریع‌تری خواهید نوشت. الگوریتم سه‌رنگ چیست؟این الگوریتم برای تشخیص اشیائی که دیگر مورد استفادهٔ برنامه نیستند و می‌توان آن‌ها را از حافظه حذف کرد به‌کار می‌رود. چرا اسم آن سه‌رنگ است؟چون هر شیء در Heap در یکی از سه وضعیت قرار می‌گیرد: 1. اشیاء سفید (White)هنوز بررسی نشده‌اندممکن است زباله باشنداگر تا پایان چرخه بررسی نشوند → حذف می‌شوند 2. اشیاء سیاه (Black)به‌طور کامل بررسی شده‌اندتمام اشاره‌گرهایشان اسکن شدهقطعاً زنده و مورد استفاده هستندحذف نمی‌شوند 3. اشیاء خاکستری (Grey)زنده هستندولی هنوز بررسی نشده‌اند که به چه اشیائی اشاره می‌کنندباید توسط GC اسکن شوندتنها اشیائی که واقعاً «قابل دسترس» نیستند، در نهایت در مجموعه سفید باقی می‌مانند و حذف می‌شوند. چرخهٔ کار چگونه است؟ (Mark Phase)برای شروع، Go GC همه اشیا را سفید در نظر می‌گیرد.سپس الگوریتم مراحل زیر را طی می‌کند:1. یافتن ریشه‌ها (Roots)ریشه‌ها شامل:متغیرهای globalمتغیرهای موجود روی stackgoroutine‌هااشاره‌گرهای staticاین‌ها همیشه قابل دسترس‌اند، بنابراین خاکستری می‌شوند.2. پردازش اشیاء خاکستریالگوریتم یک شیء خاکستری برمی‌دارد:آن را سیاه می‌کندتمام اشاره‌گرهای آن را بررسی می‌کنداگر اشاره‌ای به اشیاء سفید وجود داشت → آن‌ها را خاکستری می‌کنداین چرخه آن‌قدر تکرار می‌شود تا هیچ شیء خاکستری باقی نماند. مرحله پاکسازی (Sweep Phase)هنگامی که دیگر هیچ شیء خاکستری وجود نداشته باشد:تمام اشیاء زنده → سیاهتمام اشیاء غیرقابل دسترس → سفیددر این لحظه، مجموعه سفید حذف می‌شود و حافظهٔ آن آزاد می‌گردد. نقش Write Barrier چیست؟از آنجا که Garbage Collection در Go همزمان با اجرای برنامه (Concurrent GC) انجام می‌شود، ممکن است برنامه در حین اجرای GC، اشاره‌گرهای جدیدی ایجاد یا تغییر دهد.برای جلوگیری از بهم خوردن فرآیند، یک «سد نوشتن» (Write Barrier) فعال است که:هر time یک اشاره‌گر در heap تغییر کندهدف جدید را خاکستری می‌کندو باعث می‌شود برنامه هیچ‌وقت سیاه → سفید را نقض نکنداین نکته بسیار حیاتی است زیرا: «هیچ شیء سیاه نباید به شیء سفید اشاره کند.»اگر این اصل نقض شود، GC ممکن است شیء زنده را اشتباهی پاک کند. چرا الگوریتم سه‌رنگ مهم است؟این الگوریتم مزایای بزرگی برای Go دارد:✔ اجرای همزمان با برنامه (Concurrent)برنامه متوقف نمی‌شود یا توقف‌های بسیار کوتاهی دارد.✔ سرعت بالاGo برای برنامه‌های پرکاربرد و شبکه‌ای طراحی شده و این الگوریتم باعث عملکرد روان سیستم می‌شود.✔ نوع‌محور و دقیق (Precise GC)GC دقیقاً می‌داند کدام داده‌ها اشاره‌گر هستند.✔ بدون نیاز به مدیریت دستی حافظهبرخلاف C++ یا Rust، برنامه‌نویس نیازی به مدیریت حافظه ندارد. مثال ساده: چرا یک شیء حذف می‌شود؟فرض کنید ساختار زیر وجود دارد:A → B → C
D → E → F
اگر A، B و C از ریشه‌ها قابل دسترس باشند اما هیچ ریشه‌ای به D اشاره نکند:مجموعه دوم (D و E و F) سفید باقی می‌ماندبنابراین قابل جمع‌آوری استحتی اگر خود E به F اشاره کند، اهمیتی نداردچون E خودش قابل دسترس نیستمثال دیگه:چرا شیء E قابل جمع‌آوری است؟object E سفید است.object E می‌تواند F را ببیند، اما هیچ شیء دیگری E را نمی‌بیند.یعنی:هیچ اشاره‌گری از ریشه‌ها (A، B، C) به سمت E نمی‌رودحتی اگر خود E به F اشاره کند، مهم نیستچون E خودش قابل دسترسی نیست→ پس E و F (اگر از جای دیگری reachable نباشند) garbage هستند.این نکته مهم است: برای زنده بودن یک شیء، باید از یک ریشه قابل دسترسی باشدنه اینکه خودش به بقیه دسترسی داشته باشد!در مثال شما:A → (اشاره دارد) به چیزهاییB → ...C → ...اما هیچ کدام به E اشاره نمی‌کنند.چرا Root Objects همیشه سیاه‌اند؟چون:از دید برنامه همیشه قابل دسترسی‌انداگر آن‌ها سفید باشند، کل برنامه از بین می‌رودو نقطه شروع همهٔ reachable objectها هستندRootها نقطهٔ ثابت آغاز الگوریتم هستند. جمع‌بندیالگوریتم سه‌رنگ یک بخش کلیدی از سیستم Garbage Collection زبان Go است.این الگوریتم با دسته‌بندی اشیاء به سفید، خاکستری و سیاه و بررسی سیستماتیک آن‌ها، تعیین می‌کند چه اشیایی واقعاً در برنامه قابل دسترس هستند و چه اشیایی باید حذف شوند.نتیجهٔ استفاده از این الگوریتم:سرعت بالاحداقل توقف برنامهعدم نشت حافظهپایداری در برنامه‌های مقیاس‌پذیردرک نحوهٔ کار این الگوریتم به شما کمک می‌کند برنامه‌های Go بهینه‌تر، سریع‌تر و بدون باگ حافظه‌ای بنویسید.</description>
                <category>رامتین قبادی</category>
                <author>رامتین قبادی</author>
                <pubDate>Tue, 18 Nov 2025 09:52:33 +0330</pubDate>
            </item>
            </channel>
</rss>