<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Sajjad Manafi</title>
        <link>https://virgool.io/feed/@SajjadManafi</link>
        <description>یه برنامه نویس بک اند | gopher</description>
        <language>fa</language>
        <pubDate>2026-06-10 20:10:52</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1588253/avatar/n4zCGm.jpeg?height=120&amp;width=120</url>
            <title>Sajjad Manafi</title>
            <link>https://virgool.io/@SajjadManafi</link>
        </image>

                    <item>
                <title>Concurrency is not parallelism! #3</title>
                <link>https://virgool.io/@SajjadManafi/concurrency-is-not-parallelism-3-tlpige5g8ewo</link>
                <description>سلام؛ سعی کردم توی این نوشته، بخش های مهم ارائه Concurrency is not parallelism که توسط Rob Pike رو یه جورایی ترجمه کنم. و خوشحال میشم اگر مشکلی توی متن یا ترجمه بود کامنت بزارید تا تصحیح اش کنم.این ارائه نسبتا طولانیه پس قراره چند تا پارت داشته باشیم و میتونید لینک پارت های قبلی و بعدی رو در انتهای نوشته پیدا کنید.و اسلاید های ارائه رو هم میتونید از اینجا ببینید.Goroutineچیزی که احتمالا شبیه threads ها در نظرش میگیرید. ولی در واقع متفاوت اند. که من زیاد به جزئیات تفاوت اونها نمی پردازم. فقط میخوام بگم چی هستن.f(&amp;quothello&amp;quot, &amp;quotworld&amp;quot) // f runs; we waitخب ما اینجا یه function داخل برناممون داریم. در حالت عادی که هممون باهاش آشنا هستیم. ما صبر میکنیم که اجرای این function تموم بشه و بعد میریم خط بعدی.go f(&amp;quothello&amp;quot, &amp;quotworld&amp;quot) // f starts running
g() // does not wait for f to returnولی اگر عبارت go رو قبل از اجرای function امون بزاریم چی؟ اتفاقی که میافته اینه که این تابع f شروع میکنه به اجرا شدن، ولی دیگه شما منتظر تموم شدن اجرای اون نمیموند و خط بعدی اجرا میشه. حداقل از نظر مفهومی نه لزوما. (concurrency vs parallel)یعنی از لحاظ مفهومی برنامه ما به اجرا شدنش ادامه میده همزمان با اینکه تابع f داره کارای خودشو انجام میده.اگر کمی گیج کننده هست، به این فکر کنید که بسیار شبیه ampersand (&amp;) داخل shell هست. که کامند میره و توی بکگراند برای خودش اجرا میشهA single ampersand terminates an asynchronous command. An ampersand does the same thing as a semicolon or newline in that it indicates the end of a command, but it causes Bash to execute the command asynchronously. That means Bash will run it in the background and run the next command immediately after, without waiting for the former to end.Goroutines are not threadsخب goroutine ها خیلی شبیه thread ها هستن. ولی خب اونا خیلی ارزون ترن!  یعنی ساختشون خیلی آسون و کم هزینه تره. و در صورت لزوم به صورت dynamic روی thread های سیستم عامل multiplex میشن. پس نیازی نیست نگران scheduling و blocking و... باشیم چون سیستم خودش حواسش به اینا هست و مراقبه :)و هروقت که یک goroutine نیاز به block شدن داره، مثل یه خوندن یه چیزی یا... ، هیچ goroutine دیگه ای نیاز به منتظر موندن نداره، چون همشون به صورت dynamic برنامه ریزی میشن. بنابرین شاید شبیه thread ها به نظر برسن، ولی goroutine ها خیلی خیلی سبک تر و کم هزینه تر از اونا هستن.خب گفتیم که باید بین این ها ارتباط برقرار کنیم. اما چطور؟Channelsبرای ارتباط برقرار کردن channel هارو داریم که یکمی شبیه pipe ها داخل shell هست.Channels are typed values that allow goroutines to synchronize and exchange information.?هرچقدر به جمله ی فارسی فکر کردم دیدم واقعا منظورو نمیشه رسونداینجا یه مثال نسبتا ساده براش داریم:timerChan := make(chan time.Time)
go func() {
    time.Sleep(deltaT)
    timerChan &lt;- time.Now() // send time on timerChan
}()
// Do something else; when ready, receive.
// Receive will block until timerChan delivers.
// Value sent is other goroutine&#039;s completion time.
completedAt := &lt;-timerChanیک timerChan داریم، که یک channel از نوع time هستش. و بعدش اون فانکشن رو توی بکگراند اجرا میکنیم. داخلش چند ثانیه ای sleep داریم. و بعدش زمان اون لحظه رو داخل timerChan میفرسته. و چون فانکشن بالایی رو با عبارت go اجرا کردیم، بلافاصله میره سراغ اجرای ادامه ی کد، و بعدش اون یکی process  آمادست و منتظره یه value مونده تا از چنل بگیره. و goroutine بلاک میشه تا دریافتش کنه و بعد ادامه بده.SelectThe select statement is like a switch, but the decision is based on ability to communicate rather than equal values.این امکان رو به ما میده که در لحظه به چندین channel گوش کنیم و رفتار برناممون رو کنترل کنیم. در واقع چک میکنه که کدوم یکی آماده برقراری ارتباط هست.select {
case v := &lt;-ch1:
    fmt.Println(&amp;quotchannel 1 sends&amp;quot, v)
case v := &lt;-ch2:
    fmt.Println(&amp;quotchannel 2 sends&amp;quot, v)
default: // optional
    fmt.Println(&amp;quotneither channel was ready&amp;quot)
}اگر هیچ کدوم از channel ها چیزی نفرستادن، default اجرا میشه. و اگر default رو نداشتیم و هیچ کدوم آماده برقراری ارتباط نبودن، صبر میکنه تا یکیشون آماده برقراری ارتباط بشن. و اگر هر دوتاشونم آماده بودن، سیستم به صورت رندوم یکیشونو انتخاب میکنه.این خیلی شبیه switch statement هستش ولی برای ارتباط برقرار کردن...بیاین یکم بیشتر concurrency یاد بگیریمولی قبلش یه اشاره ای به closure بکنم. ما میتونیم از closure ها برای اینکه یه سری عملیات توی بکگراند انجام بشن و لازم نباشه براشون صبر کنیم، استفاده کنیم. (این تنها کاربردشون نیست)این closure ها چی ان؟ خیلی خلاصه بخوام بگم یه نوع فانکشن لوکال بی نام?!خودتون میتونید بیشتر راجبش بخونید.func(message string) {
		fmt.Println(message)
}(&amp;quotHello World!&amp;quot)
// output: Hello World!یا مثالی که خود Rob Pike میزنه:func Compose(f, g func(x float) float)
                  func(x float) float {
     return func(x float) float {
        return f(g(x))
    }
}
print(Compose(sin, cos)(0.5))بگذریم...go func() { // copy input to output
    for val := range input {
        output &lt;- val
    }
}()اینجا ما دوتا channel داریم. و میخوایم input رو روی output کپی کنیم. و نمیخوایم تا تموم شدن کپی صبر کنیم.پس قبل closure امون عبارت go رو می نویسیم، و بعد داخلش یه for داریم که قراره کار خوندن و نوشتن رو برامون انجام بده. پس روی input که یک channel هستش، توسط range حرکت میکنیم ، و هر value ای که داخلش وجود داره رو میریزیم داخل channel دوممون، یعنی output.با استفاده از range ما میتونیم روی یک channel تا زمانی که داخلش value وجود داره حرکت کنیم و وقتی تموم شد خودش خارج میشه.توی پارت بعدی قراره یه load balancer بنویسیم و مثال های واقعی تری داشته باشیم. پس حتما پارت بعدی رو بخونید ؛)پارت اولپارت دومپارت چهارم</description>
                <category>Sajjad Manafi</category>
                <author>Sajjad Manafi</author>
                <pubDate>Fri, 22 Apr 2022 22:35:17 +0430</pubDate>
            </item>
                    <item>
                <title>Concurrency is not parallelism! #2</title>
                <link>https://virgool.io/@SajjadManafi/concurrency-is-not-parallelism-2-kdjpvoxpkdl6</link>
                <description>سلام؛ سعی کردم توی این نوشته، بخش های مهم ارائه Concurrency is not parallelism که توسط Rob Pike رو یه جورایی ترجمه کنم. و خوشحال میشم اگر مشکلی توی متن یا ترجمه بود کامنت بزارید تا تصحیح اش کنم.این ارائه نسبتا طولانیه پس قراره چند تا پارت داشته باشیم و میتونید لینک پارت های قبلی و بعدی رو در انتهای نوشته پیدا کنید.و اسلاید های ارائه رو هم میتونید از اینجا ببینید.خب فرض کنیم میخوایم از دست این کتابای قدیمی خلاص بشیم. پس یه gopher داریم که اونا رو میبره و میندازه داخل زباله سوز. (اینجا Rob Pike یه اشاره هایی به کتابای ++C میکنه?) ولی خب ما فقط یه gopher داریم پس زمان خیلی زیادی طول میکشه این کار تموم بشه مخصوصا اگر تعداد کتاب هامون زیاد باشن.خب اگه ما یه gopher دیگه بیاریم و بهش گاری بدیم چی؟ کار سریعتر انجام میشه. ولی اینجا یه مشکلی هست. اونها میتونند سر راه همدیگه قرار بگیرند. و جلوی زباله سوز یا جایی که کتاب هارو برمیدارند گیر بیافتند، پس لازمه که اونها هماهنگ بشند. پس اونها باید باهم ارتباط برقرار کنند مثل ارسال کردن یه پیام به همدیگه یا...خب اگه همه چیز رو دو برابر کنیم چی؟ gopher ها، زباله سوز ها، گاری ها و حتی تعداد کتاب ها. حالا ما توی همون زمان دو برابر تعداد کتاب جابجا میکنیم و میسوزونیم. ( دو برابر زمانی که فقط یک gopher داشتیم). درسته این میشه parallel. ولی به این فکر کنید که ترکیب concurrent این دو gopher هست که این کارو انجام میده.این طراحی به صورت خودکار parallel نیست. میدونیم که دوتا gopher وجود داره. ولی کی گفته که هر دوتاشون همزمان کار میکنند؟ من میتونم بگم که فقط یک gopher اجازه حرکت در لحظه رو داره. دقیقا مثل داشتن یک کامپیوتر تک هسته ای (core).  اونوقت طراحی همچنان concurrent و درسته. اما ذاتا دیگه parallel نیست. مگر اینکه بتونیم هر دوی این gopher هارو همزمان در لحظه حرکت بدیم. اینجاست که parallelism میاد وسط. یعنی اجرای همزمان دو چیز، نه صرفا داشتن دو چیز.خب ما دیدیم که میتونیم مشکل رو به قطعات concurrent تقسیم کنیم. پس میتونیم مدل های دیگه ای هم ارائه کنیم.حالا ما همونقدر کتاب داریم با همون یدونه زباله سوز، ولی اینبار ۳ تا gopher داریم که باید زحمت کارای مارو بکشن. یکیشون فقط کتاب بار میزنه، یکیشون حمل میکنه و گاری خالی رو بر میگردونه، و یکی هم کتابا رو میندازه تو آتیش. که باعث میشه کارامون سریعتر انجام بشن ولی شایدم نه اونقدر سریع. چون ممکنه متوقف بشن. مثل وقتی که gopher وسطی داره با گاری خالی برمیگرده. در واقع اون لحظه کار جلو نمیره و میشه گفت هیچ کار مفیدی انجام نمیشه.پس میتونیم یه gopher دیگه اضافه کنیم که گاری خالی رو برگردونه. یعنی حالا ۴ تا gopher داریم که هرکدوم یه کار ساده رو انجام میدن. درسته که در اصل تعداد کار های ما بیشتر شده، ولی در عوض سرعت بیشتری داریم. چون ترکیب concurrent قطعات درست مدیریت شده، سریعتر اجرا میشن.تصور کنید همه چیز درست کار کنه و هر ۴ gopher ما مشغول کار باشند، اینجوری کار ما ۴ برابر سریع تر از ورژن اصلی که اول آورده شد پیش میره.  کمی بعیده ولی ممکنه!ما عملکرد رو با اضافه کردن یک رویه concurrent به طراحی موجود بهبود دادیم.در واقع تعداد task هارو افزایش دادیم ولی در نهایت همه چیز (کل برنامه) سریعتر اجرا شد!گوفرهای بیشتری که کار بیشتری انجام می دهند باعث میشود که کار سریعتر تمام شود. این بینشی عمیق تر از parallelism صرف است.ما تونستیم مشکل رو حل کنیم و کار رو تقسیم به چندین رویه مستقل تبدیل کنیم پس حالا ما میتونیم اونها رو به صورت parallel ترکیب کنیم تا یه راه حل نهایی و بهتر بسازیم. در واقع طراحی concurrent ساختار، این موضوع رو برامون آسون تر کرده.البته خب شایدم خبری از parallelization نباشه! ماجرا مثل قبله. کی گفته که همه ی این ۸ تا gopher در یک لحظه مشغول به کارن؟ ممکنه فقط یکیشون مشغول کار باشه. (همون ماجرای کامپیوتر تک هسته و اینا...) و ۷ تای باقی توی اون لحظه بیکار باشن.ولی طراحی ما هنوز درسته! و این خیلی موضوع بزرگ و مهمیه. چون وقتی که در حال اجرای concurrency هستیم نیاز نیست نگران parallelism باشیم. در واقع parallelism موضوع آزادیه که ما میتونیم تصمیم بگیریم که در لحظه چند تا از این gopher های بدبخت مشغول کار باشند.بریم سراغ یه دیزاین دیگه D:بازم ۲ تا gopher داریم. ولی این بار به جای اینکه یه gopher کل مسیر رو طی کنه، یه ایستگاه این وسط داریم. اولیه کتابا رو بار میزنه و میاره میریزتشون وسط، و اون یکی منتظر اومدن کتابا میشه و بعدش اونا رو بار میزنه و میبره میسوزونه.اگه سیستم درست اجرا شده باشه، در اصل ۲ برابر سریعتر از ورژن اصلی کار میکنه. حتی اگر از نظر طراحی کاملا متفاوت با طرح اصلی باشه.واضحه که میتونیم که این طرحو parallelize کنیم. یعنی ۴ تا gopher داریم و معنیش اینه که توان عملیاتیمون ۴ برابر طرح اصلیه.بریم سراغ طرح تقریبا آخر?میایم به اون روش بالاییه که از ۴ تا gopher استفاده میکردیم، یه ایستگاه اضافه میکنیم. و حالا ۸ تا gopher داریم که عین جت دارن کتاب میسوزونن?و مثل همیشه این کافی نیست و ما میتونیم با parallelize کردنش کاملش کنیم. که در واقع از همه ی تکنیک ها و دیزاین ها استفاده شده و ۱۶ تا gopher بیچاره داریم که به سختی کار میکنن :)شما نباید به اجرای parallel برنامه فکر کنید. انتظار من این هست که شما به این فکر کنید که چطور یه مسئله رو تقسیم کنید به اجزای مستقل از هم، و بعد یه راه حل کامل براش پیدا کنید.مثال هایی که تا الان زده شده توی دنیای واقعی نبودن، ولی اصولا میشه اونا شبیه دنیای واقعی دونست:book pile =&gt; web contentgopher =&gt; CPUcart =&gt; marshaling, rendering, or networkingincinerator =&gt; proxy, browser, or other consumerتوی پارت بعدی قراره در مورد concurrency توی go بنویسم و به صورت ساده یاد بدم. پس از دستش ندین ؛)لینک پارت اوللینک پارت سوم</description>
                <category>Sajjad Manafi</category>
                <author>Sajjad Manafi</author>
                <pubDate>Fri, 22 Apr 2022 18:24:00 +0430</pubDate>
            </item>
                    <item>
                <title>Concurrency is not parallelism! #1</title>
                <link>https://virgool.io/@SajjadManafi/concurrency-is-not-parallelism-1-y86nrs16zekh</link>
                <description>سلام؛ سعی کردم توی این نوشته، بخش های مهم ارائه Concurrency is not parallelism که توسط Rob Pike رو یه جورایی ترجمه کنم. و خوشحال میشم اگر مشکلی توی متن یا ترجمه بود کامنت بزارید تا تصحیح اش کنم.این ارائه نسبتا طولانیه پس قراره چند تا پارت داشته باشیم و میتونید لینک پارت های بعدی رو در انتهای نوشته پیدا کنید.و اسلاید های ارائه رو هم میتونید از اینجا ببینید.چیزی که تقریبا همه ی کسانی که حداقل یه بار به go سَرَک کشیدن راجبش میدونن، اینه که go خیلی خوب از  concurrency پشتیبانی میکنه.ولی خب اکثر مردم concurrency رو با parallelism اشتباه میگیرن، یا حتی اونا رو یکی میدونن! درسته به هم مروبط هستند ولی دوتا مفهوم کاملا متمایز از همدیگه هستند! چیزی که مردم رو گیج میکرد این بود که برنامشون رو با چند تا پردازنده اجرا میکردند ولی کندتر عمل میکرد! و اونا فکر میکردند خرابه و کار نمیکنه، ولی در واقع چیزی که خراب بود دیدگاه اونا راجب این مسئله بود.ممکنه اول این نوشته متوجه تفاوتشون نشید، ولی هرچقدر بیشتر بخونید و جلوبرید به درک دقیق و عمیق تری از تفاوت این دو میرسید.خب حالا این concurrency چی هست؟!میشه گفت concurrency ترکیب فرایند هایی (میشه گفت function ها) هستند که به طور مستقل از هم به طور همزمان اجرا میشوند.Concurrency is about dealing with lots of things at once.در واقع concurrency به معنای برخورد همزمان با خیلی چیزاست.پس parallelism چیه؟!خب parallelism اجرای همزمان چیزهایی هستند که میتونن به هم مربوط باشن یا نباشن!Parallelism is about doing lots of things at once.یعنی Parallelism به معنای انجام همزمان چندتا کاره...نتیجه؟این دوتا خیلی شبیه به هم هستند، ولی واقعا دوتا مفهوم جدا از هستند. یعنی concurrency در مورد ساختار است ولی parallelism در مورد اجرا.بنابراین concurrency راهی برای ساخت یک چیز است، تا شاید بتوان از parallelism برای انجام بهتر کار استفاده کرد، اما parallelism، هدف concurrency نیست. هدف concurrency ساختار خوب است.بیشتر بخوام بگم، concurrency راهی برای ساختار یک راه حل برای حل مسئله ارائه می دهد که ممکن است (اما نه لزوما) قابل موازی سازی (parallelism) باشد.مثال بزنم؟کامپیوتر هامون با mouse , keyboard و... در ارتباط هستند، که توسط سیستم عامل به شکل مستقل داخل kernel مدیریت میشن. یعنی به صورت concurrent و  اونها لزوما parallel نیستن.اگر فقط یک processor داشته باشیم، فقط یکی از این ها در لحظه در حال اجرا هستند. بنابرین یک مدل concurrent برای اینها وجود داره. پس ذاتا parallel نیستند. یعنی لازم نیست parallel باشند!بنابرین اگر بخوایم برای اجرای parallel مثال بزنیم، میشه ضرب داخلی بردار رو مثال زد، که میتونی تقسیمش کنیم به چندتا عملیات کوچیکتر و به صورت parallel اجراشون کنیم.بنابرین concurrency راه و ساختاری رو ارائه میده، که بتونیم روی قطعات مستقل از هم کار کنیم یا بهتره اینجوری بگم که concurrency راهی برای ساختار یک برنامه با شکستن آن به قطعاتی است که می توانند به طور مستقل اجرا شوند. و ما نیاز داریم که این قطعات رو با همدیگه هماهنگ کنیم و برای انجام این کار نیاز به نوعی ارتباط بین اونها داریم.و Tony Hoare در سال 1978، مقاله ای به اسم communicating sequential processes نوشت که واقعا یکی از بزرگترین مقالات در علوم کامپیوتر است.که بسیاری از آدمها ابزار هایی برای استفاده از ایده های او در زبان های concurrent مثل Erlang و... ساخته اند. و خب go هم برخی از این ایده هارو توی خودش داره.(و Rob Pike توصیه کرده که حتما این مقاله رو بخونیم)توی پارت بعدی قراره از gopher هامون یخورده کار بکشیم پس حتما برای درک بهتر موضوع این پارت رو هم بخونید ؛) لینک پارت دوملینک پارت سوم</description>
                <category>Sajjad Manafi</category>
                <author>Sajjad Manafi</author>
                <pubDate>Fri, 22 Apr 2022 17:03:36 +0430</pubDate>
            </item>
            </channel>
</rss>