چی هست fuzz testing؟
* در Go 1.18، fuzz testing بهصورت داخلی وارد stdlib شد**؛ ابزاری که بهطور خودکار ورودیهای تصادفی تولید کرده و تابع مورد نظر را تست میکند تا **Bugها و edge caseها را بیابد
* برخلاف تستهای واحد که ورودیهای مشخص دارند، fuzz با تکیه بر یک seed corpus (مثلاً تعدادی ورودی اولیه) شروع گرفته و بر اساس راهنمای پوشش کد تست را گسترش میدهد، مسیرهای جدید کد را کشف میکند و موارد جالبی تولید میکند که تستهای سنتی ممکن است پوشش ندهند
---
2. نحوه نوشتن fuzz test در Go
* تابع
*
*
---
3. مزایا و معایب
✅ مزایا:
* افزایش پوشش تست و کشف خطاهای نادیدهگرفتهشده: بهویژه برای parserها، handlers با JSON یا ورودی پیچیده
* سهولت استفاده: تست زیاد بدون نیاز به نوشتن دستی هزاران ورودی.
* هر بار موارد جالب کشفشده ذخیرهشده و قابل اجرای مجدد هستند
❌ معایب یا چالشها:
* نیاز به طراحی درست تابع تحت تست (مثلاً برگشت error برای ورودی نامعتبر مانند invalid UTF-8)
* زمانبر بودن تست: اجرای fuzz برای هزاران ورودی ممکن است زمان زیادی ببرد
* در مولفههای پیچیدهتر (مثلاً structهایی با فیلد private) ممکن است نیاز به ساخت custom generator باشد.
---
4. تجربه افراد و ابزارهای مکمل
* سیستمهایی مثل
* کتابخانههای property-based مانند
* جامعه توسعهدهندهها تجربههای بسیار مثبتی داشتهاند:
* در Go 1.18، fuzz testing بهصورت داخلی وارد stdlib شد**؛ ابزاری که بهطور خودکار ورودیهای تصادفی تولید کرده و تابع مورد نظر را تست میکند تا **Bugها و edge caseها را بیابد
* برخلاف تستهای واحد که ورودیهای مشخص دارند، fuzz با تکیه بر یک seed corpus (مثلاً تعدادی ورودی اولیه) شروع گرفته و بر اساس راهنمای پوشش کد تست را گسترش میدهد، مسیرهای جدید کد را کشف میکند و موارد جالبی تولید میکند که تستهای سنتی ممکن است پوشش ندهند
---
2. نحوه نوشتن fuzz test در Go
func FuzzReverse(f *testing.F) {
f.Add("abc") // seed اولیه
f.Add("bb")
f.Fuzz(func(t *testing.T, str string) {
rev1 := Reverse(str)
rev2 := Reverse(rev1)
if str != rev2 {
t.Errorf("fuzz test failed: %q became %q", str, rev1)
}
if utf8.ValidString(str) && !utf8.ValidString(rev1) {
t.Errorf("invalid utf-8 after reverse: %q", rev1)
}
})
}
* تابع
FuzzXXX
در فایل تست نوشته میشود؛*
f.Add(...)
ورودیهای اولیه را مشخص میکند (seed corpus)؛*
f.Fuzz(...)
تابع تست را با signature مشخص اجرا میکند و Go وظیفه دارد ورودیهای جدید را تولید و اجرا کند---
3. مزایا و معایب
✅ مزایا:
* افزایش پوشش تست و کشف خطاهای نادیدهگرفتهشده: بهویژه برای parserها، handlers با JSON یا ورودی پیچیده
* سهولت استفاده: تست زیاد بدون نیاز به نوشتن دستی هزاران ورودی.
* هر بار موارد جالب کشفشده ذخیرهشده و قابل اجرای مجدد هستند
❌ معایب یا چالشها:
* نیاز به طراحی درست تابع تحت تست (مثلاً برگشت error برای ورودی نامعتبر مانند invalid UTF-8)
* زمانبر بودن تست: اجرای fuzz برای هزاران ورودی ممکن است زمان زیادی ببرد
* در مولفههای پیچیدهتر (مثلاً structهایی با فیلد private) ممکن است نیاز به ساخت custom generator باشد.
---
4. تجربه افراد و ابزارهای مکمل
* سیستمهایی مثل
go-fuzz
(پیش از نسخه رسمی Go) برای fuzz کردن بستههای Go استفاده میشد و بسیار موثر بود* کتابخانههای property-based مانند
pgregory.net/rapid
گزینهی جایگزینی هستند که قابلیتهای پیشرفته توليد داده، مینیمالسازی خطاها و persistence را ارائه میدهند * جامعه توسعهدهندهها تجربههای بسیار مثبتی داشتهاند:
❤4
Forwarded from Software Engineer Labdon
🌟 ۵ استراتژی کلیدی برای دسترسی بالا (High Availability)
۱. 🍎 Load Balancing
توزیع هوشمند درخواستها به سرورهای مختلف با در نظر گرفتن معیارهایی مثل مصرف CPU، حافظه و زمان پاسخگویی. این کار از بارگذاری بیشازحد یک سرور جلوگیری کرده و تضمین دسترسی مناسب را فراهم میکند
۲. 🔁 Data Redundancy with Isolation
ایجاد نسخههای متعدد از دادهها در دیتاسنترها یا مناطق مختلف (AZ/Region) برای جلوگیری از توقف سرویس در صورت خرابی یک محل. تکنیکهایی مثل replication و توزیع داده استفاده میشود
۳. 🛠 Failover
راهاندازی خودکار سرویسهای پشتیبان (standby) که در صورت خرابی سرور اصلی، بدون وقفه بارکاری را ادامه دهند. این امکان از طریق load balancer، دیتابیس یا سرویسهای کاربردی قابل اجراست
۴. 📈 Auto Scaling
تنظیم خودکار مقیاس منابع در مواجهه با افزایش یا کاهش بار. منابع مانند VM، کانتینر یا فانکشن سرورلس به کلود یا سیستم مدیریت اختصاصی اضافه و حذف میشوند
۵. 🚦 Rate Limiting
اعمال محدودیت در تعداد درخواستهای دریافتی (مثلاً تعداد مشخص در هر ثانیه یا دقیقه) در لایههای مختلف مثل load balancer یا خود سرور. جلوگیری از overload سیستم و تضمین تجربه کاربری پایدار را ممکن میکند
---
🧭 چرا این روشها مهماند؟
* با ترکیب این استراتژیها میتونی سیستمت رو بهگونهای طراحی کنی که حتی در صورت خرابی یا حمله ناگهانی، ادامه بهکار دهد.
* هر مورد از این استراتژیها یک جنبهی خاص از پایداری مثل توزیع بار، حفاظت دادهها یا کنترل درخواست را پوشش میدهد.
* این اصول نمایانگر مفاهیمی مثل حذف Single Point of Failure، failover خودکار، کشش دینامیک و کنترل ترافیک هستند.
---
🧩 سایر رویکردها که ممکنه مفید باشن:
* Redundancy + Fault Tolerance: استفاده از سرورهای active-active یا active-passive در دادهسنترهای مختلف بههمراه clustering و heartbeat برای مانیتورینگ خودکار .
* Distributed Storage & Replication: برای پایداری داده و تحمل خرابی در نودهای جغرافیایی متعدد
* Monitoring, Health Checks, Graceful Degradation: پیادهسازی مانیتورینگ لحظهای، بررسی سلامت سرویس و ارائه fallback مناسب در شرایط بحرانی برای حفظ تجربه کاربری
---
✅ جمعبندی سریع
این پنج استراتژی (Load Balancing، Data Redundancy، Failover، Auto Scaling، Rate Limiting) پایهایترین اصول برای طراحی سیستمهای با High Availability هستند. با اجرای مناسب آنها میتونی سطح دسترسی بالا، مقاومت در برابر خطا و تجربهی بدون وقفهای برای کاربران فراهم کنی.
➖➖➖➖➖➖➖➖
https://t.iss.one/addlist/QtXiQlynEJwzODBk
۱. 🍎 Load Balancing
توزیع هوشمند درخواستها به سرورهای مختلف با در نظر گرفتن معیارهایی مثل مصرف CPU، حافظه و زمان پاسخگویی. این کار از بارگذاری بیشازحد یک سرور جلوگیری کرده و تضمین دسترسی مناسب را فراهم میکند
۲. 🔁 Data Redundancy with Isolation
ایجاد نسخههای متعدد از دادهها در دیتاسنترها یا مناطق مختلف (AZ/Region) برای جلوگیری از توقف سرویس در صورت خرابی یک محل. تکنیکهایی مثل replication و توزیع داده استفاده میشود
۳. 🛠 Failover
راهاندازی خودکار سرویسهای پشتیبان (standby) که در صورت خرابی سرور اصلی، بدون وقفه بارکاری را ادامه دهند. این امکان از طریق load balancer، دیتابیس یا سرویسهای کاربردی قابل اجراست
۴. 📈 Auto Scaling
تنظیم خودکار مقیاس منابع در مواجهه با افزایش یا کاهش بار. منابع مانند VM، کانتینر یا فانکشن سرورلس به کلود یا سیستم مدیریت اختصاصی اضافه و حذف میشوند
۵. 🚦 Rate Limiting
اعمال محدودیت در تعداد درخواستهای دریافتی (مثلاً تعداد مشخص در هر ثانیه یا دقیقه) در لایههای مختلف مثل load balancer یا خود سرور. جلوگیری از overload سیستم و تضمین تجربه کاربری پایدار را ممکن میکند
---
🧭 چرا این روشها مهماند؟
* با ترکیب این استراتژیها میتونی سیستمت رو بهگونهای طراحی کنی که حتی در صورت خرابی یا حمله ناگهانی، ادامه بهکار دهد.
* هر مورد از این استراتژیها یک جنبهی خاص از پایداری مثل توزیع بار، حفاظت دادهها یا کنترل درخواست را پوشش میدهد.
* این اصول نمایانگر مفاهیمی مثل حذف Single Point of Failure، failover خودکار، کشش دینامیک و کنترل ترافیک هستند.
---
🧩 سایر رویکردها که ممکنه مفید باشن:
* Redundancy + Fault Tolerance: استفاده از سرورهای active-active یا active-passive در دادهسنترهای مختلف بههمراه clustering و heartbeat برای مانیتورینگ خودکار .
* Distributed Storage & Replication: برای پایداری داده و تحمل خرابی در نودهای جغرافیایی متعدد
* Monitoring, Health Checks, Graceful Degradation: پیادهسازی مانیتورینگ لحظهای، بررسی سلامت سرویس و ارائه fallback مناسب در شرایط بحرانی برای حفظ تجربه کاربری
---
✅ جمعبندی سریع
این پنج استراتژی (Load Balancing، Data Redundancy، Failover، Auto Scaling، Rate Limiting) پایهایترین اصول برای طراحی سیستمهای با High Availability هستند. با اجرای مناسب آنها میتونی سطح دسترسی بالا، مقاومت در برابر خطا و تجربهی بدون وقفهای برای کاربران فراهم کنی.
➖➖➖➖➖➖➖➖
https://t.iss.one/addlist/QtXiQlynEJwzODBk
👍2❤1
🏗 مراحل کامپایل در زبان Go
کامپایلر Go شامل مراحل زیر هست:
1. Tokenizing (Lexical Analysis)
کد به اجزای کوچکتر مثل if, for, x, +, 123 تجزیه میشه.
این کار توسط lexer انجام میشه.
2. Parsing (Syntax Analysis)
از توکنها یک درخت نحوی یا AST (Abstract Syntax Tree) ساخته میشه.
مثلاً a + b به شکل درختی با + به عنوان ریشه و a و b به عنوان فرزندها تحلیل میشه.
3. Type Checking
بررسی میکنه که همه چیز از نظر نوع (type) درسته یا نه:
آیا a + b مجازه؟ (آیا a و b عدد هستن؟)
آیا تابعی با امضای درست فراخوانی شده؟
4. Intermediate Representation (IR)
کد به فرم میانی ترجمه میشه که خواندن و بهینهسازی روش راحتتره.
Go از فرم SSA (Static Single Assignment) استفاده میکنه (در مرحله بعد توضیح داده میشه).
5. SSA (Static Single Assignment)
در این مدل، هر متغیر فقط یکبار مقداردهی میشه.
این به کامپایلر کمک میکنه که راحتتر بهینهسازی انجام بده، مثلاً:
حذف کدهای مرده
inline کردن توابع
بهینهسازی حلقهها
6. Code Generation
در نهایت، از SSA کد ماشین تولید میشه (برای لینوکس/ویندوز/مک، معماری x86/ARM و…).
کامپایلر Go شامل مراحل زیر هست:
Source Code → Tokenizing → Parsing → AST → Type Checking → IR → SSA → Machine Code
1. Tokenizing (Lexical Analysis)
کد به اجزای کوچکتر مثل if, for, x, +, 123 تجزیه میشه.
این کار توسط lexer انجام میشه.
2. Parsing (Syntax Analysis)
از توکنها یک درخت نحوی یا AST (Abstract Syntax Tree) ساخته میشه.
مثلاً a + b به شکل درختی با + به عنوان ریشه و a و b به عنوان فرزندها تحلیل میشه.
3. Type Checking
بررسی میکنه که همه چیز از نظر نوع (type) درسته یا نه:
آیا a + b مجازه؟ (آیا a و b عدد هستن؟)
آیا تابعی با امضای درست فراخوانی شده؟
4. Intermediate Representation (IR)
کد به فرم میانی ترجمه میشه که خواندن و بهینهسازی روش راحتتره.
Go از فرم SSA (Static Single Assignment) استفاده میکنه (در مرحله بعد توضیح داده میشه).
5. SSA (Static Single Assignment)
در این مدل، هر متغیر فقط یکبار مقداردهی میشه.
این به کامپایلر کمک میکنه که راحتتر بهینهسازی انجام بده، مثلاً:
حذف کدهای مرده
inline کردن توابع
بهینهسازی حلقهها
6. Code Generation
در نهایت، از SSA کد ماشین تولید میشه (برای لینوکس/ویندوز/مک، معماری x86/ARM و…).
❤3👍2
Gopher Academy
🏗 مراحل کامپایل در زبان Go کامپایلر Go شامل مراحل زیر هست: Source Code → Tokenizing → Parsing → AST → Type Checking → IR → SSA → Machine Code 1. Tokenizing (Lexical Analysis) کد به اجزای کوچکتر مثل if, for, x, +, 123 تجزیه میشه. این کار توسط lexer انجام…
🌀 چرا Go سریع کامپایل میکنه؟
* کامپایلر Go فایلها رو به صورت مستقل کامپایل میکنه (no header files مثل C/C++)
* importها فقط به شکل explicit مجاز هستن (هیچ چیزی مخفیانه load نمیشه)
* فرم SSA بسیار بهینه و کمحجم هست
* استفاده از حافظهی کم در زمان build
---
🧪 مثال عملی (build داخلی Go)
اگر این کد رو ذخیره کنی:
و بعد دستور زیر رو بزنی:
میبینی که این مراحل اتفاق میافته:
---
🧰 ابزار مفید:
اگه بخوای دقیقتر رفتار کامپایلر رو ببینی:
1. فقط کامپایل کن بدون لینک:
این دستور خروجی اسمبلی (Assembly) کد رو نشون میده.
2. آنالیز باینری نهایی:
➖➖➖➖➖➖➖➖
https://t.iss.one/addlist/QtXiQlynEJwzODBk
* کامپایلر Go فایلها رو به صورت مستقل کامپایل میکنه (no header files مثل C/C++)
* importها فقط به شکل explicit مجاز هستن (هیچ چیزی مخفیانه load نمیشه)
* فرم SSA بسیار بهینه و کمحجم هست
* استفاده از حافظهی کم در زمان build
---
🧪 مثال عملی (build داخلی Go)
اگر این کد رو ذخیره کنی:
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
و بعد دستور زیر رو بزنی:
go build -x main.go
میبینی که این مراحل اتفاق میافته:
WORK=/tmp/go-build123456
mkdir -p $WORK/b001/
compile -> main.a
link -> main binary
---
🧰 ابزار مفید:
go tool compile
و go tool objdump
اگه بخوای دقیقتر رفتار کامپایلر رو ببینی:
1. فقط کامپایل کن بدون لینک:
go tool compile -S main.go
این دستور خروجی اسمبلی (Assembly) کد رو نشون میده.
2. آنالیز باینری نهایی:
go tool objdump ./main
➖➖➖➖➖➖➖➖
https://t.iss.one/addlist/QtXiQlynEJwzODBk
👍2🔥1🍾1
در طراحی کامپایلرها، Static Single Assignment (SSA) یک فرم نمایش میانی (Intermediate Representation یا IR) است که در آن هر متغیر تنها یکبار تعریف میشود. این روش برای بهینهسازی کد و سادهسازی تحلیلهایی مثل زنجیرههای استفاده-تعریف (use-define chains) استفاده میشود. کامپایلر گولنگ (مانند gc یا ابزارهای مرتبط با LLVM) ممکن است در مراحل بهینهسازی داخلی خود از مفاهیم مشابه SSA استفاده کند،
مثال ساده:
فرض کنید کدی مثل این دارید
در فرم SSA، متغیر x به نسخههای مختلفی (مثل x1 و x2) تقسیم میشود تا هر تخصیص یکتا باشد:
این نمایش به ابزارهای تحلیل کمک میکنه تا بتونن دقیقتر بررسی کنن که مقادیر متغیرها از کجا میان و کجا استفاده میشن.
مثال ساده:
فرض کنید کدی مثل این دارید
func main() {
x := 1
x = x + 2
fmt.Println(x)
}
در فرم SSA، متغیر x به نسخههای مختلفی (مثل x1 و x2) تقسیم میشود تا هر تخصیص یکتا باشد:
x1 := 1
x2 := x1 + 2
fmt.Println(x2)
این نمایش به ابزارهای تحلیل کمک میکنه تا بتونن دقیقتر بررسی کنن که مقادیر متغیرها از کجا میان و کجا استفاده میشن.
🔴 این کار باعث میشه ردیابی جریان دادهها (مثل اینکه یک متغیر کجا تعریف و کجا استفاده شده) سادهتر بشه. این روش بهخصوص برای ابزارهایی مثل بررسی باگها، بهینهسازی کد، یا تحلیل وابستگیها خیلی مفیده.
❤2👍2
🎯 تفاوت بین Heap و Stack به زبان ساده:
Stack:
- چیست؟
حافظهای با دسترسی سریع و مدیریت خودکار که برای ذخیره متغیرهای محلی و موقت (مثل متغیرهای داخل تابع) استفاده میشه.
- ویژگیها:
- تخصیص و آزادسازی حافظه به صورت LIFO (Last In, First Out) انجام میشه.
- اندازهاش معمولاً محدود و ثابت است.
- سریعتره چون مدیریتش سادهست.
- متغیرهای محلی (مثل
Heap:
- چیست؟
حافظهای پویا برای ذخیره دادههایی که عمر طولانیتری دارن یا اندازهشون در زمان اجرا مشخص میشه (مثل اشیاء یا آرایههای پویا).
- ویژگیها:
- تخصیص و آزادسازی حافظه به صورت دستی یا توسط Garbage Collector (در گولنگ به صورت خودکار).
- کندتر از Stack چون مدیریتش پیچیدهست.
- برای دادههای بزرگ یا اشتراکگذاری بین توابع استفاده میشه.
تفاوت کلیدی:
- سرعت: Stack سریعتره چون مدیریتش سادهست.
- مدیریت: Stack خودکار مدیریت میشه، اما Heap نیاز به Garbage Collector داره (در گولنگ).
- عمر داده: Stack برای دادههای موقت (محدوده تابع)، Heap برای دادههای با عمر طولانیتر.
- اندازه: Stack محدودتره، Heap بزرگتر و پویاست.
در گولنگ:
گولنگ با Escape Analysis تصمیم میگیره که یک متغیر در Stack یا Heap ذخیره بشه. مثلاً اگر متغیر از تابع خارج بشه (مثل برگرداندن اشارهگر)، به Heap میره.
Stack:
- چیست؟
حافظهای با دسترسی سریع و مدیریت خودکار که برای ذخیره متغیرهای محلی و موقت (مثل متغیرهای داخل تابع) استفاده میشه.
- ویژگیها:
- تخصیص و آزادسازی حافظه به صورت LIFO (Last In, First Out) انجام میشه.
- اندازهاش معمولاً محدود و ثابت است.
- سریعتره چون مدیریتش سادهست.
- متغیرهای محلی (مثل
int x = 5
) و ارجاعات تابع در Stack ذخیره میشن.Heap:
- چیست؟
حافظهای پویا برای ذخیره دادههایی که عمر طولانیتری دارن یا اندازهشون در زمان اجرا مشخص میشه (مثل اشیاء یا آرایههای پویا).
- ویژگیها:
- تخصیص و آزادسازی حافظه به صورت دستی یا توسط Garbage Collector (در گولنگ به صورت خودکار).
- کندتر از Stack چون مدیریتش پیچیدهست.
- برای دادههای بزرگ یا اشتراکگذاری بین توابع استفاده میشه.
تفاوت کلیدی:
- سرعت: Stack سریعتره چون مدیریتش سادهست.
- مدیریت: Stack خودکار مدیریت میشه، اما Heap نیاز به Garbage Collector داره (در گولنگ).
- عمر داده: Stack برای دادههای موقت (محدوده تابع)، Heap برای دادههای با عمر طولانیتر.
- اندازه: Stack محدودتره، Heap بزرگتر و پویاست.
در گولنگ:
گولنگ با Escape Analysis تصمیم میگیره که یک متغیر در Stack یا Heap ذخیره بشه. مثلاً اگر متغیر از تابع خارج بشه (مثل برگرداندن اشارهگر)، به Heap میره.
❤1👍1💯1🦄1
🛠 ابزارها در حوزه Linters و تحلیل کد Go
1. Actionlint
* وظیفه: بررسی استاتیک فایلهای workflow در GitHub Actions (.yml/.yaml در مسیر
* ویژگیها:
* بررسی نحوی و semantic expressions (
* اعتبارسنجی فراخوانی Actionها، ورودی/خروجی، نوع runners و امنیت اسکریپتها
* استفاده از ShellCheck و Pyflakes برای lint کردن inline scripts
* CLI + کتابخانه Go برای استفاده در ابزارهای CI/CD ([megalinter.io][1])
---
2. Hadolint
* وظیفه: lint کردن Dockerfile
* ویژگیها:
* نوشته شده با Haskell**؛ استفاده از AST برای تحلیل دستورات Docker
* ادغام با **ShellCheck برای بررسی اسکریپتهای bash داخل RUN
* امکان ignore قوانین، سفارشیسازی severity، trusted registries و خروجیهای متنوع (
* قابلیت اجرا به صورت binary، container تصویر Docker و ادغام در CI یا IDE ([megalinter.io][2])
---
3. deadcode
* وظیفه: شناسایی کدهای بلااستفاده (dead code) در برنامههای Go
* ویژگیها:
* استفاده از تحلیل Rapid Type Analysis (RTA) برای ساخت call graph از تابعهای reachable از
* شناسایی توابع و متدهایی که در جریان اجرا هرگز فراخوانی نمیشوند، حتی در ورودیهای تست
* گزینههای
* نصب از طریق
---
4. fieldalignment
* وظیفه: آنالیز alignment فیلدهای struct
* ویژگیها:
* بررسی شکل ساختار struct برای بهبود چینش فیلدها و کاهش حافظه مصرفشده
* موجود در پکیج
* نصب با
---
5. Protolint
* وظیفه: lint (و در برخی موارد fix) فایلهای
* ویژگیها:
* اجرا بدون نیاز به compiler اصلی (
* تولید گزارش برای قوانین style مانند نامگذاری، indentation، order imports، documentation، comment برای RPC و پیامها
* توانایی غیرفعالسازی قوانین در سطح فایل، استفاده از پلاگین برای قوانین سفارشی، و خروجیهای متنوع (
✅ کدومش برای پروژه شما کاربردیه؟
* CI پروژه با workflows عالیه → Actionlint
* ساختن Docker image استاندارد/امن → Hadolint
* حذف کدهای غیرضروری پس refactor → deadcode
* بهینهسازی حافظه باینری در structها → fieldalignment
* بررسی فایلهای protobuf و استانداردسازی API → Protolint
1. Actionlint
* وظیفه: بررسی استاتیک فایلهای workflow در GitHub Actions (.yml/.yaml در مسیر
.github/workflows/
)* ویژگیها:
* بررسی نحوی و semantic expressions (
${{ }}
)* اعتبارسنجی فراخوانی Actionها، ورودی/خروجی، نوع runners و امنیت اسکریپتها
* استفاده از ShellCheck و Pyflakes برای lint کردن inline scripts
* CLI + کتابخانه Go برای استفاده در ابزارهای CI/CD ([megalinter.io][1])
---
2. Hadolint
* وظیفه: lint کردن Dockerfile
* ویژگیها:
* نوشته شده با Haskell**؛ استفاده از AST برای تحلیل دستورات Docker
* ادغام با **ShellCheck برای بررسی اسکریپتهای bash داخل RUN
* امکان ignore قوانین، سفارشیسازی severity، trusted registries و خروجیهای متنوع (
json
, sarif
, checkstyle
)* قابلیت اجرا به صورت binary، container تصویر Docker و ادغام در CI یا IDE ([megalinter.io][2])
---
3. deadcode
* وظیفه: شناسایی کدهای بلااستفاده (dead code) در برنامههای Go
* ویژگیها:
* استفاده از تحلیل Rapid Type Analysis (RTA) برای ساخت call graph از تابعهای reachable از
main
* شناسایی توابع و متدهایی که در جریان اجرا هرگز فراخوانی نمیشوند، حتی در ورودیهای تست
* گزینههای
-test
, -filter
, -generated
برای کنترل نوع تحلیل و محدودسازی نتایج* نصب از طریق
go install ...@latest
([Google Groups][3], [Go][4], [Go Packages][5])---
4. fieldalignment
* وظیفه: آنالیز alignment فیلدهای struct
* ویژگیها:
* بررسی شکل ساختار struct برای بهبود چینش فیلدها و کاهش حافظه مصرفشده
* موجود در پکیج
go/analysis
و قابل اجرا بهصورت standalone یا در قالب Pass در تحلیلهای سفارشی* نصب با
go install golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment@latest
---
5. Protolint
* وظیفه: lint (و در برخی موارد fix) فایلهای
.proto
مطابق با استاندارد Google Protobuf* ویژگیها:
* اجرا بدون نیاز به compiler اصلی (
protoc
) و سبک اجرا* تولید گزارش برای قوانین style مانند نامگذاری، indentation، order imports، documentation، comment برای RPC و پیامها
* توانایی غیرفعالسازی قوانین در سطح فایل، استفاده از پلاگین برای قوانین سفارشی، و خروجیهای متنوع (
json
, junit
, sarif
)✅ کدومش برای پروژه شما کاربردیه؟
* CI پروژه با workflows عالیه → Actionlint
* ساختن Docker image استاندارد/امن → Hadolint
* حذف کدهای غیرضروری پس refactor → deadcode
* بهینهسازی حافظه باینری در structها → fieldalignment
* بررسی فایلهای protobuf و استانداردسازی API → Protolint
❤3👍1
Forwarded from Gopher Academy
🏆4✍1👨💻1
🔐 مفهوم Mutex در Go
ا
---
🧠 وضعیتهای مختلف Mutex
میتوان عملکرد آن را با وضعیتهای زیر توضیح داد:
ا
ا* Unlocked (حالت اولیه): Mutex آزاد است و هر goroutine میتواند با فراخوانی
ا* Locked: وقتی یک goroutine
ا* Waiting: در صورت تلاش همزمان چند goroutine برای گرفتن قفل، بقیه به صف انتظار اضافه میشوند.
ا* Starvation Mode: اگر یک goroutine بیش از \~۱ms نتواند قفل را بگیرد، سیستم وارد حالت گرسنگی (fair mode) شده و به ترتیب به goroutineهای قدیمیتر اجازه دسترسی میدهد ([CSDN Blog][3], [Zhihu Zhiwan][4]).
---
⚙️ عملکرد درونی Mutex
* از عملیات غیرقابل قطع (CAS) برای کنترل فیلد
* در شرایط کمرقابت ابتدا بهصورت spinning تلاش میکند تا حد ممکن بدون خوابیدن lock را بگیرد.
* در سطوح بالای رقابت، goroutineها به صف انتظار اضافه میشوند و بیدار میشوند وقتی قفل آزاد شد.
* حالت starvation زمانی فعال میشود که یک goroutine مدت طولانی در انتظار است تا از حالت FIFO استفاده شود
---
✅ نکات کاربردی و بهترین شیوهها
1. هیچ گاه Mutex را کپی نکنید؛ حتی تصادفاً**—مستقیماً باید از pointers استفاده شود
2. هیچگاه موضعی در struct آن را جاسازی (embed) نکنید، چون باعث در دسترسپذیری ناخواسته متدهای Lock/Unlock میشود
3. از
4. بخش قفلشده باید حداقل زمان ممکن طول بکشد؛ انجام عملیات بلندمدت در آن ممکن است باعث کاهش concurrency و تأخیر جدی شود.
---
⚠️ مشکلات رایج و اشتباهات متداول
* **کپی ناخواسته Mutex: حذف ایمنی synchronization و موجب رفتار نامشخص.
ا* embedding Mutex: باعث انتشار متدهای داخلی قفل به بیرون struct میشود — روش اشتباهی است
ا* Double Unlock یا Unlock بدون Lock قبلی → panic.
* عدم رعایت defer → ممکن است در صورت خطا یا exit، قفل آزاد نشود و deadlock رخ دهد.
ا* Deadlock ناشی از تداخل دو یا چند goroutine با mutexهای متفاوت و انتظار متقابل بر مبنای نظم اشتباهی بین
ا
sync.Mutex
یک اصل اساسی برای کنترل دسترسی امن به منابع مشترک بین goroutineها است. این نوع قفل تضمین میکند که در هر لحظه تنها یک goroutine به بخش حیاتی از کد (critical section) دسترسی دارد ---
🧠 وضعیتهای مختلف Mutex
میتوان عملکرد آن را با وضعیتهای زیر توضیح داد:
ا
ا* Unlocked (حالت اولیه): Mutex آزاد است و هر goroutine میتواند با فراخوانی
Lock()
آن را بگیرد.ا* Locked: وقتی یک goroutine
Lock()
میزند، دیگران باید منتظر بمانند.ا* Waiting: در صورت تلاش همزمان چند goroutine برای گرفتن قفل، بقیه به صف انتظار اضافه میشوند.
ا* Starvation Mode: اگر یک goroutine بیش از \~۱ms نتواند قفل را بگیرد، سیستم وارد حالت گرسنگی (fair mode) شده و به ترتیب به goroutineهای قدیمیتر اجازه دسترسی میدهد ([CSDN Blog][3], [Zhihu Zhiwan][4]).
---
⚙️ عملکرد درونی Mutex
* از عملیات غیرقابل قطع (CAS) برای کنترل فیلد
state
استفاده میشود.* در شرایط کمرقابت ابتدا بهصورت spinning تلاش میکند تا حد ممکن بدون خوابیدن lock را بگیرد.
* در سطوح بالای رقابت، goroutineها به صف انتظار اضافه میشوند و بیدار میشوند وقتی قفل آزاد شد.
* حالت starvation زمانی فعال میشود که یک goroutine مدت طولانی در انتظار است تا از حالت FIFO استفاده شود
---
✅ نکات کاربردی و بهترین شیوهها
1. هیچ گاه Mutex را کپی نکنید؛ حتی تصادفاً**—مستقیماً باید از pointers استفاده شود
2. هیچگاه موضعی در struct آن را جاسازی (embed) نکنید، چون باعث در دسترسپذیری ناخواسته متدهای Lock/Unlock میشود
3. از
defer m.Unlock()
برای اطمینان از آزادسازی قفل حتی در صورت panic یا return زودهنگام استفاده کنید 4. بخش قفلشده باید حداقل زمان ممکن طول بکشد؛ انجام عملیات بلندمدت در آن ممکن است باعث کاهش concurrency و تأخیر جدی شود.
---
⚠️ مشکلات رایج و اشتباهات متداول
* **کپی ناخواسته Mutex: حذف ایمنی synchronization و موجب رفتار نامشخص.
ا* embedding Mutex: باعث انتشار متدهای داخلی قفل به بیرون struct میشود — روش اشتباهی است
ا* Double Unlock یا Unlock بدون Lock قبلی → panic.
* عدم رعایت defer → ممکن است در صورت خطا یا exit، قفل آزاد نشود و deadlock رخ دهد.
ا* Deadlock ناشی از تداخل دو یا چند goroutine با mutexهای متفاوت و انتظار متقابل بر مبنای نظم اشتباهی بین
Lock()
ها.❤6👍1
مقالهی «Top 6 Golang Logging Best Practices» در HackerNoon توسط Lane Wagner در سال ۲۰۲۲ منتشر شده و به بررسی نکاتی اساسی ولی کاربردی دربارهی لاگنویسی در زبان Go پرداخته است. در ادامه، خلاصهای مختصر
---
## نکات کلیدی مقاله
1. استفاده از `error` بجای رشتهها (strings)
از نوع استاندارد
2. Wrap کردن خطاها
بجای لاگ فقط پیام خطا، آن را wrap کن تا محل دقیق رخداد خطا (stack trace یا خط کد) حفظ شود و دیباگ آسانتر شود.
3. استفاده از `fmt.Errorf()` برای قالببندی
4. قالبدهی structها (Format Structs)
وقتی structها در لاگها استفاده میشن، آنها را قالبمند کن تا خواناتر و مفیدتر باشند؛ مثلاً با فرمت:
5. استفاده از نسخه variadic توابع مانند `fmt.Println()`
ورژن variadic بهت اجازه میدهد مولفههای مختلف را بدون تلاش برای concatenation دستی به هم بچسبونی. خوانا و منعطفتره.
6. استفاده از بستهی استاندارد `log`
برای شروع خوبه، خصوصاً برای پروژههای ساده یا کوچک.
---
جمعبندی سریع
اینها اصولی هستند که در بسیاری از آموزشها و بحثهای Go توصیه میشن: استفاده از سیستم خطای داخلی، پیروی از استانداردها در wrap خطا، قالبدهی مناسب، و استفاده از امکانات داخلی زبان قبل از رفتن به راهحلهای پیچیدهتر.
---
توصیههای عملی
* لاگنویسی رو با استفاده از خطاهای داخلی Go شروع کن.
* ورودیها رو wrap کن؛ structها رو مرتب قالب بده.
* برای لاگهای پیشرفتهتر، از structured logging استفاده کن (مثل Zap یا Zerolog).
* همیشه context مهم رو مثل request ID در لاگها نگهدار.
* حجم لاگ رو کنترل کن: نه خیلی زیاد باشه که کارایی رو پایین بیاره، نه خیلی کم که مفید نباشه.
---
## نکات کلیدی مقاله
1. استفاده از `error` بجای رشتهها (strings)
از نوع استاندارد
error
برای نشان دادن خطاها استفاده کن تا از رفتارهای نادرست مانند نادیدهگرفتن خطا یا پراکندگی سازوکار خطا جلوگیری شود.2. Wrap کردن خطاها
بجای لاگ فقط پیام خطا، آن را wrap کن تا محل دقیق رخداد خطا (stack trace یا خط کد) حفظ شود و دیباگ آسانتر شود.
3. استفاده از `fmt.Errorf()` برای قالببندی
fmt.Errorf()
با قابلیت %w
به تو اجازه میدهد خطاها را قالببندی و wrap کنی:return fmt.Errorf("failed to open file: %w", err)
4. قالبدهی structها (Format Structs)
وقتی structها در لاگها استفاده میشن، آنها را قالبمند کن تا خواناتر و مفیدتر باشند؛ مثلاً با فرمت:
fmt.Printf("%+v", myStruct)
5. استفاده از نسخه variadic توابع مانند `fmt.Println()`
ورژن variadic بهت اجازه میدهد مولفههای مختلف را بدون تلاش برای concatenation دستی به هم بچسبونی. خوانا و منعطفتره.
6. استفاده از بستهی استاندارد `log`
برای شروع خوبه، خصوصاً برای پروژههای ساده یا کوچک.
log
پایدار و سبک هست و کافی برای کاربردهای ابتدایی است.---
جمعبندی سریع
اینها اصولی هستند که در بسیاری از آموزشها و بحثهای Go توصیه میشن: استفاده از سیستم خطای داخلی، پیروی از استانداردها در wrap خطا، قالبدهی مناسب، و استفاده از امکانات داخلی زبان قبل از رفتن به راهحلهای پیچیدهتر.
---
توصیههای عملی
* لاگنویسی رو با استفاده از خطاهای داخلی Go شروع کن.
* ورودیها رو wrap کن؛ structها رو مرتب قالب بده.
* برای لاگهای پیشرفتهتر، از structured logging استفاده کن (مثل Zap یا Zerolog).
* همیشه context مهم رو مثل request ID در لاگها نگهدار.
* حجم لاگ رو کنترل کن: نه خیلی زیاد باشه که کارایی رو پایین بیاره، نه خیلی کم که مفید نباشه.
🤝4👍1
📌 چرا به جای sync.Mutex از sync/atomic استفاده کنیم؟
سریعتره چون نیازی به قفل کردن نداره.
اما فقط برای عملیات ساده مثل افزایش/خواندن مقدار مناسبه.
برای عملیات پیچیدهتر، هنوز باید از sync.Mutex یا sync.RWMutex استفاده کنی.
سریعتره چون نیازی به قفل کردن نداره.
اما فقط برای عملیات ساده مثل افزایش/خواندن مقدار مناسبه.
برای عملیات پیچیدهتر، هنوز باید از sync.Mutex یا sync.RWMutex استفاده کنی.
❤2
Forwarded from DevOps Labdon
یکی از فوق العاده ترین ابزارهای مدیریت کلاستر kubernetes که هرروز باهاش کار میکنم و واقعا لذت میبرم k9s هست:
https://github.com/derailed/k9s
<Mohsen Khodabakhshi/>
https://github.com/derailed/k9s
<Mohsen Khodabakhshi/>
GitHub
GitHub - derailed/k9s: 🐶 Kubernetes CLI To Manage Your Clusters In Style!
🐶 Kubernetes CLI To Manage Your Clusters In Style! - derailed/k9s
❤6
Forwarded from Software Engineer Labdon
اگه یه چیزی مثل curl برای gRPC میخواین میتونین از این استفاده کنین:
https://github.com/fullstorydev/grpcurl
<بلک استیت />
https://github.com/fullstorydev/grpcurl
<بلک استیت />
GitHub
GitHub - fullstorydev/grpcurl: Like cURL, but for gRPC: Command-line tool for interacting with gRPC servers
Like cURL, but for gRPC: Command-line tool for interacting with gRPC servers - fullstorydev/grpcurl
🔥2🍾2❤1
💐امکانات جدید در GoLand 2025.2
۱. تحلیل جریان داده برای جلوگیری از nil dereference
اGoLand اکنون از تحلیل بینتابعی (interprocedural) استفاده میکند تا جریان دادههای nil را در حلقههای فراخوانی تابع، فایلها و بستهها دنبال کند. در نتیجه، هشدارهایی برای استفادههای ناایمن از اشارهگرها (dereference) به شکل مستقیم در ادیتور نمایش داده میشود. علاوه بر این، تب جدیدی به نام Data Flow Analysis در پنجره Problems اضافه شده که مسیر دقیق جریان nil را نشان میدهد.
۲. صفحه خوشآمدگویی غیرمسدودکننده (Non‑blocking Welcome screen)
صفحه خوشآمدگویی (Welcome Screen) حالا به صورت تب (tab) در IDE باز میشود، بدون آنکه اجرای محیط توسعه را متوقف کند. این امکان را دارید که بدون باز کردن پروژه به ترمینال، ابزار HTTP، Docker، Kubernetes یا پایگاهداده دسترسی داشته باشید و حتی فایلهای مستقل را ویرایش کنید.
۳. کشف هوشمندانهتر endpointها و تولید درخواست (Request) خودکار
ابزار Endpoints بهبود یافته تا الگوهای مدرن ServeMux را بهتر بشناسد؛ از جمله مسیرهای wildcard یا آنهایی که با HTTP method همراه هستند، مانند GET /task/{id}/.
علاوه بر این، متد HTTP در کنار هر endpoint نمایش داده شده، autocomplete برای ساخت آسانتر request فعال شده و پشتیبانی از فریمورکهایی مانند Chi, Gin, Gorilla نیز بهبود یافته است.
۴. اJunie؛ عامل هوشمند داخل IDE
عامل هوشمند Junie حالا سریعتر شده (حدود ۳۰٪ افزایش سرعت)، از پروتکل MCP (Model Context Protocol) پشتیبانی میکند و امکان کار در محیط Remote Development را فراهم میآورد—همه اینها در دل IDE برای تسهیل کارهای حرفهایتر.
۵. ارتقا در پشتیبانی از golangci-lint نسخه ۲
ادغام با golangci-lint بهبود یافته، به طوری که نسخهی جدید آن (v2) در تحلیل بلادرنگ (real-time) بهتر و مطمئنتر عملکرد دارد.
---
خلاصه کاربردی
ویژگی جدید کاربرد
تحلیل Nil با DFA جلوگیری از خطاهای اشارهگری قبل از runtime
صفحه خوشآمدگویی غیرمسدودکننده دسترسی سریعتر به ابزارها بدون باز کردن پروژه
کشف و Request خودکار endpointها تسهیل تعامل با HTTP در توسعه وب
اJunie با MCP و پشتیبانی Remote افزایش سرعت و قابلیت هوشمند برای توسعه حرفهای
ارتقاء golangci‑lint integration تحلیل کد دقیقتر و قابلاعتمادتر در زمان توسعه
---
در مجموع، نسخه 2025.2 تمرکزش را روی بهبود تجربه توسعهدهنده معطوف کرده—از تشخیص هوشمند خطا تا دسترسی سریع به ابزارها و هوشمندسازی کمکها در IDE.
۱. تحلیل جریان داده برای جلوگیری از nil dereference
اGoLand اکنون از تحلیل بینتابعی (interprocedural) استفاده میکند تا جریان دادههای nil را در حلقههای فراخوانی تابع، فایلها و بستهها دنبال کند. در نتیجه، هشدارهایی برای استفادههای ناایمن از اشارهگرها (dereference) به شکل مستقیم در ادیتور نمایش داده میشود. علاوه بر این، تب جدیدی به نام Data Flow Analysis در پنجره Problems اضافه شده که مسیر دقیق جریان nil را نشان میدهد.
۲. صفحه خوشآمدگویی غیرمسدودکننده (Non‑blocking Welcome screen)
صفحه خوشآمدگویی (Welcome Screen) حالا به صورت تب (tab) در IDE باز میشود، بدون آنکه اجرای محیط توسعه را متوقف کند. این امکان را دارید که بدون باز کردن پروژه به ترمینال، ابزار HTTP، Docker، Kubernetes یا پایگاهداده دسترسی داشته باشید و حتی فایلهای مستقل را ویرایش کنید.
۳. کشف هوشمندانهتر endpointها و تولید درخواست (Request) خودکار
ابزار Endpoints بهبود یافته تا الگوهای مدرن ServeMux را بهتر بشناسد؛ از جمله مسیرهای wildcard یا آنهایی که با HTTP method همراه هستند، مانند GET /task/{id}/.
علاوه بر این، متد HTTP در کنار هر endpoint نمایش داده شده، autocomplete برای ساخت آسانتر request فعال شده و پشتیبانی از فریمورکهایی مانند Chi, Gin, Gorilla نیز بهبود یافته است.
۴. اJunie؛ عامل هوشمند داخل IDE
عامل هوشمند Junie حالا سریعتر شده (حدود ۳۰٪ افزایش سرعت)، از پروتکل MCP (Model Context Protocol) پشتیبانی میکند و امکان کار در محیط Remote Development را فراهم میآورد—همه اینها در دل IDE برای تسهیل کارهای حرفهایتر.
۵. ارتقا در پشتیبانی از golangci-lint نسخه ۲
ادغام با golangci-lint بهبود یافته، به طوری که نسخهی جدید آن (v2) در تحلیل بلادرنگ (real-time) بهتر و مطمئنتر عملکرد دارد.
---
خلاصه کاربردی
ویژگی جدید کاربرد
تحلیل Nil با DFA جلوگیری از خطاهای اشارهگری قبل از runtime
صفحه خوشآمدگویی غیرمسدودکننده دسترسی سریعتر به ابزارها بدون باز کردن پروژه
کشف و Request خودکار endpointها تسهیل تعامل با HTTP در توسعه وب
اJunie با MCP و پشتیبانی Remote افزایش سرعت و قابلیت هوشمند برای توسعه حرفهای
ارتقاء golangci‑lint integration تحلیل کد دقیقتر و قابلاعتمادتر در زمان توسعه
---
در مجموع، نسخه 2025.2 تمرکزش را روی بهبود تجربه توسعهدهنده معطوف کرده—از تشخیص هوشمند خطا تا دسترسی سریع به ابزارها و هوشمندسازی کمکها در IDE.
🔥5❤1👍1
«به جای اینکه توی benchmark از
توضیح
در تستهای بنچمارک گولنگ (یعنی تابعهایی که با
ولی از نسخههای جدیدتر Go، متد [`b.Loop()`](https://pkg.go.dev/testing#B.Loop) اضافه شده که همین کار رو به شکل مدرن و کمی بهینهتر انجام میده و خوانایی رو هم بهتر میکنه:
فرق اصلی
* کد کوتاهتر و خواناتر
* جلوگیری از اشتباهات احتمالی در حلقه شمارشی
* خود Go در آینده ممکنه بهینهسازیهای بیشتری روی
مثال تبدیل
قدیم:
جدید:
پس پیغام `b.N can be modernized using b.Loop()` یعنی «لطفاً حلقه
for i := 0; i < b.N; i++ { ... }
استفاده کنی، میتونی از متد جدیدتر b.Loop()
استفاده کنی.»توضیح
در تستهای بنچمارک گولنگ (یعنی تابعهایی که با
func BenchmarkXxx(b *testing.B)
نوشته میشن)، معمولاً برای اجرای کد به تعداد کافی و گرفتن میانگین زمان اجرا، از این الگو استفاده میشه:for i := 0; i < b.N; i++ {
// کدی که باید بنچمارک بشه
}
ولی از نسخههای جدیدتر Go، متد [`b.Loop()`](https://pkg.go.dev/testing#B.Loop) اضافه شده که همین کار رو به شکل مدرن و کمی بهینهتر انجام میده و خوانایی رو هم بهتر میکنه:
b.Loop(func() {
// کدی که باید بنچمارک بشه
})
فرق اصلی
* کد کوتاهتر و خواناتر
* جلوگیری از اشتباهات احتمالی در حلقه شمارشی
* خود Go در آینده ممکنه بهینهسازیهای بیشتری روی
b.Loop
انجام بدهمثال تبدیل
قدیم:
func BenchmarkSomething(b *testing.B) {
for i := 0; i < b.N; i++ {
doWork()
}
}
جدید:
func BenchmarkSomething(b *testing.B) {
b.Loop(func() {
doWork()
})
}
پس پیغام `b.N can be modernized using b.Loop()` یعنی «لطفاً حلقه
for
رو به b.Loop
تغییر بده».🍓4👨💻1
دیدگاه جامعه درباره استفاده از Enum در Go
اهمیت خاص گذاشتن روی مقدار Invalid در صفر:
هشدار نسبت به وابستگی زیاد به iota وقتی این مقادیر در دیتابیس ذخیره میشن:
برخی هم در بحثهای Reddit اشاره کردهاند که enumهای واقعی مثل Rust’s sum types در Go وجود ندارند و هرچقدر هم شبیهسازی شوند، محدودیتهایی دارند.
اهمیت خاص گذاشتن روی مقدار Invalid در صفر:
“New go devs from Java tend to forget that the enum doesn’t default to null… defining 0 as unknown saves a lot of confusing bugs!”
هشدار نسبت به وابستگی زیاد به iota وقتی این مقادیر در دیتابیس ذخیره میشن:
“Reordering/removing cases also doesn't cause any big problem… unless you are using the number representation of enums in the database.”
برخی هم در بحثهای Reddit اشاره کردهاند که enumهای واقعی مثل Rust’s sum types در Go وجود ندارند و هرچقدر هم شبیهسازی شوند، محدودیتهایی دارند.
👌7
Forwarded from AI Labdon
تاجگذاری OpenAi در میدان شطرنج هوش مصنوعی ؛ ChatGPT گراک رو به زمین زد!
▪️در اولین دوره مسابقات شطرنج هوش مصنوعی در Kaggle Game Arena، مدل o3 از OpenAI با یک نمای قاطع 4 بر 0 مقابل Grok 4 (xAI) پیروز شد.
▪️مدل o3 با دقت 90.8% و بازیهای حسابشده، حریف رو به اشتباهات سخت کشوند؛ در حالی که Grok 4 با دقت 80.2% نتونست جلوی سقوط مهرهها رو بگیره.
▪️ردهبندی نهایی :
🥇 OpenAI - o3 (قهرمان)
🥈 xAI - Grok 4 (نایبقهرمان)
🥉 Gemini 2.5 Pro (مقام سوم)
▪️در اولین دوره مسابقات شطرنج هوش مصنوعی در Kaggle Game Arena، مدل o3 از OpenAI با یک نمای قاطع 4 بر 0 مقابل Grok 4 (xAI) پیروز شد.
▪️مدل o3 با دقت 90.8% و بازیهای حسابشده، حریف رو به اشتباهات سخت کشوند؛ در حالی که Grok 4 با دقت 80.2% نتونست جلوی سقوط مهرهها رو بگیره.
▪️ردهبندی نهایی :
🥇 OpenAI - o3 (قهرمان)
🥈 xAI - Grok 4 (نایبقهرمان)
🥉 Gemini 2.5 Pro (مقام سوم)
🏆3 1