ar
Feedback
Gopher Academy

Gopher Academy

الذهاب إلى القناة على Telegram
3 841
المشتركون
-124 ساعات
+27 أيام
+2230 أيام
جذب المشتركين
سبتمبر '26
سبتمبر '26
+44
في 6 قنوات
أغسطس '26
+69
في 4 قنوات
Get PRO
يوليو '26
+58
في 0 قنوات
Get PRO
يونيو '26
+67
في 0 قنوات
Get PRO
مايو '26
+45
في 0 قنوات
Get PRO
أبريل '26
+24
في 5 قنوات
Get PRO
مارس '26
+10
في 0 قنوات
Get PRO
فبراير '26
+79
في 1 قنوات
Get PRO
يناير '26
+29
في 8 قنوات
Get PRO
ديسمبر '25
+103
في 7 قنوات
Get PRO
نوفمبر '25
+72
في 0 قنوات
Get PRO
أكتوبر '25
+598
في 1 قنوات
Get PRO
سبتمبر '25
+61
في 6 قنوات
Get PRO
أغسطس '25
+84
في 9 قنوات
Get PRO
يوليو '25
+99
في 10 قنوات
Get PRO
يونيو '25
+47
في 7 قنوات
Get PRO
مايو '25
+45
في 1 قنوات
Get PRO
أبريل '25
+63
في 8 قنوات
Get PRO
مارس '25
+90
في 8 قنوات
Get PRO
فبراير '25
+91
في 3 قنوات
Get PRO
يناير '25
+96
في 3 قنوات
Get PRO
ديسمبر '24
+113
في 7 قنوات
Get PRO
نوفمبر '24
+94
في 2 قنوات
Get PRO
أكتوبر '24
+116
في 4 قنوات
Get PRO
سبتمبر '24
+138
في 4 قنوات
Get PRO
أغسطس '24
+101
في 2 قنوات
Get PRO
يوليو '24
+187
في 5 قنوات
Get PRO
يونيو '24
+173
في 11 قنوات
Get PRO
مايو '24
+301
في 2 قنوات
Get PRO
أبريل '24
+185
في 3 قنوات
Get PRO
مارس '24
+172
في 3 قنوات
Get PRO
فبراير '24
+154
في 0 قنوات
Get PRO
يناير '24
+207
في 0 قنوات
Get PRO
ديسمبر '23
+215
في 4 قنوات
Get PRO
نوفمبر '23
+77
في 2 قنوات
Get PRO
أكتوبر '23
+79
في 0 قنوات
Get PRO
سبتمبر '23
+70
في 0 قنوات
Get PRO
أغسطس '23
+108
في 0 قنوات
Get PRO
يوليو '23
+68
في 0 قنوات
Get PRO
يونيو '23
+106
في 0 قنوات
Get PRO
مايو '23
+211
في 0 قنوات
Get PRO
أبريل '23
+142
في 0 قنوات
Get PRO
مارس '23
+56
في 0 قنوات
Get PRO
فبراير '23
+70
في 0 قنوات
Get PRO
يناير '23
+62
في 0 قنوات
Get PRO
ديسمبر '22
+14
في 0 قنوات
Get PRO
نوفمبر '22
+24
في 0 قنوات
Get PRO
أكتوبر '22
+15
في 0 قنوات
Get PRO
سبتمبر '22
+78
في 0 قنوات
Get PRO
أغسطس '22
+47
في 0 قنوات
Get PRO
يوليو '22
+36
في 0 قنوات
Get PRO
يونيو '22
+26
في 0 قنوات
Get PRO
مايو '22
+27
في 0 قنوات
Get PRO
أبريل '22
+14
في 0 قنوات
Get PRO
مارس '22
+21
في 0 قنوات
Get PRO
فبراير '22
+13
في 0 قنوات
Get PRO
يناير '22
+24
في 0 قنوات
Get PRO
ديسمبر '21
+51
في 0 قنوات
Get PRO
نوفمبر '21
+107
في 0 قنوات
Get PRO
أكتوبر '21
+13
في 0 قنوات
Get PRO
سبتمبر '21
+31
في 0 قنوات
Get PRO
أغسطس '21
+29
في 0 قنوات
Get PRO
يوليو '21
+41
في 0 قنوات
Get PRO
يونيو '21
+29
في 0 قنوات
Get PRO
مايو '21
+26
في 0 قنوات
Get PRO
أبريل '21
+49
في 0 قنوات
Get PRO
مارس '21
+376
في 0 قنوات
التاريخ
نمو المشتركين
الإشارات
القنوات
21 سبتمبر+1
20 سبتمبر+2
19 سبتمبر0
18 سبتمبر+1
17 سبتمبر+6
16 سبتمبر+1
15 سبتمبر+2
14 سبتمبر+2
13 سبتمبر+3
12 سبتمبر+3
11 سبتمبر+4
10 سبتمبر+3
09 سبتمبر0
08 سبتمبر+1
07 سبتمبر+3
06 سبتمبر+3
05 سبتمبر0
04 سبتمبر0
03 سبتمبر+4
02 سبتمبر+1
01 سبتمبر+4
منشورات القناة
🔵 عنوان مقاله Data Races and the Limits of ThreadSanitizer in C and Go 🟢 خلاصه مقاله: در دنیای برنامه‌نویسی همواره یکی از نگرانی‌های اصلی توسعه‌دهندگان، مشکلات مربوط به مسابقه داده‌ها (Data Races) است. این خطا زمانی رخ می‌دهد که چندین رشته (Thread) همزمان به‌طور ناهمزمان و بدون کنترل صحیح به داده‌های مشترک دسترسی پیدا کنند، که این امر می‌تواند باعث ایجاد رفتارهای پیش‌بینی‌ناپذیر و خطاهای سخت شناسایی و رفع شود. به همین دلیل، ابزارهای تشخیص مسابقه داده‌ها مانند ThreadSanitizer، نقش حیاتی در توسعه برنامه‌های پایدار و مطمئن ایفا می‌کنند. در این مقاله، نگاهی می‌اندازیم به نحوه عملکرد ThreadSanitizer، موتور قدرتمند در پس‌زمینه‌اش که توانایی کشف مسابقه‌های داده‌ها در زبان‌های برنامه‌نویسی مانند Go و C را دارد. این ابزار با تجزیه و تحلیل دقیق عملیات اجرایی، تلاش می‌کند تا در حین اجرای برنامه، برخوردهای ناهمزمان را تشخیص دهد و هشدارهای لازم را صادر کند. اما، در کنار این امکانات، محدودیت‌هایی نیز وجود دارد که در موارد خاص، ممکن است نتواند تمامی مسابقه‌ها را شناسایی کند. یکی از مهم‌ترین محدودیت‌ها زمانی است که دو شیء (Object) در سیستم‌های همزمان، تحت کنترل همگام‌سازی متفاوتی قرار دارند، مانند زمانی که هر کدام در مسیرهای اجرای جداگانه با نقاط همگرایی متفاوتی مدیریت می‌شوند. در چنین مواردی، ThreadSanitizer ممکن است نتواند این مسابقه‌های پنهان یا ناپیدای داده‌ها را کشف کند، چرا که مسیرهای همزمانی هر شیء به صورت جداگانه بررسی می‌شود و ارتباطات میان آن‌ها به سادگی قابل تشخیص نیستند. این موضوع نشان می‌دهد که ابزارهای هشداردهنده نمی‌توانند همیشه انتظارات کامل را برآورده سازند و باید در کنار آن‌ها، روش‌های دیگر کنترل همزمانی نیز مورد استفاده قرار گیرد. در مجموع، درک محدودیت‌های ThreadSanitizer اهمیت زیادی دارد تا برنامه‌نویسان بتوانند بیشتر به استراتژی‌های پیشگیری و طراحی سیستم‌هایی مقاوم در مقابل مسابقه‌های داده‌ها فکر کنند. این ابزار، با وجود کارایی بالا، نمی‌تواند جایگزین رویکردهای کامل و جامع در مدیریت همزمانی باشد و بهترین استفاده زمانی است که به عنوان یک قسمت از استراتژی کلی برای تضمین کیفیت کد به کار رود. #برنامه‌نویسی #RaceCondition #ThreadSanitizer #همزمانی 🟣لینک مقاله: https://theconsensus.dev/p/2026/09/06/data-races-and-the-limits-of-threadsanitizer-in-c-and-go.html ➖➖➖➖➖➖➖➖ 👑 @gopher_academy

2
🔵 عنوان مقاله GoHT: Haml, Slim and EGO Template Engine for Go 🟢 خلاصه مقاله: در دنیای توسعه برنامه‌های تحت زبان Go، یکی از چالش‌های رایج، هماهنگی و هم‌زمانی نوشتن قالب‌های وب با کد اصلی است. اما حالا ابزارهای جدیدی ارائه شده‌اند که این فرآیند را بسیار ساده‌تر می‌کنند. در این میان، سیستم‌های قالب‌سازی Haml، Slim و EGO برای زبان Go به توسعه‌دهندگان امکان می‌دهند تا به‌صورت هم‌زمان و هم‌پوشان، هم قالب‌ها و هم کدهای منطق برنامه‌نویسی را بنویسند. این رویکرد باعث می‌شود فرآیند توسعه سریع‌تر، سازمان‌یافته‌تر و قابل نگهداری‌تر شود، مخصوصاً زمانی که نیاز به ساخت قالب‌های پیچیده و پویا دارید. در این فریمورک‌ها، امکان افزودن بلوک‌های @haml، @slim و @ego در فایل‌های مربوطه فراهم شده است، که باعث می‌شود قالب‌ها را به صورت خوانا و نزدیک به HTML استاندارد بنویسید. این قابلیت‌ها، به توسعه‌دهندگان اجازه می‌دهند قالب‌ها را در کنار کدهای اصلی زبان Go طراحی و ویرایش کنند، بدون نیاز به جدا کردن فایل‌های قالب یا استفاده از روش‌های پیچیده. علاوه بر این، این روش نوآورانه، بهره‌وری تیم را افزایش می‌دهد و توسعه برنامه‌های تحت وب را بسیار آسان‌تر می‌سازد. در نتیجه، استفاده از این موتورهای قالب‌سازی ترکیبی، یک انقلاب در توسعه وب با زبان Go است. با این ابزارها، نوشتن قالب‌های زیبا، قابل‌فهم و انعطاف‌پذیر در کنار کدهای اصلی برنامه، به روشی ساده و کارآمد تبدیل می‌شود. این فناوری، راه‌حلی مناسب برای توسعه‌دهندگانی است که به دنبال روشی مدرن و روان برای ساخت برنامه‌های وب هستند و می‌خواهند کارآمدی و کیفیت پروژه‌های خود را به سطح بالاتری برسانند. #برنامه_نویسی #Go #قالب_سازی #توسعه_وب 🟣لینک مقاله: https://goht.dev/ ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
139
3
🔵 عنوان مقاله Rune: A Fast, Native, Open Source IDE Built in Go 🟢 خلاصه مقاله: رون: یک محیط توسعه سریع، بومی و منبع باز با پایه زبان Go رون یک محیط توسعه یکپارچه و قدرتمند است که بر پایه زبان برنامه‌نویسی Go ساخته شده و به عنوان یک IDE منبع باز و سبک شناخته می‌شود. این ابزار، با هدف فراهم کردن تجربه برنامه‌نویسی سریع و کارآمد طراحی شده است، به گونه‌ای که توسعه‌دهندگان بتوانند فرآیند کدنویسی را بدون محدودیت‌های سیستم‌های سنگین یا نیاز به ابزارهای خارجی انجام دهند. این IDE با بهره‌گیری از شتاب‌دهنده‌های گرافیکی GPU، عملکرد بسیار بالایی در اجرای وظایف مختلف دارد. یکی از ویژگی‌های منحصربه‌فرد آن، بهره‌گیری از تکنولوژی‌های نوین در نمایش و واکنش سریع به عملیات کاربر است، که این امر در نسخه‌های جدید بهبود یافته است و اکنون به سطحی رسیده است که به‌راحتی با نمونه‌های معتبر مثل Alacritty و Ghostty رقابت می‌کند، بدون آنکه مجبور باشد از CGo در مسیرهای حساس استفاده کند. در این مقاله، جزئیات جالبی درباره نحوه طراحی و بهینه‌سازی ترمینال یکپارچه در رون ارائه شده است. تیم توسعه نشان داده است که با رعایت اصول برنامه‌نویسی مدرن و بهره‌گیری از قابلیت‌های پیشرفته زبان Go، می‌توان یک ترمینال سریع، بی‌نقص و در عین حال سبک و قابل انعطاف ساخت که در مقایسه با ترمینال‌های موجود، عملکرد فوق‌العاده‌تری دارد و مصرف منابع بسیار کمتری دارد. در نهایت، رون نشان می‌دهد که با بهره‌گیری از فناوری‌های نوین و رعایت استانداردهای کدباز، می‌توان ابزارهای توسعه‌ای قدرتمند و در دسترس ساخت که نه تنها نیازهای حرفه‌ای‌های برنامه‌نویس را برآورده می‌کنند، بلکه قابل توسعه و بهبود در آینده نیز هستند. این پروژه نمونه‌ای الهام‌بخش است از آنچه زبان Go و فلسفه متن‌باز می‌توانند در عرصه توسعه ابزارهای برنامه‌نویسی ارائه دهند. #رون #برنامه‌نویسی #زبانGo #منبعباز 🟣لینک مقاله: https://rune.build/blog/rune-is-now-open-source ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
149
4
🔵 عنوان مقاله wasm2go: Translate WebAssembly Binaries into Go Code 🟢 خلاصه مقاله: در دنیای توسعه نرم‌افزار، یکی از چالش‌های مهم، ادغام کدهای مختلف در یک برنامه است. در این راستا، ابزارهایی مانند wasm2go نقش بسزایی دارند. این ابزار یک کامپایلر است که امکان ترجمه باینری‌های WebAssembly (WASM) را به کد زبان Go فراهم می‌کند، به گونه‌ای که بتوان آن را به عنوان یک بسته مستقل و قابل استفاده در برنامه‌های نوشته‌شده با زبان Go، به‌راحتی استفاده کرد. این قابلیت به توسعه‌دهندگان این امکان را می‌دهد تا بدون نیاز به موتورهای اجرای WASM، بتوانند کتابخانه‌های C ساخته‌شده با SDK های مبتنی بر WASI را در برنامه‌های Go خود استفاده کنند. با بهره‌گیری از wasm2go، می‌توانید به سادگی زیربنای برنامه‌تان را گسترش دهید، بدون اینکه حجم نهایی برنامه خود را با موتورهای شوک‌دار مانند ماشین مجازی WASM افزایش دهید. این ابزار به شما کمک می‌کند تا کدهای کاربردی را به صورت مستقیم و بهینه وارد پروژه‌های خود کنید، در نتیجه کارایی و سرعت اجرای برنامه‌های تان بهبود می‌یابد. در نهایت، این روش، راهی کارآمد و سبک برای ادغام فناوری‌های مختلف در برنامه‌های مدرن است. #ولوبازار #توسعه_وب #برنامه‌نویسی #وبAssembly 🟣لینک مقاله: https://github.com/goccy/wasm2go ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
160
5
🔵 عنوان مقاله Scaling Go in CI by Replacing actions/setup-go 🟢 خلاصه مقاله: در محیط‌های توسعه‌ی مستمر، یکی از چالش‌هایی که برنامه‌نویسان روبه‌رو می‌شوند، مدیریت بهینه کش‌ها است؛ مخصوصاً زمانی که از ابزارهای خودکار و عملیات‌های آماده‌ی GitHub استفاده می‌کنند. در این مقاله به بررسی مشکلی می‌پردازیم که هنگام استفاده از اکشن رسمی GitHub، یعنی actions/setup-go، اتفاق می‌افتد. همانطور که می‌دانید، این اکشن برای راه‌اندازی سریع و آسان زبان برنامه‌نویسی Go در فرآیندهای CI طراحی شده است و نقش مهمی در تسریع فرآیندهای تست و ساخت دارد. متأسفانه، زمانی که چندین شغل هم‌زمان در CI اجرا می‌شوند، ممکن است تداخل‌هایی در کش‌ها رخ دهد. این تداخل‌ها منجر به این می‌شود که کش‌ها در میان اجراهای مختلف به‌درستی به‌روزرسانی نشوند و در نتیجه، مجبور می‌شوید کش‌ها را به صورت دستی پاک یا اصلاح کنید. یکی دیگر از مشکلات رایج این است که کش‌ها معمولاً تا زمانی که فایل‌های مرتبط با پیکربندی Go، مانند فایل go.mod، تغییر نکنند، به‌روزرسانی نمی‌شوند و در نتیجه، تغییری در تکنولوژی‌های مورد استفاده را در نظر نمی‌گیرند. دلیل این موضوع این است که اکشن actions/setup-go، بر اساس فایل‌های مشخص و تغییرات آن‌ها تصمیم می‌گیرد که کش را به‌روزرسانی کند یا خیر. در نتیجه، اگر فایل go.mod تغییر نکند، کش قدیمی باقی می‌ماند و نسخه‌ی قدیمی‌تر برنامه‌ها و وابستگی‌ها به‌کار گرفته می‌شود. این وضعیت ممکن است باعث بروز مشکلات در ساخت و تست برنامه‌ها و کاهش سرعت توسعه شود. برای حل این مشکل، توصیه می‌شود که تیم‌های توسعه دهنده در فرآیندهای CI خود، راهکارهای جایگزین یا بهبودهای خاصی را implement کنند. یکی از روش‌ها، جایگزین کردن اکشن actions/setup-go با راهکارهای سفارشی است که کنترل بیشتری بر مدیریت کش دارند یا بر اساس تغییرات فایل‌های کلیدی، کش را به‌روزرسانی می‌کنند. همچنین می‌توان از استراتژی‌های تعریف‌شده در فایل‌های YAML و تعیین محدودیت‌هایی برای کش‌ها بهره برد تا همزمانی و هماهنگی بهتری بین شغل‌ها برقرار شود. در نهایت، درک مسئله و پیاده‌سازی راهکارهای مناسب، می‌تواند نقش مهمی در افزایش بهره‌وری و تسریع گردش کار در پروژه‌های مبتنی بر Go در محیط‌های CI و CD ایفا کند، و مطمئن شوید که هر نسخه‌ی جدید برنامه، به‌درستی ساخته و آزمایش می‌شود و کش‌ها همواره به‌روز هستند. #هوشمندسازی_CI #go #کش_موتور #توسعه_نرم‌افزار 🟣لینک مقاله: https://www.cloudx.ai/posts/setup-go ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
181
6
🔵 عنوان مقاله golang-set 3.0: A Simple, Well-Tested, Generic Set Type 🟢 خلاصه مقاله: در نسخه ۳ از پکیج "گولانگ-ست"، یک نوع مجموعه ساده، آزمایش‌ شده و عمومی ارائه شده است که به کاربران این زبان برنامه‌نویسی امکان می‌دهد مجموعه‌های خاص خود را با سهولت و اطمینان پیاده‌سازی کنند. هرچند آینده‌ی نسخه‌های بعدی ممکن است نوع مجموعه عمومی رسمی در زبان گولانگ وارد شود، اما در حال حاضر، این نسخه‌ با ثبات و کارآمد، گزینه‌ای کامل و قابل اعتماد است که نیازهای رایج برنامه‌نویسی را برطرف می‌کند. این بسته‌ی نرم‌افزاری، ساخت مجموعه‌ها را بسیار آسان و سریع می‌سازد و به طور کامل آزمایش شده است تا کیفیت و کارایی بالا را تضمین کند. توسعه‌دهندگان می‌توانند به راحتی از آن در پروژه‌های مختلف استفاده کنند و مطمئن باشند که برای مدیریت داده‌های مجموعه‌ای، پاسخگو و قابل توسعه است. این نسخه به طور ویژه برای کسانی طراحی شده است که به دنبال راه‌حلی پایدار و قابل اطمینان در زمینه مجموعه‌های داده هستند و قصد دارند کد خود را نگهداری و توسعه دهند. در کل، "گولانگ-ست ۳.۰" یک ابزار قدرتمند است که نیازهای معمول برنامه‌نویسان را برآورده می‌کند و با قابلیت‌های گسترده و تست‌شده، به یکی از گزینه‌های برتر در حوزه مدیریت مجموعه‌ها تبدیل شده است. #گولانگ #برنامه‌نویسی #کد_پایدار #مجموعه‌ها 🟣لینک مقاله: https://github.com/deckarep/golang-set ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
199
7
لا يوجد نص...
231
8
🔵 عنوان مقاله Size-Specialized Memory Allocation in Go 1.27 🟢 خلاصه مقاله: در نسخه ۱.۲۷ زبان برنامه‌نویسی گو، بهینه‌سازی‌های مهمی در نحوه تخصیص حافظه صورت گرفته است. یکی از این بهبودها مربوط به تخصیص حافظه‌های کوچک است؛ به طوری که عملیات‌های تخصیص حافظه‌های زیر ۸۰ بایت تا ۳۰ درصد سریع‌تر شده‌اند. این بهبود عملکرد، تأثیر چشمگیری در سرعت اجرای برنامه‌های شما دارد و تنها کافی است که دوباره‌سازی برنامه خود را انجام دهید تا از این مزایا بهره‌مند شوید. در این نسخه، دلیل اصلی این بهبود و انتخاب ۸۰ بایت به عنوان «نقطه عسل» (همان نقطه‌ی بهینه) چیست؟ توسعه‌دهندگان گو، در تلاش بودند تا نمونه‌هایی از حافظه‌های کوچک را به صورت مؤثرتر مدیریت کنند و در نتیجه، سرعت تخصیص آن‌ها را به میزان قابل توجهی افزایش دهند. انتخاب ۸۰ بایت به عنوان نقطه‌ی عسل، بر اساس تحلیل دقیق حجم‌های حافظه‌ای است که بیشترین تکرار و اهمیت را در برنامه‌ها دارند، و کمک می‌کند تا حافظه به صورت بهینه‌تر و کاراتر مدیریت شود. در مجموع، این بهبود در حافظه‌های کوچک در نسخه جدید، نه تنها کارایی برنامه‌ها را بالا می‌برد، بلکه فرآیند توسعه و بهبود آن‌ها را نیز سریع‌تر می‌کند. بنابراین، اگر در پروژه‌های خود از زبان Go استفاده می‌کنید، توصیه می‌شود برنامه خود را مجدداً کامپایل کنید تا از این بهبودهای قابل توجه بهره‌مند شوید و عملکرد برنامه‌های خود را به سطح جدیدی برسانید. #هدایت_حافظه #گو_نسخه_۱_۲۷ #بهینه‌سازی_کارایی #برنامه‌نویسی 🟣لینک مقاله: https://go.dev/blog/size-specialized-allocations ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
231
9
🔵 عنوان مقاله A 40ms Go GC Pause Caused by Swap 🟢 خلاصه مقاله: امروز می‌خواهم به تجربه‌ای مهم در زمینه زبان برنامه‌نویسی Go اشاره کنم که شاید برای توسعه‌دهندگان زیادی آشنا باشد. در این حادثه، یک توقف ۴۰ میلی‌ثانیه‌ای در فرآیند جمع‌آوری زباله (Garbage Collection) به دلیل استفاده از سوپ ایجاد شد. این مشکل وقتی رخ داد که تصمیم گرفتم در محیط تولید، از سوپ برای جذب نوسانات حافظه استفاده کنم. در ابتدا، هدف من از فعال‌سازی سوپ در سیستم این بود که بتوانم بهره‌وری حافظه را بهتر مدیریت و نوسانات ناگهانی مصرف رم را کنترل کنم. اما به زودی متوجه شدم این اقدام من سبب توقف قابل توجهی در اجرای برنامه شد. توقف ۴۰ میلی‌ثانیه‌ای که پس از سوپ رخ داد، تاثیر قابل توجهی بر تجربه کاربر و کارایی سیستم داشت. این تجربه نشان داد که استفاده نااگاهانه یا بدون برنامه‌ریزی صحیح از قابلیت‌های جمع‌آوری زباله می‌تواند مشکلاتی جدی در پرفورمنس ایجاد کند. من این مقاله را نوشتم تا شما از اشتباه من درس بگیرید و اجازه ندهید در محیط‌های حساس، تصمیمات ناگهانی و ناآگاهانه منجر به کاهش کارایی سیستم شما شود. بهتر است قبل از فعال‌سازی هر قابلیت جدید، آزمایش‌های دقیقی انجام دهید و عواقب احتمالی را بسنجید، زیرا در مواردی مانند این، یک تصمیم کوچک می‌تواند منجر به بروز توقف‌های ناخوشایند و کاهش رضایت کاربر شود. #برنامه‌نویسی #GoLang #مدیریت_حافظه #بهبود_عملکرد 🟣لینک مقاله: https://frn.sh/go-gc/ ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
226
10
امروز، ۲۶ شهریور، زادروز پسر کوروش بزرگه؛ روزی که به‌عنوان «روز پسر» نام‌گذاری شده.
265
11
[pointer][pointer][pointer][pointer] ↓ ↓ heap heap ↓ ↓ Restaurant Restaurant ب CPU باید pointer را دنبال کند تا به object برسد. بنابراین Value Type می‌تواند cache locality بهتری ایجاد کند. البته این به اندازه و ساختار واقعی struct و access pattern بستگی دارد؛ نمی‌شود گفت pointer همیشه بد و value همیشه خوب است. ۸. نکته بسیار مهم: Pointer همیشه بد نیست این را حتماً در ذهن داشته باش. این حرف: Pointer → Value = همیشه performance بهتر درست نیست. مثلاً اگر struct خیلی بزرگ باشد: type HugeStruct struct { Data [10000]byte } کپی کردن آن ممکن است گران باشد. در چنین شرایطی: func process(x HugeStruct) می‌تواند هزینه‌ی copy داشته باشد. در حالی که: func process(x *HugeStruct) فقط یک pointer را منتقل می‌کند. پس تصمیم بین: T و: *T به مواردی مثل: اندازه struct تعداد allocationها escape analysis lifetime object mutation تعداد pointerها memory layout access pattern وابسته است. ۹. احتمالاً اتفاق مهمی که Uber انجام داده اگر بخواهیم ساده‌سازی کنیم، مشکل آنها احتمالاً چیزی شبیه این بوده: Search Request ↓ Ranking ↓ Thousands of objects ↓ Heap allocations ↓ GC ↓ CPU consumption ↓ Latency با تغییر data structures: Search Request ↓ Ranking ↓ More value-based structures ↓ Fewer heap allocations ↓ Less GC work ↓ Less CPU ↓ Lower latency و درواقعه GC حدود ۴۰٪ CPU را مصرف می‌کرده و این تغییرات باعث کاهش شدید این هزینه شده است. یک نکته خیلی مهم برای Go Developer اگر بخواهم این بخش را در یک جمله خلاصه کنم: آنها فقط کد را سریع‌تر نکردند؛ تعداد و شکل objectهایی را که Go باید در heap مدیریت و توسط GC بررسی کند تغییر دادند. این نوع optimization در سیستم‌های high-throughput خیلی مهم است. و نکته جالب‌تر این است که برای پیدا کردن همین bottleneckها از production profiling استفاده کردند، نه اینکه صرفاً حدس بزنند کدام کد کند است.
345
12
بذارید دقیق و با مثال توضیح بدیم. ۱. اول ببینیم Embedding چیست فرض کن برای هر رستوران یک embedding داریم: Restaurant: Pizza Hut Embedding: [0.1823, -0.4211, 0.7328, 0.0912, ...] این اعداد معمولاً float32 هستند. مثلاً یک embedding با 768 dimension: type Embedding []float32 هر float32 برابر ۴ بایت است: 768 × 4 = 3072 bytes یعنی تقریباً 3KB برای هر embedding. حالا اگر میلیون‌ها رستوران/آیتم داشته باشی، حجم حافظه خیلی سریع بالا می‌رود. ۲. کاهش دقت اعشار یعنی چه؟ فرض کن مقدار اصلی: 0.18237491 باشد. برای مدل‌های ML همیشه لازم نیست تمام این دقت را نگه داریم. می‌توان آن را مثلاً به چیزی مثل: 0.1824 تقلیل داد. اینجا یک نکته مهم وجود دارد: کاهش precision الزاماً به معنی تبدیل float32 به float16 نیست. روش‌های مختلفی وجود دارد، مثل: FP32 → FP16 FP32 → BF16 Quantization INT8 و روش‌های دیگر ایده کلی این است: دقت کمتر ↓ حجم کمتر ↓ Memory bandwidth کمتر ↓ Cache بهتر ↓ CPU / latency کمتر مثلاً اگر از float32 به float16 برویم: float32 = 4 bytes float16 = 2 bytes پس embedding: 768 × 4 = 3072 bytes تبدیل می‌شود به: 768 × 2 = 1536 bytes یعنی تقریباً ۵۰٪ کاهش حجم. در پروژه Uber طبق توضیحی که آوردی، ترکیب روش‌های فشرده‌سازی به حدود ۴۶٪ کاهش حجم embeddingها رسیده است. ۳. اما قسمت جالب‌تر: Pointer → Value این قسمت برای یک برنامه‌نویس Go خیلی مهم‌تر است. فرض کن چنین structای داریم: type Restaurant struct { ID string Name string Price float64 } و جایی در سیستم: func getRestaurant() *Restaurant { return &Restaurant{ ID: "123", Name: "Pizza", Price: 12.5, } } اینجا داریم pointer برمی‌گردانیم: *Restaurant یعنی یک object روی heap ساخته می‌شود و ما pointer آن را نگه می‌داریم. چرا این می‌تواند برای GC بد باشد؟ فرض کن سیستم Uber Eats در هر search هزاران یا میلیون‌ها object بسازد: Search │ ├── Restaurant pointer ├── Restaurant pointer ├── ... └── Restaurant pointer مثلاً: []*Restaurant به جای: []Restaurant در حالت pointer، تعداد زیادی object جداگانه داریم که GC باید آنها را بررسی و مدیریت کند. یعنی: Heap ├── Restaurant #1 ├── Restaurant #2 ├── Restaurant #3 ├── ... هرچه allocation بیشتر باشد، کار GC هم بیشتر می‌شود. ۴.ا Value Type چه تغییری ایجاد می‌کند؟ به جای: restaurants := []*Restaurant{ &Restaurant{...}, &Restaurant{...}, &Restaurant{...}, } می‌توانیم داشته باشیم: restaurants := []Restaurant{ {ID: "1", Name: "A"}, {ID: "2", Name: "B"}, {ID: "3", Name: "C"}, } یعنی objectها داخل خود slice قرار می‌گیرند. به شکل ساده: Pointer []*Restaurant slice ├── pointer ──────> Restaurant #1 ├── pointer ──────> Restaurant #2 └── pointer ──────> Restaurant #3 Value []Restaurant slice ├── Restaurant #1 ├── Restaurant #2 └── Restaurant #3 در حالت دوم، معمولاً allocationهای جداگانه‌ی کمتری داریم. ۵. چرا GC اینجا خیلی مهم است؟ ا Go یک Garbage Collector دارد. وقتی objectهایی روی heap ساخته می‌شوند: r := &Restaurant{} و دیگر کسی به آنها نیاز ندارد، GC باید تشخیص دهد: این object دیگر قابل دسترسی نیست، پس می‌توانم حافظه‌اش را آزاد کنم. اگر برنامه تعداد بسیار زیادی object کوچک تولید کند: request ↓ 1000 objects ↓ 10,000 objects ↓ 100,000 objects ا GC باید دائماً این heap را بررسی کند. در یک سیستم search با traffic بسیار بالا، این هزینه می‌تواند قابل توجه باشد. ۶. یک مثال واقعی‌تر در Go فرض کن Search Engine شما برای هر request این کار را می‌کند: type Result struct { ID string Score float64 Restaurant *Restaurant } اگر 10,000 نتیجه داشته باشیم: []Result اما هر Result به یک object دیگر اشاره می‌کند: Result | +----> Restaurant | +----> Restaurant | +----> Restaurant این ساختار pointer-heavy است. اگر بتوانیم: type Result struct { ID string Score float64 Restaurant Restaurant } داشته باشیم، data locality بهتر می‌شود و objectهای جداگانه‌ی کمتری ساخته می‌شوند. ۷.ا Data Locality هم مهم است این قسمت خیلی جالب است. ا CPU دوست دارد داده‌هایی که پشت سر هم هستند را از memory/cache بخواند. مثلاً: []Restaurant ممکن است در حافظه تقریباً این‌طور باشد: [Restaurant][Restaurant][Restaurant][Restaurant] ولی: []*Restaurant ممکن است:
239
13
🔰 بهینه‌سازی Embeddingها در شرکت Uber با هدف کاهش دقت اعشار و فشرده‌سازی تا ۴۶٪، در کنار تبدیل Pointerها به Value Typeها در کد Go که باعث شد مصرف ۴۰ درصدی CPU توسط Garbage Collector به‌شدت کاهش پیدا کند. 🟢 توضیحات کامل در لینک زیر: 👇 🔴 part 1: 🔴 part 2: ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
473
14
مهندسان اوبر در یک بلاگ‌پست فنی جزییات جالبی از نصف کردن تاخیر جستجوی Uber Eats منتشر کرده‌اند. فارغ از بهینه‌سازی‌های مرسوم معماری، استفاده عملی‌شان از ایجنت‌های هوش مصنوعی برای تیونینگ کد توجه من را جلب کرد. خلاصه تغییرات کلیدی: ۱. تغییر متریک اصلی به ATF (مدت‌زمان رندر اولین بخش تصویر در گوشی کاربر) و تبدیل رندر HTML به یک پایپلاین کاملا Async. ۲. جداسازی Hydration به دو فاز مجزا؛ واکشی سریع سیگنال‌های رتبه‌بندی برای اجرای زودهنگام مدل‌ها، و لود موازی جزییات نمایشی (قیمت، تصویر و...). ۳. بهینه‌سازی امبدینگ‌ها با کاهش دقت اعشار و فشرده‌سازی تا ۴۶٪، در کنار تبدیل پوینترها به Value types در کد Go که مصرف ۴۰ درصدی پردازنده توسط Garbage Collector را به شدت کم کرد. ۴. استفاده از لوپ خودکار ایجنتی؛ ایجنت با تحلیل پروفایل‌های زنده پروداکشن، باتل‌نک‌های ریز را پیدا می‌کرد، کد بهینه‌سازی می‌نوشت، پول‌ریکوئست می‌زد و با بنچمارک نتیجه را می‌سنجید. ۵. برنامه‌های آینده بر پایه مایکروبچینگ، فیلترینگ در لایه ایندکس (Zero-Pass Ranking) و استریم فرگمنت‌های نتایج به سمت کلاینت. لینک مقاله: بخوانیدش، خیلی جالبه! uber.com/us/en/blog/uber-eats-search-pipeline/ | <Mehdi Allahyari/>
252
15
میدلولها خیلی بدردتون میخوره چند روز بعد از اینکه درباره تجربه خوبم با Graphify نوشتم، از workflow اصلی همون پروژه حذفش کردم! نه چون Graphify بد بود. اتفاقاً چون استفاده ازش باعث شد دقیق‌تر بفهمم از این مدل ابزارها چی می‌خوام. مسئله‌ای که داشتم فقط Search داخل codebase نبود. مسئله اصلی Orientation بود. هر تسک جدید با چند سؤال تکراری شروع می‌شد: این component کجا استفاده شده؟ این composable رو چی مصرف می‌کنه؟ این feature بین چه فایل‌هایی پخش شده؟ اگه این قسمت رو تغییر بدم، چه چیزهای دیگه‌ای تحت تأثیر قرار می‌گیرن؟ و Graphify برای اولین بار این حس رو بهم داد که قبل از باز کردن فایل‌ها، می‌شه یه نقشه از پروژه داشت. بعد رفتم سراغ Codebase Memory MCP تا ببینم همین ایده وقتی مستقیم وارد workflow خود Coding Agent می‌شه چه فرقی می‌کنه. مهاجرت هم اصلاً بی‌دردسر نبود :))) بعد از نصب و Index کردن پروژه، MCP داخل Codex با خطای Transport closed شکست خورد. CLI کار می‌کرد، Index سالم بود، حتی MCP خام هم جواب می‌داد؛ ولی چیزی که واقعاً می‌خواستم یعنی workflow داخل Codex کار نمی‌کرد. بعد از بررسی و سه Clean Start مستقل، MCP بالاخره در هر سه Session پایدار کار کرد و migration رو نهایی کردم. اما بخش جالب‌تر برای من اولین تسک واقعی بعد از مهاجرت بود. می‌خواستم نسخه موبایل پورتفولیوم رو اصلاح کنم: Header، Language Selector، Bottom Navigation و Responsive behavior. قبل از اینکه شروع کنم فایل‌ها رو بگردم، از CBM خواستم محدوده کار رو پیدا کنه. یکی از چیزهایی که سریع مشخص کرد این بود که BottomNav.vue از قبل توی پروژه وجود داره، ولی اصلاً داخل Layout mount نشده. همین کشف ساده جلوی ساختن دوباره چیزی رو گرفت که از قبل داشتم. ولی در همون تسک محدودیتش هم مشخص شد. و CBM معماری اولیه رو خوب پیدا کرد، اما detect_changes نتونست impact واقعی یه تغییر UI رو کامل بفهمه. Responsive CSS، Safe Area، RTL، Overflow توی عرض 320px و چیزی که کاربر واقعاً توی Browser می‌بینه، لزوماً توی Call Graph مشخص نیست. و اینجا به نتیجه‌ای رسیدم که به نظرم از خود مهاجرت مهم‌تره: من دیگه Graphify و Codebase Memory رو دو رقیب مستقیم نمی‌بینم. برای پروژه‌های Code-heavy، جایی که بیشتر سؤال‌ها درباره implementation فعلی، dependencyها، refactor و impact تغییراته، CBM برای من انتخاب طبیعی‌تریه. ولی وقتی پروژه فقط Code نیست و PRD، ADR، Research، Architecture Docs، PDF، Diagram و Domain Knowledge بخش مهمی از پروژه‌ان، Graphify هنوز ارزش خیلی جدی‌ای داره. حتی برای یه محصول بزرگ احتمالاً از هر دو استفاده می‌کنم: کدبیس Memory برای اینکه بفهمم: «الان کد چطور کار می‌کنه؟» و Graphify برای اینکه بفهمم: «چرا اصلاً اینطوری طراحی شده؟» با یه شرط مهم: هیچ‌کدوم Source of Truth نهایی نیستن. و Graph کمک می‌کنه سریع‌تر برسم به جواب. ولی برای implementation هنوز سورس رو می‌خونم، برای requirement خود PRD رو چک می‌کنم و برای UI هنوز Browser حرف آخر رو می‌زنه. تجربه کامل migration، failure، تست MCP و اولین task واقعی بعد از مهاجرت رو اینجا نوشتم: http://aliarghyani.vercel.app/fa/blog/graphify-to-codebase-memory-mcp | <Ali Arghyani/>
227
16
🔵 عنوان مقاله Claude Fable 5.1 and Mythos 5.1 (8 minute read) 🟢 خلاصه مقاله: شرکت انتروپیک به تازگی نسخه‌های جدید مدل‌های خود را معرفی کرده است؛ Claude Fable 5.1 و Mythos 5.1. این نسخه‌ها با بهبود در قابلیت‌های کدنویسی و تحقیقات، به کاربران امکان می‌دهند تا در حوزه‌های تخصصی با کارایی بیشتری فعالیت کنند. همچنین، قیمت‌گذاری این نسخه‌ها به گونه‌ای تنظیم شده است که هزینه‌های موثر برای کاربران کاهش یابد، در عین حال محافظت‌ها و اقدامات امنیتی به‌روز و جامع‌تری در آن‌ها تعبیه شده است. نسخه Mythos، که از همان مدل پایه بهره می‌برد، به شکل ویژه‌ای برای کنترل دسترسی‌های پیشرفته طراحی شده است. این قابلیت‌ها، به‌خصوص در کارهای حساس در زمینه امنیت سایبری و علوم زیستی، امکان دسترسی مطمئن و کنترل شده را فراهم می‌آورد. به این ترتیب، Mythos نه تنها قدرتمند است بلکه به کاربران اجازه می‌دهد تا در زمینه‌های حیاتی، با اعتماد کامل از امکانات آن بهره‌مند شوند. به طور کلی، این نسخه‌های جدید نشان‌دهنده تعهد انتروپیک به ارتقاء مداوم فناوری‌ها و تضمین امنیت و کارایی در استفاده‌های تخصصی هستند. ارائه امکانات پیشرفته در کنار قیمت مناسب و محافظت‌های کارآمد، این مدل‌ها را به گزینه‌ای برتر در حوزه هوش مصنوعی و فناوری‌های نوین تبدیل کرده است. #هوش_مصنوعی #امنیت_سایبری #پژوهش #فناوری 🟣لینک مقاله: https://www.anthropic.com/claude-fable-and-mythos-5-1?utm_source=tldrai ➖➖➖➖➖➖➖➖ 👑 @ai_Labdon
329
17
همکاران سیستم برگزار می‌کند: بوت‌کمپ برنامه‌نویسی Go ℹ️ آغاز دوره از ۲ مهرماه | ۴ جلسه ۴.۵ ساعته | ساعت ۸:۳۰ تا ۱۳ ‼️ در طی ۴
همکاران سیستم برگزار می‌کند: بوت‌کمپ برنامه‌نویسی Go ℹ️ آغاز دوره از ۲ مهرماه | ۴ جلسه ۴.۵ ساعته | ساعت ۸:۳۰ تا ۱۳ ‼️ در طی ۴ جلسه مباحث اصلی برنامه‌نویسی با زبان Go رو یاد میگیری و با انجام پروژه‌های کوچک به حل چالش‌ها و مسائل واقعی دنیای برنامه‌نویسی می‌پردازی. 🔺هزینه دوره: رایگان 📧 برای شرکت در این دوره کافیه رزومه‌ت رو برای ما ارسال کنی: Hr-Dev@systemgroup.net 🔷 سرفصل‌های بوت‌کمپ - Think in Go Familiarity with Go Program Structure, Data Types, Types, and Functions - Build with Go Methods، Interfaces، Abstraction, Packages - Go Beyond One Thread Goroutine، Channel، Shared State, Concurrency - Engineer with Confidence Development Tools, Testing, Project structure, and principles of writing reliable software ⌛ مهلت ارسال رزومه: سه‌شنبه ۳۱ شهریورماه ۱۴۰۵ 📍این دوره آموزشی به صورت حضوری در محل شرکت همکاران سیستم در شهر تهران برگزار می‌شه. لینکدین | اینستاگرام
359
18
🔵 عنوان مقاله gomodjail 2.0: An Experimental Jail for Go Modules 🟢 خلاصه مقاله: در جهان توسعه نرم‌افزار، مدیریت وابستگی‌ها یکی از چالش‌های مهم است. اخیراً، ابزار جدیدی با نام «گومودجیل ۲.۰» معرفی شده که روشی نوآورانه برای محدود کردن دسترسی‌های مربوط به ماژول‌های Go ارائه می‌دهد. این ابزار، بر پایه ایده‌ای آزمایشی ساخته شده است تا توسعه‌دهندگان بتوانند به صورت امن‌تر و کنترل‌شده‌تری وابستگی‌های پروژه‌های خود را مدیریت کنند. گومودجیل ۲.۰ توسط سازنده پروژه «لیما» توسعه یافته است و به عنوان یک سیستم نمونه‌سازی برای محدود کردن تعاملات ماژول‌های Go طراحی شده است. در این سیستم، توسعه‌دهندگان می‌توانند با استفاده از یک کامنت خاص در فایل go.mod، مشخص کنند که این ماژول تحت چه محدودیت‌هایی قرار دارد. سپس، ابزار gomodjail به طور خودکار بررسی می‌کند که آیا این ماژول توانایی دسترسی به فایل سیستم، شبکه، تنظیم سیستم کرنل و یا انجام فراخوانی‌های سیستمی خام را دارد یا خیر. در واقع، هدف از این پروژه آزمایشگاهی، ایجاد محیط‌هایی ایزوله و امن برای اجرای ماژول‌های Go است تا در صورت نیاز، دسترسی‌های خارجی محدود شده و امنیت پروژه افزایش یابد. این روش به توسعه‌دهندگان امکان می‌دهد تا وابستگی‌های خود را با کنترل دقیق‌تر مدیریت کنند و از بروز مشکلات امنیتی جلوگیری کنند. در نهایت، گومودجیل ۲.۰ نمونه‌ای است از تلاش‌های مداوم در جهت بهبود امنیت و کنترل در پروژه‌های متن‌باز Go، و نشان می‌دهد که آینده توسعه این زبان برنامه‌نویسی می‌تواند با ابزارهای پیشرفته‌تر و امن‌تر شکل گیرد. #گومودجیل #امنیت_در_برنامه‌نویسی #مدیریت_وابستگی #Go 🟣لینک مقاله: https://github.com/AkihiroSuda/gomodjail ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
342
19
🔵 عنوان مقاله go-oracledb: An Official Pure Go Driver for Oracle Database 🟢 خلاصه مقاله: در حال حاضر در مرحله آزمایشی است، اما دیدن یک کلاینت رسمی و مستقیم زبان گو از جانب اوراکل بسیار جالب توجه است. این خبر نشان می‌دهد که شرکت اوراکل به توسعه‌دهندگان فعال در حوزه زبان گو اهمیت می‌دهد و قصد دارد راه حلی رسمی و موثق برای اتصال به پایگاه داده اوراکل ارائه دهد. در حال حاضر، گزینه‌های موجود در بازار شامل «گو-ورا» است که کاملاً بر پایه زبان گو توسعه یافته و عملکرد قابل قبولی دارد، و «گو-درور» که از کتابخانه‌های کلاینت اوراکل و از طریق فناوری cgo استفاده می‌کند. این تازه‌وارد رسمی بر اساس نیازهای توسعه‌دهندگان ساخته شده و می‌تواند آینده‌ای روشن برای پروژه‌های مبتنی بر زبان گو با پایگاه داده اوراکل رقم بزند، به‌خصوص در زمانی که اعتماد به ابزارهای رسمی و پشتیبانی شده اهمیت فراوانی دارد. #اوراکل #پایگاه_داده #برنامه‌نویسی #گو 🟣لینک مقاله: https://github.com/oracle/go-oracledb ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
291
20
🔵 عنوان مقاله Could Go Build cgo Packages Without a C Compiler? 🟢 خلاصه مقاله: در فرآیند توسعه برنامه‌های گو، یکی از چالش‌های مهم، کامپایل کردن بسته‌های cgo است که نیازمند ابزارهای مربوط به زبان C است. در واقع، هنگام استفاده از قابلیت import "C" برای cross-compiling، توسعه‌دهندگان باید ابزارهای کامل زبان C را روی سیستم خود نصب و پیکربندی کنند، که این کار می‌تواند زمان‌بر و پیچیده باشد. این موضوع به ویژه در مواردی رخ می‌دهد که هدف تنها استفاده از کتابخانه‌های C از پیش‌ساخته شده است، و نیاز به توسعه مستقیم کدهای C در پروژه نیست. در این راستا، یک پیشنهاد جدید مطرح شده است که هدف آن ساده‌سازی این فرآیند است. بر اساس این ایده، بسته‌هایی که فقط به کتابخانه‌های C از پیش‌ساخته شده مراجعه می‌کنند، می‌توانند ساختار رابط خود را در فایل‌های گو مناسب و با علامت‌گذاری‌های خاص مشخص کنند. این کار به توسعه‌دهندگان اجازه می‌دهد بدون نیاز به نصب و پیکربندی یک ابزار کامل زبان C، بسته‌های مربوطه را در پروژه‌های خود استفاده و Build کنند. این راهکار به طور خاص برای پروژه‌هایی موثر است که تنها به رابط‌های C که قبلاً ساخته شده‌اند نیاز دارند و برنامه‌نویسان نمی‌خواهند وارد فرآیندهای پیچیده ساخت زبان C شوند. با این تصور، کار با بسته‌های cgo بسیار آسان‌تر و قابل‌ دسترس‌تر می‌شود، زیرا نیازی به نصب و تنظیم ابزارهای پیچیده نیست و تنها کافی است interfaceهای مورد نیاز مشخص و مستند شده باشند. این تغییر بهبود قابل توجهی در سهولت توسعه و انتشار پکیج‌های گو ایجاد می‌کند و امکان استفاده سریع‌تر و راحت‌تر از کتابخانه‌های C را فراهم می‌سازد. --- در نتیجه، این ابتکار می‌تواند توانایی ساخت بسته‌های cgo بدون نیاز به کامپایلر زبان C را فراهم کند و توسعه‌دهندگان بیشتری را ترغیب به استفاده از این فناوری کند، مخصوصاً در پروژه‌های چندپلتفرمی و محیط‌هایی که نصب ابزارهای توسعه در آنها دشوار است. #برنامه‌نویسی #گو #توسعه_پایگاه_کد #پیشرفت_تکنولوژی 🟣لینک مقاله: https://github.com/golang/go/issues/81450 ➖➖➖➖➖➖➖➖ 👑 @gopher_academy
272