🔵 عنوان مقاله
🕒 Coming in Go 1.24: An Experiment for Time and Concurrency Testing
🟢 خلاصه مقاله:
این مقاله به بررسی ویژگی جدیدی در نسخه 1.24 زبان برنامهنویسی Go میپردازد که اوایل سال آینده منتشر میشود. ویژگی مورد بحث، بسته آزمایشی testing/synctest است، که فرصتهای جدیدی برای آزمایش کدهایی که با زمان یا همزمانی سر و کار دارند را فراهم میآورد. بسته جدید قابلیتهایی را به توسعهدهندگان میدهد تا بتوانند با دقت بیشتری در مورد کنترل و محیط آزمایشی کدهای خود کار کنند. نویسنده مقاله اشاره میکند که او خود این بسته را در محل کار خود بر روی تستهای نامعلوم و مشکلدار بکار برده و تجربه موفقیتآمیزی داشته است. این گزارش نشان میدهد که testing/synctest به طور قابل توجهی بهبودی در آزمایش کدهایی که شامل مفاهیم زمان و همزمانی هستند، ارائه داده است.
🟣لینک مقاله:
https://golangweekly.com/link/163231/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
🕒 Coming in Go 1.24: An Experiment for Time and Concurrency Testing
🟢 خلاصه مقاله:
این مقاله به بررسی ویژگی جدیدی در نسخه 1.24 زبان برنامهنویسی Go میپردازد که اوایل سال آینده منتشر میشود. ویژگی مورد بحث، بسته آزمایشی testing/synctest است، که فرصتهای جدیدی برای آزمایش کدهایی که با زمان یا همزمانی سر و کار دارند را فراهم میآورد. بسته جدید قابلیتهایی را به توسعهدهندگان میدهد تا بتوانند با دقت بیشتری در مورد کنترل و محیط آزمایشی کدهای خود کار کنند. نویسنده مقاله اشاره میکند که او خود این بسته را در محل کار خود بر روی تستهای نامعلوم و مشکلدار بکار برده و تجربه موفقیتآمیزی داشته است. این گزارش نشان میدهد که testing/synctest به طور قابل توجهی بهبودی در آزمایش کدهایی که شامل مفاهیم زمان و همزمانی هستند، ارائه داده است.
🟣لینک مقاله:
https://golangweekly.com/link/163231/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
🍓2
🔵 عنوان مقاله
go-wasm-http-server 2.0: Embed Go HTTP Handlers in a Service Worker
🟢 خلاصه مقاله:
این مقاله به موضوع استفاده از WebAssembly برای تعبیه کنندگان درخواست HTTP گو (Go) در یک Service Worker در مرورگر میپردازد و نشان میدهد چگونه میتوان یک سرور HTTP را در سمت مرورگر شبیهسازی کرد. در این مقاله، نمونههای خاصی آورده شده است که میتوانند به عنوان الهام بخش برای توسعهدهندگانی باشند که به دنبال راه حلهای نوین در بهبود فعالیتهای وب خود هستند. استفاده از WebAssembly به کاربران اجازه میدهد تا عملکرد سرور-side را در مرورگر تقلید کنند، با این امکان، سرعت پردازش درخواستها و کاهش بار روی سرور مرکزی افزایش مییابد. در کل، این تکنیک میتواند پتانسیل بالایی در بهینهسازی عملیات وب و افزایش تجربه کاربری داشته باشد.
🟣لینک مقاله:
https://golangweekly.com/link/163247/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
go-wasm-http-server 2.0: Embed Go HTTP Handlers in a Service Worker
🟢 خلاصه مقاله:
این مقاله به موضوع استفاده از WebAssembly برای تعبیه کنندگان درخواست HTTP گو (Go) در یک Service Worker در مرورگر میپردازد و نشان میدهد چگونه میتوان یک سرور HTTP را در سمت مرورگر شبیهسازی کرد. در این مقاله، نمونههای خاصی آورده شده است که میتوانند به عنوان الهام بخش برای توسعهدهندگانی باشند که به دنبال راه حلهای نوین در بهبود فعالیتهای وب خود هستند. استفاده از WebAssembly به کاربران اجازه میدهد تا عملکرد سرور-side را در مرورگر تقلید کنند، با این امکان، سرعت پردازش درخواستها و کاهش بار روی سرور مرکزی افزایش مییابد. در کل، این تکنیک میتواند پتانسیل بالایی در بهینهسازی عملیات وب و افزایش تجربه کاربری داشته باشد.
🟣لینک مقاله:
https://golangweekly.com/link/163247/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
GitHub
GitHub - nlepage/go-wasm-http-server: Embed your Go HTTP handlers in a ServiceWorker and emulate an HTTP server!
Embed your Go HTTP handlers in a ServiceWorker and emulate an HTTP server! - nlepage/go-wasm-http-server
👍2
🔵 عنوان مقاله
Goverter: A Type-Safe Go Converter Generator
🟢 خلاصه مقاله:
در این مقاله به مهندسین نرمافزار راهکاری برای تولید مبدلهای نوع امن در برنامهنویسی ارائه شده است. با استفاده از کتابخانهای به نام Goverter، که در مخزن GitHub قابل دسترسی است، توسعهدهندگان میتوانند با نوشتن امضاهای تبدیل نوع داده، کد مورد نیاز برای انجام تبدیلها را به صورت خودکار تولید کنند. این امر باعث صرفهجویی در وقت و افزایش دقت و امنیت نوع داده در برنامههای نرمافزاری میشود. Goverter به واسطه خودکارسازی تولید کد، کاهش خطاهای مربوط به تبدیل نوع دادهها را تضمین میکند، به طوریکه توسعهدهندگان میتوانند بر اساس الگوهای مشخص شده در امضاها، به راحتی مبدلهای دقیق و امنی را پیادهسازی نمایند. این کتابخانه به شکل یک ابزار کاربردی در جامعه توسعهدهندگان قرار گرفته است تا استانداردهای برنامهنویسی را تحت تأثیر قرار دهد.
🟣لینک مقاله:
https://golangweekly.com/link/163249/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
Goverter: A Type-Safe Go Converter Generator
🟢 خلاصه مقاله:
در این مقاله به مهندسین نرمافزار راهکاری برای تولید مبدلهای نوع امن در برنامهنویسی ارائه شده است. با استفاده از کتابخانهای به نام Goverter، که در مخزن GitHub قابل دسترسی است، توسعهدهندگان میتوانند با نوشتن امضاهای تبدیل نوع داده، کد مورد نیاز برای انجام تبدیلها را به صورت خودکار تولید کنند. این امر باعث صرفهجویی در وقت و افزایش دقت و امنیت نوع داده در برنامههای نرمافزاری میشود. Goverter به واسطه خودکارسازی تولید کد، کاهش خطاهای مربوط به تبدیل نوع دادهها را تضمین میکند، به طوریکه توسعهدهندگان میتوانند بر اساس الگوهای مشخص شده در امضاها، به راحتی مبدلهای دقیق و امنی را پیادهسازی نمایند. این کتابخانه به شکل یک ابزار کاربردی در جامعه توسعهدهندگان قرار گرفته است تا استانداردهای برنامهنویسی را تحت تأثیر قرار دهد.
🟣لینک مقاله:
https://golangweekly.com/link/163249/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
👍2💘1
🔵 عنوان مقاله
Echo: Extensible, Minimalist Go Web Framework
🟢 خلاصه مقاله:
مقاله مورد بحث حول ویژگیها و بهروزرسانیهای اخیر در نسخه 4.13.0 فریمورک Echo برای توسعه وب میپردازد. Echo یک فریمورک وب سبک وزن است که به توسعهدهندگان امکان میدهد با امکاناتی نظیر مسیریابی HTTP، TLS خودکار، برخورد با دادهها، قالببندی، میدلورها و روشهای مختلف برای نمایش دادهها به راحتی برنامههای کاربردی وب را بنویسند. در آخرین نسخهاش، Echo تصمیم گرفته است میدلور JWT را به دلیل مشکلات امنیتی از هسته خود حذف کند. این تغییر به منظور افزایش امنیت کاربران و جلوگیری از آسیبپذیریهای احتمالی اعمال شده است. همچنین، اطلاعات مربوط به این تغییرات در مخزن GitHub موجود است که توسعهدهندگان میتوانند برای دیدن جزئیات بیشتر و دریافت آخرین کدها به آن مراجعه کنند.
🟣لینک مقاله:
https://golangweekly.com/link/163251/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
Echo: Extensible, Minimalist Go Web Framework
🟢 خلاصه مقاله:
مقاله مورد بحث حول ویژگیها و بهروزرسانیهای اخیر در نسخه 4.13.0 فریمورک Echo برای توسعه وب میپردازد. Echo یک فریمورک وب سبک وزن است که به توسعهدهندگان امکان میدهد با امکاناتی نظیر مسیریابی HTTP، TLS خودکار، برخورد با دادهها، قالببندی، میدلورها و روشهای مختلف برای نمایش دادهها به راحتی برنامههای کاربردی وب را بنویسند. در آخرین نسخهاش، Echo تصمیم گرفته است میدلور JWT را به دلیل مشکلات امنیتی از هسته خود حذف کند. این تغییر به منظور افزایش امنیت کاربران و جلوگیری از آسیبپذیریهای احتمالی اعمال شده است. همچنین، اطلاعات مربوط به این تغییرات در مخزن GitHub موجود است که توسعهدهندگان میتوانند برای دیدن جزئیات بیشتر و دریافت آخرین کدها به آن مراجعه کنند.
🟣لینک مقاله:
https://golangweekly.com/link/163251/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
Labstack
High performance, extensible, minimalist Go web framework | Echo
Echo is a high-performance web framework for building robust and scalable applications in Go.
With its minimalist design and powerful features, Echo enables developers to create efficient APIs and web
applications with ease. Harness the speed, flexibility…
With its minimalist design and powerful features, Echo enables developers to create efficient APIs and web
applications with ease. Harness the speed, flexibility…
👍2👻1
مقدار بهینه برای Semaphore (یعنی تعداد گوروتینهای همزمان) به عوامل مختلفی وابسته است، از جمله:
---
### 1. نوع سیستمعامل و سختافزار
- سیستمهای با تعداد هستههای بالا: میتوان تعداد گوروتینهای بیشتری را بهصورت همزمان اجرا کرد.
پیشنهاد: عددی بین 2 تا 4 برابر تعداد هستههای CPU.
- مثال: اگر CPU شما 8 هستهای است، مقدار
- سیستمهای کمقدرت یا سرورهای مجازی: مقدار پایینتر برای جلوگیری از استفاده بیش از حد از منابع.
پیشنهاد: 1 تا 2 برابر تعداد هستههای CPU.
- مثال: برای CPU 2 هستهای، مقدار
---
### 2. ماهیت وظایف گوروتینها
- وظایف محاسباتی سنگین (CPU-bound):
- اگر وظایف به شدت از CPU استفاده میکنند، مقدار
- دلیل: گوروتینهای زیاد منجر به رقابت برای منابع CPU میشوند و کارایی را کاهش میدهند.
- وظایف I/O سنگین (I/O-bound):
- اگر وظایف بیشتر منتظر I/O هستند (مانند درخواست به دیتابیس یا API)، میتوانید مقدار بزرگتری برای
- دلیل: در زمان انتظار برای I/O، CPU آزاد است و گوروتینهای بیشتری میتوانند اجرا شوند.
---
### 3. پیکربندی سرور و حافظه
- سیستمهایی با حافظه محدود: تعداد زیاد گوروتینها میتواند حافظه را به سرعت پر کند. در این موارد مقدار کمتری انتخاب کنید.
- پیشنهاد: برای هر گوروتین حدود 4-8 کیلوبایت حافظه در نظر بگیرید و مقدار
---
### 4. محیط تولیدی (Production) در مقابل آزمایشی (Development)
- محیط آزمایشی (Development):
- مقدار کمتر برای تسهیل اشکالزدایی.
- پیشنهاد: مقدار
- محیط تولیدی (Production):
- مقدار بهینهتر بر اساس تحلیل بار واقعی.
- پیشنهاد: با اندازهگیری و مانیتورینگ منابع، مقدار مناسب را پیدا کنید.
---
### 5. تنظیم پویا بر اساس تعداد هستههای CPU
میتوانید مقدار
---
### توصیه نهایی:
1. برای **وظایف محاسباتی**، مقدار
2. برای **وظایف I/O**، مقدار را بزرگتر تنظیم کنید (مثلاً 4 برابر تعداد هستهها).
3. مقدار را در محیط تولید با مانیتورینگ منابع (مانند CPU و حافظه) بهینه کنید.
➖➖➖➖➖➖➖➖
👑 @gopher_academy
---
### 1. نوع سیستمعامل و سختافزار
- سیستمهای با تعداد هستههای بالا: میتوان تعداد گوروتینهای بیشتری را بهصورت همزمان اجرا کرد.
پیشنهاد: عددی بین 2 تا 4 برابر تعداد هستههای CPU.
- مثال: اگر CPU شما 8 هستهای است، مقدار
20-30
مناسب است.- سیستمهای کمقدرت یا سرورهای مجازی: مقدار پایینتر برای جلوگیری از استفاده بیش از حد از منابع.
پیشنهاد: 1 تا 2 برابر تعداد هستههای CPU.
- مثال: برای CPU 2 هستهای، مقدار
5-10
مناسب است.---
### 2. ماهیت وظایف گوروتینها
- وظایف محاسباتی سنگین (CPU-bound):
- اگر وظایف به شدت از CPU استفاده میکنند، مقدار
semaphore
باید برابر یا کمی بیشتر از تعداد هستههای CPU باشد.- دلیل: گوروتینهای زیاد منجر به رقابت برای منابع CPU میشوند و کارایی را کاهش میدهند.
- وظایف I/O سنگین (I/O-bound):
- اگر وظایف بیشتر منتظر I/O هستند (مانند درخواست به دیتابیس یا API)، میتوانید مقدار بزرگتری برای
semaphore
انتخاب کنید (مثلاً 50 یا بیشتر).- دلیل: در زمان انتظار برای I/O، CPU آزاد است و گوروتینهای بیشتری میتوانند اجرا شوند.
---
### 3. پیکربندی سرور و حافظه
- سیستمهایی با حافظه محدود: تعداد زیاد گوروتینها میتواند حافظه را به سرعت پر کند. در این موارد مقدار کمتری انتخاب کنید.
- پیشنهاد: برای هر گوروتین حدود 4-8 کیلوبایت حافظه در نظر بگیرید و مقدار
semaphore
را متناسب با محدودیت حافظه تنظیم کنید.---
### 4. محیط تولیدی (Production) در مقابل آزمایشی (Development)
- محیط آزمایشی (Development):
- مقدار کمتر برای تسهیل اشکالزدایی.
- پیشنهاد: مقدار
5-10
.- محیط تولیدی (Production):
- مقدار بهینهتر بر اساس تحلیل بار واقعی.
- پیشنهاد: با اندازهگیری و مانیتورینگ منابع، مقدار مناسب را پیدا کنید.
---
### 5. تنظیم پویا بر اساس تعداد هستههای CPU
میتوانید مقدار
semaphore
را بهطور خودکار بر اساس تعداد هستههای CPU تنظیم کنید:import "runtime"
numCPU := runtime.NumCPU()
semaphore := make(chan struct{}, numCPU*2) // 2 برابر تعداد هستهها
---
### توصیه نهایی:
1. برای **وظایف محاسباتی**، مقدار
semaphore
را برابر با تعداد هستههای CPU تنظیم کنید.2. برای **وظایف I/O**، مقدار را بزرگتر تنظیم کنید (مثلاً 4 برابر تعداد هستهها).
3. مقدار را در محیط تولید با مانیتورینگ منابع (مانند CPU و حافظه) بهینه کنید.
➖➖➖➖➖➖➖➖
👑 @gopher_academy
👍3🔥2🤩1
This media is not supported in your browser
VIEW IN TELEGRAM
❤شب چله بر شما خجسته باد❤
❤10👨💻3🔥2👏1🐳1🍾1💅1
version: 2
updates:
- package-ecosystem: ""
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
——————
این فایل YAML ارائهشده مربوط به Dependabot است، ابزاری که برای مدیریت وابستگیهای پروژه در GitHub استفاده میشود. این ابزار به صورت خودکار وابستگیهای پروژه را بررسی و نسخههای جدیدتر را پیشنهاد میدهد یا بهروزرسانی میکند.
---
### ساختار Dependabot
1. `version: 2`:
- نسخه تنظیمات Dependabot را مشخص میکند. در حال حاضر، نسخه 2 جدیدترین نسخه است.
2. `updates`:
- لیستی از تنظیمات برای مدیریت بهروزرسانی وابستگیها است.
---
### اجزای اصلی تنظیمات
#### 1. `package-ecosystem`:
- نوع سیستم مدیریت بستههای پروژه شما را مشخص میکند.
- برخی از مقادیر متداول:
-
npm
برای پروژههای جاوااسکریپت.-
pip
برای پروژههای پایتون.-
gomod
برای پروژههای Go.-
docker
برای بهروزرسانی تصاویر Docker.- در فایل شما مقدار آن خالی است و باید مقدار مناسب مشخص شود.
#### 2. `directory`:
- مسیر پوشهای که فایلهای وابستگی در آن قرار دارند.
-
/
به این معنی است که Dependabot باید فایلها را از ریشه پروژه بررسی کند.#### 3. `schedule`:
- زمانبندی اجرای بهروزرسانیها را مشخص میکند.
- `interval`:
- دوره اجرای بهروزرسانیها:
-
daily
: بهروزرسانیهای روزانه.-
weekly
: بهروزرسانیهای هفتگی.-
monthly
: بهروزرسانیهای ماهانه.---
### نمونه تنظیم Dependabot برای پروژه Go
اگر پروژه شما از Go Modules استفاده میکند، تنظیمات ممکن است به شکل زیر باشد:
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
- `package-ecosystem: "gomod"`: مشخص میکند که Dependabot باید فایل
go.mod
را بررسی کند.- `directory: "/"`: فایل
go.mod
در ریشه پروژه است.- `interval: "weekly"`: بهروزرسانیها هر هفته اجرا میشوند.
---
### مزایای استفاده از Dependabot
1. امنیت بهتر:
- Dependabot مشکلات امنیتی شناختهشده در وابستگیها را شناسایی و رفع میکند.
2. بهروزرسانی خودکار:
- وابستگیها را به آخرین نسخهها ارتقا میدهد.
3. کاهش بار کاری:
- دیگر نیازی نیست به صورت دستی وابستگیها را بررسی و بهروزرسانی کنید.
---
➖➖➖➖➖➖➖➖
👑 @gopher_academy
👍3👏1🙏1
Forwarded from Bardia & Erfan
واقعا برنامه نویس بودن تو ایران ،یه مسیر شغلی کاملا مسخره است.
یوتیوب فیلتره ، سایت های آموزشی تحریم هستیم. پرداخت ارزی به سختی اتفاق میوفته و غیره.
در هر صورت خواستم بگم Github Copilot
به صورت رایگان در دسترس هست. اما تحریم هستیم.
https://aka.ms/vscode-activatecopilotfree
https://code.visualstudio.com/docs/copilot/setup-simplified
<پوریای اصلی قدیمی/>
➖➖➖➖➖➖➖➖
🕸 @labdon_academy
یوتیوب فیلتره ، سایت های آموزشی تحریم هستیم. پرداخت ارزی به سختی اتفاق میوفته و غیره.
در هر صورت خواستم بگم Github Copilot
به صورت رایگان در دسترس هست. اما تحریم هستیم.
https://aka.ms/vscode-activatecopilotfree
https://code.visualstudio.com/docs/copilot/setup-simplified
<پوریای اصلی قدیمی/>
➖➖➖➖➖➖➖➖
🕸 @labdon_academy
👻9👍6🤝2❤1💘1
Forwarded from Software Engineer Labdon
توی این مقاله اومده یه سری دلیل گفته که چرا مدیران ارشد شما را جدی نمی گیرند!!!🤔😅🚬
🔻 https://zaidesanton.substack.com/p/6-reasons-why-the-senior-leadership
➖➖➖➖➖➖➖➖
🕸 https://linktr.ee/Labdon
🔻 https://zaidesanton.substack.com/p/6-reasons-why-the-senior-leadership
➖➖➖➖➖➖➖➖
🕸 https://linktr.ee/Labdon
👍5
Forwarded from Bardia & Erfan
🥰1
اگر با زبان Go کار میکنید
بهتون اکستنشن Error Lens رو پیشنهاد میکنم
در همون لحظه و محیط کد به شما ارور های احتمالی رو میده
<Misagh Momeni Bashuqeh/>
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
بهتون اکستنشن Error Lens رو پیشنهاد میکنم
در همون لحظه و محیط کد به شما ارور های احتمالی رو میده
<Misagh Momeni Bashuqeh/>
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
👍7❤1🍾1
Forwarded from Software Engineer Labdon
🍾یه سری رودمپ بدرد بخور براتون ردیف کردم
🔻Engineering Manager
https://roadmap.sh/engineering-manager
🔻Software Design and Architecture
https://roadmap.sh/software-design-architecture
🔻System Design
https://roadmap.sh/system-design
🔻Software Architect
https://roadmap.sh/software-architect
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
🔻Engineering Manager
https://roadmap.sh/engineering-manager
🔻Software Design and Architecture
https://roadmap.sh/software-design-architecture
🔻System Design
https://roadmap.sh/system-design
🔻Software Architect
https://roadmap.sh/software-architect
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
🙏4❤1👍1🍾1
Forwarded from Software Engineer Labdon
📣 هش SHA 256 چگونه کار میکند؟
این وبسایت قدم به قدم فرآیند هش کردن رشته با الگوریتم Sha256 را بصورت گرافیکی نشان میدهد:
🔗 https://sha256algorithm.com/
🔹🔹🔹🔹🔹
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
این وبسایت قدم به قدم فرآیند هش کردن رشته با الگوریتم Sha256 را بصورت گرافیکی نشان میدهد:
🔗 https://sha256algorithm.com/
🔹🔹🔹🔹🔹
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
❤1🔥1👏1
اگه یه میلیون کار داشته باشی و بخوای همزمان اجراشون کنی، ولی فقط 8 تا CPU داری، چهجوری بهینهترین حالت رو پیدا میکنی؟
تو گولنگ، گوروتینها خیلی سبک هستن. میتونی هزار تا، ده هزار تا، یا حتی بیشتر گوروتین همزمان اجرا کنی. ولی وقتی تعداد کارهات خیلی زیاده (مثلاً یه میلیون)، دیگه تعداد CPUها محدودیت اصلی میشه و نمیصرفه حافظه رو با صدها هزار گوروتین که همزمان نمیتونن اجرا بشن، هدر بدی.
یه راه خفن برای کنترل این داستان استفاده از Semaphore هست که میتونی تعداد گوروتینهای در حال اجرا رو محدود کنی.
حالا چطور کار میکنه؟
1. یه کانال با ظرفیت مشخص (N) درست میکنی که این ظرفیت میشه تعداد گوروتینهای همزمانی که میخوای اجرا بشه.
2. کانال رو با N تا "توکن" (هرچیزی مثل عدد) پر میکنی.
3. هر گوروتین قبل از اجرا باید یه توکن از کانال بگیره و وقتی کارش تموم شد توکن رو برمیگردونه.
4. اگه توکن نباشه گوروتین منتظر میمونه تا یکی آزاد بشه.
این تصویر یه مثال ساده با N=2 هست.
| <Mohammad Abdorrahmani/>
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
تو گولنگ، گوروتینها خیلی سبک هستن. میتونی هزار تا، ده هزار تا، یا حتی بیشتر گوروتین همزمان اجرا کنی. ولی وقتی تعداد کارهات خیلی زیاده (مثلاً یه میلیون)، دیگه تعداد CPUها محدودیت اصلی میشه و نمیصرفه حافظه رو با صدها هزار گوروتین که همزمان نمیتونن اجرا بشن، هدر بدی.
یه راه خفن برای کنترل این داستان استفاده از Semaphore هست که میتونی تعداد گوروتینهای در حال اجرا رو محدود کنی.
حالا چطور کار میکنه؟
1. یه کانال با ظرفیت مشخص (N) درست میکنی که این ظرفیت میشه تعداد گوروتینهای همزمانی که میخوای اجرا بشه.
2. کانال رو با N تا "توکن" (هرچیزی مثل عدد) پر میکنی.
3. هر گوروتین قبل از اجرا باید یه توکن از کانال بگیره و وقتی کارش تموم شد توکن رو برمیگردونه.
4. اگه توکن نباشه گوروتین منتظر میمونه تا یکی آزاد بشه.
این تصویر یه مثال ساده با N=2 هست.
| <Mohammad Abdorrahmani/>
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
👍11🍾4🔥1💅1
رفتار متغیرهای حلقه در Go
در Go، وقتی یک حلقه مانند
مثال مشکلساز:
فرض کنید کدی شبیه به زیر داریم:
مشکل چیست؟
1. متغیر
2. goroutineها به دلیل اجرای همزمان (asynchronous execution) ممکن است با تأخیر اجرا شوند.
3. زمانی که goroutine اجرا میشود، ممکن است مقدار
نتیجه
تمام goroutineها ممکن است به جای مقادیر مختلف، فقط مقدار آخرین آیتم حلقه را چاپ کنند.
---
راهحل: ایجاد کپی مستقل از متغیر حلقه
برای جلوگیری از این مشکل، باید مطمئن شویم که هر goroutine به یک کپی مستقل از مقدار
اصلاح کد:
تابع ناشناس با پارامتر
یک روش دیگر برای ایجاد کپی، ارسال مقدار متغیر حلقه به تابع ناشناس به صورت پارامتر است.
کد شما:
1. `m` به عنوان آرگومان: متغیر
2. کپی مستقل: حالا تابع ناشناس داخل goroutine به یک کپی مجزا و مستقل از مقدار متغیر
3. مشکل حل میشود: هر goroutine مقدار درست متغیر مربوط به تکرار خودش را پردازش میکند.
---
چرا این کار به جلوگیری از مشکلات همزمانی کمک میکند؟
مشکلات همزمانی زمانی رخ میدهند که چندین goroutine به صورت همزمان به یک منبع مشترک دسترسی داشته باشند.
در اینجا:
- اگر از متغیر حلقه
- با ایجاد کپی (از طریق
- این جداسازی تضمین میکند که مقدار هر goroutine به حلقه وابسته نیست و دیگر دچار تداخل نخواهد شد.
---
مثال عملی
قبل از اصلاح:
#### بعد از اصلاح:
---
جمعبندی
خط
1. یک کپی مستقل از مقدار
2. این کپی را به تابع ناشناس ارسال میکند.
3. به جلوگیری از مشکلات ناشی از استفاده همزمان از متغیرهای حلقه در goroutineها کمک میکند.
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
در Go، وقتی یک حلقه مانند
for
تعریف میشود، متغیرهای حلقه (result
در این مثال) به صورت متغیر مشترک (shared) در حافظه استفاده میشوند. این بدان معناست که همه goroutineها به یک مرجع (reference) از این متغیر دسترسی دارند، نه به یک کپی از مقدار فعلی آن.مثال مشکلساز:
فرض کنید کدی شبیه به زیر داریم:
for _, result := range collections {
go func() {
fmt.Println(result.Title) // از result استفاده میشود
}()
}
مشکل چیست؟
1. متغیر
result
به طور مداوم در طول حلقه تغییر میکند.2. goroutineها به دلیل اجرای همزمان (asynchronous execution) ممکن است با تأخیر اجرا شوند.
3. زمانی که goroutine اجرا میشود، ممکن است مقدار
result
تغییر کرده باشد و goroutine به مقدار آخرین تغییر یافته دسترسی داشته باشد، نه مقداری که هنگام تعریف goroutine موجود بود.نتیجه
تمام goroutineها ممکن است به جای مقادیر مختلف، فقط مقدار آخرین آیتم حلقه را چاپ کنند.
---
راهحل: ایجاد کپی مستقل از متغیر حلقه
برای جلوگیری از این مشکل، باید مطمئن شویم که هر goroutine به یک کپی مستقل از مقدار
result
دسترسی دارد. این کار را با تعریف یک متغیر محلی جدید در هر تکرار حلقه انجام میدهیم.اصلاح کد:
for _, result := range collections {
m := result // یک کپی از `result` ایجاد میکنیم
go func() {
fmt.Println(m.Title) // حالا goroutine به کپی مستقل دسترسی دارد
}()
}
تابع ناشناس با پارامتر
یک روش دیگر برای ایجاد کپی، ارسال مقدار متغیر حلقه به تابع ناشناس به صورت پارامتر است.
کد شما:
go func(m articleapp.NewArticle) {
// کد داخل goroutine
}(m)
1. `m` به عنوان آرگومان: متغیر
result
کپی شده و به عنوان پارامتر m
به تابع ناشناس ارسال میشود.2. کپی مستقل: حالا تابع ناشناس داخل goroutine به یک کپی مجزا و مستقل از مقدار متغیر
result
دسترسی دارد.3. مشکل حل میشود: هر goroutine مقدار درست متغیر مربوط به تکرار خودش را پردازش میکند.
---
چرا این کار به جلوگیری از مشکلات همزمانی کمک میکند؟
مشکلات همزمانی زمانی رخ میدهند که چندین goroutine به صورت همزمان به یک منبع مشترک دسترسی داشته باشند.
در اینجا:
- اگر از متغیر حلقه
result
مستقیماً استفاده شود، goroutineها به یک مرجع مشترک از این متغیر دسترسی دارند.- با ایجاد کپی (از طریق
m
) و ارسال آن به تابع ناشناس، هر goroutine یک نسخه مستقل از مقدار را دارد.- این جداسازی تضمین میکند که مقدار هر goroutine به حلقه وابسته نیست و دیگر دچار تداخل نخواهد شد.
---
مثال عملی
قبل از اصلاح:
collections := []articleapp.NewArticle{
{Title: "A"}, {Title: "B"}, {Title: "C"},
}
for _, result := range collections {
go func() {
fmt.Println(result.Title) // ممکن است همه goroutineها مقدار "C" را چاپ کنند
}()
}
#### بعد از اصلاح:
for _, result := range collections {
go func(m articleapp.NewArticle) {
fmt.Println(m.Title) // هر goroutine مقدار درست را چاپ میکند
}(result)
}
---
جمعبندی
خط
(m)
:1. یک کپی مستقل از مقدار
result
ایجاد میکند.2. این کپی را به تابع ناشناس ارسال میکند.
3. به جلوگیری از مشکلات ناشی از استفاده همزمان از متغیرهای حلقه در goroutineها کمک میکند.
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
👍7
در فایل go.mod، toolchain برای تعیین نسخه ابزار Go (مانند go و ابزارهای مرتبط با آن) استفاده میشود. این ویژگی به شما امکان میدهد تا پروژه را به نسخه خاصی از ابزار Go مقید کنید، حتی اگر نسخه پیشفرض go در سیستم شما متفاوت باشد.
نحوه استفاده از toolchain
اگر در فایل go.mod خطی به شکل زیر مشاهده کنید:
این به این معنی است که پروژه نیازمند نسخه go1.20 است و باید از این نسخه استفاده شود، صرفنظر از نسخه Go نصبشده روی سیستم.
کاربردهای اصلی toolchain
اطمینان از سازگاری نسخه Go
با استفاده از toolchain، میتوانید مطمئن شوید که همه توسعهدهندگان و محیطهای CI/CD از یک نسخه خاص از ابزار Go استفاده میکنند.
مدیریت نسخهها در پروژههای تیمی
این ویژگی تضمین میکند که مشکلات ناشی از ناسازگاری نسخهها (مانند تغییرات در syntax یا behavior) به حداقل برسند.
ساخت خودکار با نسخه مشخص
اگر نسخهای که در toolchain تعریف شده، روی سیستم نصب نشده باشد، ابزار Go بهطور خودکار آن را از وبسایت Go دریافت و نصب میکند.
نکته مهم درباره toolchain
این قابلیت با ابزار Go نسخه 1.21 و بالاتر در دسترس است. اگر نسخه Go قدیمیتری دارید، خط مربوط به toolchain در فایل go.mod نادیده گرفته خواهد شد.
toolchain مستقل از دستور go در فایل go.mod عمل میکند. دستور go نسخه حداقل زبان Go برای کدنویسی و بیلد کردن را مشخص میکند:
مثالی کامل از go.mod
go 1.20: نسخه حداقل برای ویژگیهای زبان Go.
toolchain go1.20: نسخه ابزار Go که پروژه باید با آن ساخته شود.
جمعبندی
toolchain یک ابزار قوی برای مدیریت و تثبیت نسخه ابزار Go در پروژههای بزرگ است. این قابلیت بهخصوص در محیطهای توسعه تیمی و پروژههایی که وابستگی شدیدی به نسخه خاصی از Go دارند، بسیار مفید است.
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
نحوه استفاده از toolchain
اگر در فایل go.mod خطی به شکل زیر مشاهده کنید:
toolchain go1.20
این به این معنی است که پروژه نیازمند نسخه go1.20 است و باید از این نسخه استفاده شود، صرفنظر از نسخه Go نصبشده روی سیستم.
کاربردهای اصلی toolchain
اطمینان از سازگاری نسخه Go
با استفاده از toolchain، میتوانید مطمئن شوید که همه توسعهدهندگان و محیطهای CI/CD از یک نسخه خاص از ابزار Go استفاده میکنند.
مدیریت نسخهها در پروژههای تیمی
این ویژگی تضمین میکند که مشکلات ناشی از ناسازگاری نسخهها (مانند تغییرات در syntax یا behavior) به حداقل برسند.
ساخت خودکار با نسخه مشخص
اگر نسخهای که در toolchain تعریف شده، روی سیستم نصب نشده باشد، ابزار Go بهطور خودکار آن را از وبسایت Go دریافت و نصب میکند.
نکته مهم درباره toolchain
این قابلیت با ابزار Go نسخه 1.21 و بالاتر در دسترس است. اگر نسخه Go قدیمیتری دارید، خط مربوط به toolchain در فایل go.mod نادیده گرفته خواهد شد.
toolchain مستقل از دستور go در فایل go.mod عمل میکند. دستور go نسخه حداقل زبان Go برای کدنویسی و بیلد کردن را مشخص میکند:
go 1.20
مثالی کامل از go.mod
module example.com/myproject go 1.20 toolchain go1.20 require ( github.com/some/library v1.2.3 )
go 1.20: نسخه حداقل برای ویژگیهای زبان Go.
toolchain go1.20: نسخه ابزار Go که پروژه باید با آن ساخته شود.
جمعبندی
toolchain یک ابزار قوی برای مدیریت و تثبیت نسخه ابزار Go در پروژههای بزرگ است. این قابلیت بهخصوص در محیطهای توسعه تیمی و پروژههایی که وابستگی شدیدی به نسخه خاصی از Go دارند، بسیار مفید است.
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
👍2🥰1🎉1
Gopher Academy
در فایل go.mod، toolchain برای تعیین نسخه ابزار Go (مانند go و ابزارهای مرتبط با آن) استفاده میشود. این ویژگی به شما امکان میدهد تا پروژه را به نسخه خاصی از ابزار Go مقید کنید، حتی اگر نسخه پیشفرض go در سیستم شما متفاوت باشد. نحوه استفاده از toolchain اگر…
در فایل go.mod، دو دستور go و toolchain نقشهای متفاوتی دارند، هرچند هر دو به نسخههای Go مرتبط هستند. در ادامه به تفاوتهای این دو دستور میپردازیم:
1. go: مشخص کردن نسخه حداقل زبان Go
این دستور نشاندهنده نسخه حداقل زبان Go است که پروژه باید با آن سازگار باشد. به عبارتی، این مقدار مشخص میکند که کدام نسخه از ویژگیهای زبان و استاندارد Go برای کامپایل و اجرای پروژه لازم است.
کاربرد:
تعیین نسخه حداقل زبان Go که برای این پروژه لازم است.
اگر نسخه ابزار Go نصبشده روی سیستم از این مقدار کمتر باشد، ابزار Go اجازه بیلد (build) یا اجرای پروژه را نمیدهد.
این دستور به طور مستقیم بر رفتار زبان و کتابخانههای استاندارد تأثیر میگذارد.
مثال:
ویژگیهای زبان و کتابخانههای استاندارد Go 1.20 به بالا در دسترس هستند.
اگر نسخه Go نصبشده روی سیستم از 1.20 کمتر باشد، هنگام اجرای دستورات go build یا go run خطا خواهید گرفت.
2. toolchain: تعیین نسخه ابزار Go
این دستور که در Go 1.21 معرفی شده، نسخهای از ابزار Go (Go Toolchain) را مشخص میکند که پروژه باید از آن استفاده کند. ابزار Go شامل مواردی مانند go build, go run, go mod, و غیره است.
کاربرد:
مجبور کردن سیستم یا محیط CI/CD به استفاده از نسخه مشخص ابزار Go، صرفنظر از نسخه نصبشده روی سیستم.
در صورت نبود نسخه مشخصشده از ابزار Go، به طور خودکار آن نسخه دانلود و نصب میشود.
مثال:
حتی اگر نسخه go روی سیستم شما 1.19 باشد، ابزار Go نسخه 1.20 را دانلود و استفاده میکند.
این خط تضمین میکند که تمام ابزارهای مرتبط با Go (کامپایلر، مدیریت ماژولها، و غیره) از نسخه خاصی پیروی کنند.
تفاوتهای اصلی
ویژگیgotoolchainهدفنسخه حداقل زبان Goنسخه ابزار Go (Go Toolchain)اثرگذاریروی ویژگیهای زبان و استانداردهاروی ابزارهای مرتبط با Goزمان معرفیقدیمی (از ابتدای Go Modules)جدید (از Go 1.21 به بعد)رفتار در نبود نسخهخطا میدهدنسخه مناسب را دانلود و استفاده میکندتأثیر بر ساخت پروژهفقط بررسی زبان و استانداردهاتعیین دقیق نسخه ابزار برای کل فرآیند
چرا از هر دو استفاده کنیم؟
go: برای اطمینان از این که کد با نسخه خاصی از زبان سازگار است.
toolchain: برای تضمین این که ابزارها و محیط ساخت دقیقاً از نسخه خاصی استفاده کنند.
مثال ترکیبی
زبان Go باید حداقل 1.20 باشد (برای ویژگیهای زبان و استانداردها).
ابزارهای مرتبط با Go باید از نسخه 1.21 استفاده کنند (حتی اگر نسخه نصبشده 1.20 باشد، نسخه 1.21 دانلود و استفاده میشود).
نتیجهگیری
go برای تعیین حداقل سازگاری زبان Go است.
toolchain برای کنترل نسخه ابزار Go در محیطهای مختلف به کار میرود.
ترکیب این دو، کنترل دقیقتری بر محیط توسعه و اجرای پروژه فراهم میکند.
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
1. go: مشخص کردن نسخه حداقل زبان Go
این دستور نشاندهنده نسخه حداقل زبان Go است که پروژه باید با آن سازگار باشد. به عبارتی، این مقدار مشخص میکند که کدام نسخه از ویژگیهای زبان و استاندارد Go برای کامپایل و اجرای پروژه لازم است.
کاربرد:
تعیین نسخه حداقل زبان Go که برای این پروژه لازم است.
اگر نسخه ابزار Go نصبشده روی سیستم از این مقدار کمتر باشد، ابزار Go اجازه بیلد (build) یا اجرای پروژه را نمیدهد.
این دستور به طور مستقیم بر رفتار زبان و کتابخانههای استاندارد تأثیر میگذارد.
مثال:
go 1.20
ویژگیهای زبان و کتابخانههای استاندارد Go 1.20 به بالا در دسترس هستند.
اگر نسخه Go نصبشده روی سیستم از 1.20 کمتر باشد، هنگام اجرای دستورات go build یا go run خطا خواهید گرفت.
2. toolchain: تعیین نسخه ابزار Go
این دستور که در Go 1.21 معرفی شده، نسخهای از ابزار Go (Go Toolchain) را مشخص میکند که پروژه باید از آن استفاده کند. ابزار Go شامل مواردی مانند go build, go run, go mod, و غیره است.
کاربرد:
مجبور کردن سیستم یا محیط CI/CD به استفاده از نسخه مشخص ابزار Go، صرفنظر از نسخه نصبشده روی سیستم.
در صورت نبود نسخه مشخصشده از ابزار Go، به طور خودکار آن نسخه دانلود و نصب میشود.
مثال:
toolchain go1.20
حتی اگر نسخه go روی سیستم شما 1.19 باشد، ابزار Go نسخه 1.20 را دانلود و استفاده میکند.
این خط تضمین میکند که تمام ابزارهای مرتبط با Go (کامپایلر، مدیریت ماژولها، و غیره) از نسخه خاصی پیروی کنند.
تفاوتهای اصلی
ویژگیgotoolchainهدفنسخه حداقل زبان Goنسخه ابزار Go (Go Toolchain)اثرگذاریروی ویژگیهای زبان و استانداردهاروی ابزارهای مرتبط با Goزمان معرفیقدیمی (از ابتدای Go Modules)جدید (از Go 1.21 به بعد)رفتار در نبود نسخهخطا میدهدنسخه مناسب را دانلود و استفاده میکندتأثیر بر ساخت پروژهفقط بررسی زبان و استانداردهاتعیین دقیق نسخه ابزار برای کل فرآیند
چرا از هر دو استفاده کنیم؟
go: برای اطمینان از این که کد با نسخه خاصی از زبان سازگار است.
toolchain: برای تضمین این که ابزارها و محیط ساخت دقیقاً از نسخه خاصی استفاده کنند.
مثال ترکیبی
module example.com/myproject go 1.20 // حداقل نسخه زبان Go toolchain go1.21 // نسخه ابزار Go
زبان Go باید حداقل 1.20 باشد (برای ویژگیهای زبان و استانداردها).
ابزارهای مرتبط با Go باید از نسخه 1.21 استفاده کنند (حتی اگر نسخه نصبشده 1.20 باشد، نسخه 1.21 دانلود و استفاده میشود).
نتیجهگیری
go برای تعیین حداقل سازگاری زبان Go است.
toolchain برای کنترل نسخه ابزار Go در محیطهای مختلف به کار میرود.
ترکیب این دو، کنترل دقیقتری بر محیط توسعه و اجرای پروژه فراهم میکند.
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
👍4👏1
Forwarded from Bardia & Erfan
درود به همگی چند ماه پیش تصمیم گرفتم توی مواردی که خیلی باهاش سروکار دارم نمونه سوالتش رو از بعضی سایت ها و یا استک اور فلو بهش برخوردم رو توی ریپوهای زیر جداگانه جمع آوری کنم
اگر دوس داشتید به اشتراک بزارید و حمایت و مشارکت کنید
🎯- نمونه سوالات مصاحبه ای گیت
https://github.com/mrbardia72/git-Interview-Questions-And-Answers
🎯- نمونه سوالات مصاحبه ای گولنگ
https://github.com/mrbardia72/Go-Interview-Questions-And-Answers
🎯- نمونه سوالات مصاحبه ای دیتابیس
https://github.com/mrbardia72/db-Interview-Questions-and-Answers
🎯- نمونه سوالات مصاحبه ای داکر
https://github.com/mrbardia72/docker-Interview-Questions-and-Answers
🎯- نمونه سوالات مصاحبه ای والت
https://github.com/mrbardia72/vault-Interview-Questions-and-Answers
👇👇join👇👇
https://t.me/addlist/KpzXaiSpKENkMGM0
اگر دوس داشتید به اشتراک بزارید و حمایت و مشارکت کنید
🎯- نمونه سوالات مصاحبه ای گیت
https://github.com/mrbardia72/git-Interview-Questions-And-Answers
🎯- نمونه سوالات مصاحبه ای گولنگ
https://github.com/mrbardia72/Go-Interview-Questions-And-Answers
🎯- نمونه سوالات مصاحبه ای دیتابیس
https://github.com/mrbardia72/db-Interview-Questions-and-Answers
🎯- نمونه سوالات مصاحبه ای داکر
https://github.com/mrbardia72/docker-Interview-Questions-and-Answers
🎯- نمونه سوالات مصاحبه ای والت
https://github.com/mrbardia72/vault-Interview-Questions-and-Answers
👇👇join👇👇
https://t.me/addlist/KpzXaiSpKENkMGM0
در Go، تفاوت بین `size` و `capacity` در مورد ساختارهایی مانند آرایهها و اسلایسها این است:
1. Size (طول یا `len`):
- نشاندهنده تعداد عناصر فعلی موجود در یک اسلایس یا آرایه است.
- با تابع
- همیشه برابر با تعداد عناصر پر شدهی اسلایس یا آرایه است.
2. Capacity (ظرفیت یا `cap`):
- نشاندهنده حداکثر تعداد عناصری است که یک اسلایس میتواند نگه دارد بدون نیاز به تخصیص دوباره حافظه.
- با تابع
- برای اسلایسها ممکن است بزرگتر از
### مثال:
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
1. Size (طول یا `len`):
- نشاندهنده تعداد عناصر فعلی موجود در یک اسلایس یا آرایه است.
- با تابع
len()
قابل دسترسی است.- همیشه برابر با تعداد عناصر پر شدهی اسلایس یا آرایه است.
2. Capacity (ظرفیت یا `cap`):
- نشاندهنده حداکثر تعداد عناصری است که یک اسلایس میتواند نگه دارد بدون نیاز به تخصیص دوباره حافظه.
- با تابع
cap()
قابل دسترسی است.- برای اسلایسها ممکن است بزرگتر از
len
باشد.### مثال:
s := make([]int, 3, 5) // اسلایس با طول 3 و ظرفیت 5
fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 5
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
❤3🙏1
Gopher Academy
در Go، تفاوت بین `size` و `capacity` در مورد ساختارهایی مانند آرایهها و اسلایسها این است: 1. Size (طول یا `len`): - نشاندهنده تعداد عناصر فعلی موجود در یک اسلایس یا آرایه است. - با تابع len() قابل دسترسی است. - همیشه برابر با تعداد عناصر پر شدهی…
اگر طول (size) یک اسلایس در Go بیشتر از ظرفیت (
این عملیات میتواند هزینهبر باشد، زیرا شامل تخصیص مجدد و کپی دادهها است. به همین دلیل مدیریت ظرفیت مناسب برای بهینهسازی عملکرد اهمیت دارد.
### مثال:
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
cap
) آن شود، Go بهطور خودکار یک حافظه جدید با ظرفیت بزرگتر تخصیص میدهد. سپس عناصر قدیمی را به حافظه جدید منتقل کرده و عنصر جدید را اضافه میکند.این عملیات میتواند هزینهبر باشد، زیرا شامل تخصیص مجدد و کپی دادهها است. به همین دلیل مدیریت ظرفیت مناسب برای بهینهسازی عملکرد اهمیت دارد.
### مثال:
s := make([]int, 3, 5)
s = append(s, 1, 2, 3) // ظرفیت پر میشود
s = append(s, 4) // ظرفیت بیشتر میشود (افزایش خودکار ظرفیت)
fmt.Println(len(s)) // 7
fmt.Println(cap(s)) // 10 (ممکن است مقدار جدید متفاوت باشد)
➖➖➖➖➖➖➖➖
https://t.me/addlist/KpzXaiSpKENkMGM0
👍2🔥2🍓2