Forwarded from linuxtnt(linux tips and tricks) (hosein seilany https://seilany.ir/)
⭐️اگر میخواهید:
🔹دمای CPU پایینتر و پایداری بیشتر داشته باشی
🔹زمان Context Switch بین threadها کاهش پیدا کنه
🔹فقط از هستههای فیزیکی واقعی استفاده بشه
🔹هستههای منطقی (Hyper-Threading/SMT) خاموش بشود
🔹هر فرآیند منابع کامل یک core را در اختیار داشته باشه
🔹 کارایی بهتر در پردازشهای real-time، بازیها یا سیستمهای کمتأخیر داشته باشی
✅ کافیست Hyper-Threading (Intel) یا SMT (AMD) رو غیرفعال کنی با اضافه کردن یک پارامتر ساده به GRUB:
مراحل سریع:
فایل GRUB رو باز کن با ویرایشگر مورد علاقهات:
sudo nano /etc/default/grub
خط زیر رو پیدا و یا اضافه کن:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nosmt"
فایل رو ذخیره کن و خارج شو.
دستور زیر رو اجرا کن تا تغییرات اعمال بشه:
sudo update-grub
سیستم رو ریستارت کن تا تغییرات فعال بشه.
🔻پست و آموزش بیشتر در وبلاگ آکادمی:
https://learninghive.ir/linux-blogs/
🔹دمای CPU پایینتر و پایداری بیشتر داشته باشی
🔹زمان Context Switch بین threadها کاهش پیدا کنه
🔹فقط از هستههای فیزیکی واقعی استفاده بشه
🔹هستههای منطقی (Hyper-Threading/SMT) خاموش بشود
🔹هر فرآیند منابع کامل یک core را در اختیار داشته باشه
🔹 کارایی بهتر در پردازشهای real-time، بازیها یا سیستمهای کمتأخیر داشته باشی
✅ کافیست Hyper-Threading (Intel) یا SMT (AMD) رو غیرفعال کنی با اضافه کردن یک پارامتر ساده به GRUB:
مراحل سریع:
فایل GRUB رو باز کن با ویرایشگر مورد علاقهات:
sudo nano /etc/default/grub
خط زیر رو پیدا و یا اضافه کن:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nosmt"
فایل رو ذخیره کن و خارج شو.
دستور زیر رو اجرا کن تا تغییرات اعمال بشه:
sudo update-grub
سیستم رو ریستارت کن تا تغییرات فعال بشه.
🔻پست و آموزش بیشتر در وبلاگ آکادمی:
https://learninghive.ir/linux-blogs/
Forwarded from محتوای آزاد سهراب (Sohrab)
فقط برای تفریح!
خب این فیلم رو گرفتم و همون کارهایی رو انجام میدم که توی بلاگ گفتم، یعنی با یک کرنل لینوکس و بیزیباکس یک نیمچه توزیع مینیمال میسازیم!
تماشا از یوتوب
تماشا از پیرتوب
تماشا از آپارات 🥴
@SohrabContents
خب این فیلم رو گرفتم و همون کارهایی رو انجام میدم که توی بلاگ گفتم، یعنی با یک کرنل لینوکس و بیزیباکس یک نیمچه توزیع مینیمال میسازیم!
تماشا از یوتوب
تماشا از پیرتوب
تماشا از آپارات 🥴
@SohrabContents
Forwarded from Gopher Academy
💋چی کار میکنه sync.Once
تضمین میکنه یک تابع دقیقاً یکبار اجرا بشه حتی اگر چندین goroutine همزمان تلاش کنن اون رو اجرا کنن. متد اصلیش
💋موارد متداول استفاده
* پیادهسازی Singleton (یکبار ساختن نمونهٔ مشترک).
* بارگذاری تنبل (lazy load) کانفیگ یا منابع سنگین فقط وقتی لازم شدن.
* عملهایی که باید فقط یکبار انجام بشن (مثلاً ثبت یک handler، close ای که نباید دوباره انجام بشه، و غیره).
مثال ساده (Singleton)
مثال: امن کردن
💋 نکات و خطرات (خیلی مهم)
1. اگر تابعِ داخل `Do` پانیک کند: در نسخهٔ فعلیِ استاندارد،
> (نکته: در Go 1.21 بهعلاوه توابعی مثل
2.ا `Once` را بعد از استفاده کپی نکنید — کپی کردن یک
3. تابعِ داخل `Do` نباید خودش `Do` را صدا بزند (یا باعث قفل/deadlock شود). اگر
4. ا`Do` مقدار/خطا برنمیگرداند — اگر تابع شما ممکن است خطا داشته باشد و بخواهید آن را به callerها برگردانید، معمولاً از pattern زیر استفاده میکنند:
اما دقت کنید: اگر
💋 پیشنهاد وقتی میخواهید retry یا مقدار/خطای دقیق داشته باشید
اگر نیاز دارید تابع مقدار برگردونه و رفتارِ retry داشته باشید، باید از الگوهای دیگری استفاده کنید (مثلاً mutex + state machine، یا کانالها، یا بستههای ثالث که این الگو رو پیادهسازی میکنن). در Go 1.21 توابعی مثل
تضمین میکنه یک تابع دقیقاً یکبار اجرا بشه حتی اگر چندین goroutine همزمان تلاش کنن اون رو اجرا کنن. متد اصلیش
Do(f func()) هست: اولین فراخوانی Do تابع f را اجرا میکنه و فراخوانیهای بعدی هیچ کاری نمیکنن (بلوک نمیشن؛ فقط بازمیگردن).💋موارد متداول استفاده
* پیادهسازی Singleton (یکبار ساختن نمونهٔ مشترک).
* بارگذاری تنبل (lazy load) کانفیگ یا منابع سنگین فقط وقتی لازم شدن.
* عملهایی که باید فقط یکبار انجام بشن (مثلاً ثبت یک handler، close ای که نباید دوباره انجام بشه، و غیره).
مثال ساده (Singleton)
var instance *MyType
var once sync.Once
func GetInstance() *MyType {
once.Do(func() {
instance = &MyType{ /* init */ }
})
return instance
}
مثال: امن کردن
close یک channel`var once sync.Once
var ch = make(chan struct{})
func safeClose() {
once.Do(func() { close(ch) })
}
💋 نکات و خطرات (خیلی مهم)
1. اگر تابعِ داخل `Do` پانیک کند: در نسخهٔ فعلیِ استاندارد،
Do آن فراخوانی را «تمامشده» در نظر میگیرد — یعنی بعد از پانیک، فراخوانیهای بعدی Do دیگر f را اجرا نخواهند کرد. (در عمل پانیک به caller برمیگردد ولی Once وضعیتِ «انجامشده» را علامت میزند). پس اگر f ممکن است پانیک کند یا نیاز به retry دارید، sync.Once ممکن است مناسبِ کامل نباشد. > (نکته: در Go 1.21 بهعلاوه توابعی مثل
OnceFunc / OnceValue اضافه شدند که رفتار پانیک/بازگردانی را متفاوت ارائه میدهند؛ خوب است اگر از این ورژنها استفاده میکنید نگاهی به مستندات بیندازید). 2.ا `Once` را بعد از استفاده کپی نکنید — کپی کردن یک
Once بعد از اولین استفاده خطا/رفتار غیرمنتظره ایجاد میکند. 3. تابعِ داخل `Do` نباید خودش `Do` را صدا بزند (یا باعث قفل/deadlock شود). اگر
f در همان Once دوباره Do را فراخوانی کند، قفل/deadlock یا رفتار نامناسب ممکن است رخ دهد. (بهصورت کلی از بلوکهای طولانی یا عملیات که ممکن است بلوکه شوند داخل f خودداری کنید).4. ا`Do` مقدار/خطا برنمیگرداند — اگر تابع شما ممکن است خطا داشته باشد و بخواهید آن را به callerها برگردانید، معمولاً از pattern زیر استفاده میکنند:
var once sync.Once
var cfg Config
var cfgErr error
func LoadConfig() error {
once.Do(func() {
cfg, cfgErr = loadFromDisk()
})
return cfgErr
}
اما دقت کنید: اگر
loadFromDisk پانیک کند یا با خطاهای خاصی مواجه شود و شما نیاز به retry داشته باشید، این الگو کافی نیست چون Do بعد از اولین اجرا (حتی اگر پانیک شد) اجازهٔ تکرار نمیدهد.💋 پیشنهاد وقتی میخواهید retry یا مقدار/خطای دقیق داشته باشید
اگر نیاز دارید تابع مقدار برگردونه و رفتارِ retry داشته باشید، باید از الگوهای دیگری استفاده کنید (مثلاً mutex + state machine، یا کانالها، یا بستههای ثالث که این الگو رو پیادهسازی میکنن). در Go 1.21 توابعی مثل
OnceValue هم اضافه شدند که کمک میکنند مقدار بازگردونده و رفتار پانیک مشخصتر بشهForwarded from Gopher Academy
بیایید هر دو حالت را ببینیم:
۱️⃣ نمونهٔ Retryدار (برای مواقعی که تابع ممکن است خطا بدهد)
۲️⃣ نمونهٔ واقعیتر (مثلاً بارگذاری فایل کانفیگ فقط یکبار)
---
🧩 مثال ۱:
اما گاهی میخواهیم تابع فقط *در صورت موفقیت* «once» باشد، وگرنه دفعهٔ بعدی دوباره تلاش کند.
برای این کار، باید رفتار خودمان را روی
🟢 نتیجه خروجی:
یعنی تابع تا زمانی که موفق نشده، باز هم قابل اجراست — اما بعد از موفقیت فقط یکبار انجام میشود ✅
🧱 مثال ۲: بارگذاری فایل کانفیگ فقط یکبار (Real-world)
🔹 حتی اگر
🔹 در برنامههای بزرگ (microserviceها، سرورها، یا SDKها) این pattern خیلی رایج است.
۱️⃣ نمونهٔ Retryدار (برای مواقعی که تابع ممکن است خطا بدهد)
۲️⃣ نمونهٔ واقعیتر (مثلاً بارگذاری فایل کانفیگ فقط یکبار)
---
🧩 مثال ۱:
sync.Once با قابلیت Retrysync.Once بهصورت پیشفرض فقط یکبار اجرا میشود — حتی اگر اون اجرا شکست بخوره.اما گاهی میخواهیم تابع فقط *در صورت موفقیت* «once» باشد، وگرنه دفعهٔ بعدی دوباره تلاش کند.
برای این کار، باید رفتار خودمان را روی
Once شبیهسازی کنیم:package main
import (
"errors"
"fmt"
"sync"
)
type OnceRetry struct {
mu sync.Mutex
done bool
}
func (o *OnceRetry) Do(f func() error) error {
o.mu.Lock()
defer o.mu.Unlock()
if o.done {
return nil
}
err := f()
if err != nil {
return err
}
o.done = true
return nil
}
func main() {
var once OnceRetry
counter := 0
task := func() error {
counter++
if counter < 3 {
fmt.Println("❌ Failed attempt", counter)
return errors.New("temporary error")
}
fmt.Println("✅ Success on attempt", counter)
return nil
}
for i := 0; i < 5; i++ {
err := once.Do(task)
if err != nil {
fmt.Println("Error:", err)
}
}
fmt.Println("Final counter =", counter)
}
🟢 نتیجه خروجی:
❌ Failed attempt 1
Error: temporary error
❌ Failed attempt 2
Error: temporary error
✅ Success on attempt 3
Final counter = 3
یعنی تابع تا زمانی که موفق نشده، باز هم قابل اجراست — اما بعد از موفقیت فقط یکبار انجام میشود ✅
🧱 مثال ۲: بارگذاری فایل کانفیگ فقط یکبار (Real-world)
package main
import (
"encoding/json"
"fmt"
"os"
"sync"
)
type Config struct {
Port int `json:"port"`
Mode string `json:"mode"`
}
var (
cfg Config
cfgErr error
cfgOnce sync.Once
)
func LoadConfig() (Config, error) {
cfgOnce.Do(func() {
fmt.Println("📁 Reading config.json only once...")
data, err := os.ReadFile("config.json")
if err != nil {
cfgErr = err
return
}
cfgErr = json.Unmarshal(data, &cfg)
})
return cfg, cfgErr
}
func main() {
for i := 0; i < 3; i++ {
c, err := LoadConfig()
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Loaded config:", c)
}
}
}
🔹 حتی اگر
LoadConfig() چندبار فراخوانی شود، فایل فقط یکبار خوانده میشود.🔹 در برنامههای بزرگ (microserviceها، سرورها، یا SDKها) این pattern خیلی رایج است.
Forwarded from محتوای آزاد سهراب (Sohrab)
این ویدئو چون محتوای ارائه دانشگاهم بود زیاد چیزی رو پوشش ندادم داخلش.
یک ویدئو دیگه ضبط میکنم و یک توزیع میسازیم با این استک:
musl, dinit, busybox
حالا بجای dinit احتمالا از runit استفاده کنم ولی از اونجایی که dinit رو خیلی وقته میخوام امتحان کنم احتمالا اون رو استفاده کنم.
اگر بتونم مشکل استکنتورک بیزیباکس رو هم حل کنم از brew به عنوان مدیربسته استفاده میکنیم.
اگر هم پیشنهادی دارید توی کامنتها بگید.
@SohrabContents
یک ویدئو دیگه ضبط میکنم و یک توزیع میسازیم با این استک:
musl, dinit, busybox
حالا بجای dinit احتمالا از runit استفاده کنم ولی از اونجایی که dinit رو خیلی وقته میخوام امتحان کنم احتمالا اون رو استفاده کنم.
اگر بتونم مشکل استکنتورک بیزیباکس رو هم حل کنم از brew به عنوان مدیربسته استفاده میکنیم.
اگر هم پیشنهادی دارید توی کامنتها بگید.
@SohrabContents
Forwarded from محتوای آزاد سهراب (Sohrab)
This media is not supported in your browser
VIEW IN TELEGRAM
Forwarded from DevTwitter | توییت برنامه نویسی
یکی از چالشهای کار با کتابخانههای مختلف به کمک هوش مصنوعی بهروز نبودن یا در فرمت مناسب نبودن مستنداته. یک سرویس رایگان و بهروز هست به اسم Context7 که تقریباً همه چیز رو داره و راحت میتونید به فرآیند کاریتون در کدنویسی با AI اضافهاش کنید.
https://context7.com/
@DevTwitter | <Hamed/>
https://context7.com/
@DevTwitter | <Hamed/>
Forwarded from Gopher Academy
Here's a toy example:
```go
// Given a channel of documents.
docs := make(chan []string, 10)
docs <- []string{"go", "is", "awesome"}
docs <- []string{"cats", "are", "cute"}
close(docs)
// Extract all words from the documents.
words := make(chan string, 10)
chans.Flatten(ctx, words, docs)
close(words)
// Calculate the total byte count of all words.
step := func(acc int, word string) int { return acc + len(word) }
count := chans.Reduce(ctx, words, 0, step)
fmt.Println("byte count =", count)
```
byte count = 22
```go
// Given a channel of documents.
docs := make(chan []string, 10)
docs <- []string{"go", "is", "awesome"}
docs <- []string{"cats", "are", "cute"}
close(docs)
// Extract all words from the documents.
words := make(chan string, 10)
chans.Flatten(ctx, words, docs)
close(words)
// Calculate the total byte count of all words.
step := func(acc int, word string) int { return acc + len(word) }
count := chans.Reduce(ctx, words, 0, step)
fmt.Println("byte count =", count)
```
byte count = 22
Forwarded from Gopher Academy
Here's a toy example:
byte count = 22
// Given a channel of documents.
docs := make(chan []string, 10)
docs <- []string{"go", "is", "awesome"}
docs <- []string{"cats", "are", "cute"}
close(docs)
// Extract all words from the documents.
words := make(chan string, 10)
chans.Flatten(ctx, words, docs)
close(words)
// Calculate the total byte count of all words.
step := func(acc int, word string) int { return acc + len(word) }
count := chans.Reduce(ctx, words, 0, step)
fmt.Println("byte count =", count)
byte count = 22
Forwarded from Gopher Academy
✅ این تصویر نمونهای از مفهوم Summary برای یک bitmap در حافظهی Go رو نشون میده
🧩 این Bitmap Summary در مدیریت صفحات Go
در این شکل، هر بیت از bitmap نشاندهندهی وضعیت یک صفحهی حافظه است:
*
*
برای بهینهسازی جستجوی صفحات آزاد، Go برای هر bitmap سه مقدار خلاصهشده (summary) نگه میداره:
*
*
*
🔹 فلش در تصویر جهت افزایش آدرس حافظه (از پایین به بالا) رو نشون میده.
در نتیجه، ۳ صفحهی آزاد در بخش پایینتر حافظه (low address) و ۷ صفحهی آزاد در بالاترین بخش (high address) قرار دارن.
این ساختار باعث میشه Go خیلی سریعتر بتونه محدودههای بزرگ از صفحات آزاد رو پیدا کنه بدون اینکه کل bitmap رو اسکن کنه — فقط با نگاه کردن به summaryها!
➖➖➖➖➖➖➖➖
👑 @gopher_academy
🧩 این Bitmap Summary در مدیریت صفحات Go
در این شکل، هر بیت از bitmap نشاندهندهی وضعیت یک صفحهی حافظه است:
*
0 → صفحه آزاد (free)*
1 → صفحه در حال استفاده (allocated)برای بهینهسازی جستجوی صفحات آزاد، Go برای هر bitmap سه مقدار خلاصهشده (summary) نگه میداره:
*
start = 3 → یعنی در ابتدای bitmap، ۳ صفحهی متوالی آزاد داریم*
end = 7 → یعنی در انتهای bitmap، ۷ صفحهی متوالی آزاد داریم*
max = 10 → طولانیترین دنبالهی صفحات آزاد در کل bitmap برابر با ۱۰ صفحه است🔹 فلش در تصویر جهت افزایش آدرس حافظه (از پایین به بالا) رو نشون میده.
در نتیجه، ۳ صفحهی آزاد در بخش پایینتر حافظه (low address) و ۷ صفحهی آزاد در بالاترین بخش (high address) قرار دارن.
این ساختار باعث میشه Go خیلی سریعتر بتونه محدودههای بزرگ از صفحات آزاد رو پیدا کنه بدون اینکه کل bitmap رو اسکن کنه — فقط با نگاه کردن به summaryها!
➖➖➖➖➖➖➖➖
👑 @gopher_academy
Forwarded from محتوای آزاد سهراب (Sohrab)
This media is not supported in your browser
VIEW IN TELEGRAM
در سه زبان مختلف
Forwarded from محتوای آزاد سهراب (Sohrab)
This media is not supported in your browser
VIEW IN TELEGRAM
Forwarded from محتوای آزاد سهراب (Sohrab)
This media is not supported in your browser
VIEW IN TELEGRAM
Forwarded from محتوای آزاد سهراب (Sohrab)
This media is not supported in your browser
VIEW IN TELEGRAM
Forwarded from Gopher Academy
🔵 عنوان مقاله
progjpeg: image/jpeg But With Progressive Encoding Support
🟢 خلاصه مقاله:
progjpeg نسخهای از بسته image/jpeg در زبان Go است که امکان Progressive Encoding را به آن اضافه میکند؛ قابلیتی که تصویر را ابتدا بهصورت کمجزئیات نشان میدهد و در چند گذر با دریافت دادههای بیشتر شفافتر میشود. این ویژگی میتواند در شبکههای کند تجربه کاربری را بهبود دهد و توسط بیشتر مرورگرها و دیکدرهای تصویر پشتیبانی میشود. چون درخواست افزودن این قابلیت در مخزن رسمی Go «متوقف/فریز» شده بود، progjpeg این خلأ را برای توسعهدهندگان پر میکند. هرچند کاربرد آن تخصصی است، اما برای سرویسهای وب و سامانههای سنگینِ تصویر میتواند تجربه بارگذاری روانتری فراهم کند، با درنظرگرفتن ملاحظاتی مثل پیچیدگی کدنویسی و تفاوت احتمالی در اندازه فایل.
#Go #Golang #JPEG #ProgressiveJPEG #ImageProcessing #WebPerformance #OpenSource
🟣لینک مقاله:
https://golangweekly.com/link/176639/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
progjpeg: image/jpeg But With Progressive Encoding Support
🟢 خلاصه مقاله:
progjpeg نسخهای از بسته image/jpeg در زبان Go است که امکان Progressive Encoding را به آن اضافه میکند؛ قابلیتی که تصویر را ابتدا بهصورت کمجزئیات نشان میدهد و در چند گذر با دریافت دادههای بیشتر شفافتر میشود. این ویژگی میتواند در شبکههای کند تجربه کاربری را بهبود دهد و توسط بیشتر مرورگرها و دیکدرهای تصویر پشتیبانی میشود. چون درخواست افزودن این قابلیت در مخزن رسمی Go «متوقف/فریز» شده بود، progjpeg این خلأ را برای توسعهدهندگان پر میکند. هرچند کاربرد آن تخصصی است، اما برای سرویسهای وب و سامانههای سنگینِ تصویر میتواند تجربه بارگذاری روانتری فراهم کند، با درنظرگرفتن ملاحظاتی مثل پیچیدگی کدنویسی و تفاوت احتمالی در اندازه فایل.
#Go #Golang #JPEG #ProgressiveJPEG #ImageProcessing #WebPerformance #OpenSource
🟣لینک مقاله:
https://golangweekly.com/link/176639/web
➖➖➖➖➖➖➖➖
👑 @gopher_academy
GitHub
GitHub - dlecorfec/progjpeg: Go JPEG package with progressive encoding
Go JPEG package with progressive encoding. Contribute to dlecorfec/progjpeg development by creating an account on GitHub.
Forwarded from DevTwitter | توییت برنامه نویسی
توی این ریپو یه لیست خیلی خوب از پادکست های برنامه نویسی و تکنولوژی جمع کردن، به زبان انگلیسی و آلمانی و روسی و... هستش، هم برای یادگیری زبان تخصصی خوبه هم خود اون تکنولوژی
https://github.com/rShetty/awesome-podcasts
@DevTwitter | <MEHDI Homeily/>
https://github.com/rShetty/awesome-podcasts
@DevTwitter | <MEHDI Homeily/>
Forwarded from Linuxor ?
Forwarded from Linuxor ?
توی یوتیوب عدد دیسلایک ها نشون داده نمیشه
علتش هم بخاطر اینه که گوگل سال 2021 یهویی تصمیم گرفت، اون عدد رو مخفی کنه چون بعضی از پستا بیخودی دیسلایک میگرفت یعنی کاربرا میدیدن دیسلایک زیاده و بد تر پست رو دیسلایک میکردن و این باعث میشد دیسلایک ها بالا بره، همچنین بعضیا میومدن یه ویدیو رو با دیسلایک گروهی خرابش میکردن برای همین گوگل اومد اون عدد رو مخفی کرد ولی توی API ش هنوز اون عدد به فرانتاند داده میشه میتونید با این اکستنشن عدد دیسلایک هارو اضافه کنید:
returnyoutubedislike.com/install
@Linuxor
علتش هم بخاطر اینه که گوگل سال 2021 یهویی تصمیم گرفت، اون عدد رو مخفی کنه چون بعضی از پستا بیخودی دیسلایک میگرفت یعنی کاربرا میدیدن دیسلایک زیاده و بد تر پست رو دیسلایک میکردن و این باعث میشد دیسلایک ها بالا بره، همچنین بعضیا میومدن یه ویدیو رو با دیسلایک گروهی خرابش میکردن برای همین گوگل اومد اون عدد رو مخفی کرد ولی توی API ش هنوز اون عدد به فرانتاند داده میشه میتونید با این اکستنشن عدد دیسلایک هارو اضافه کنید:
returnyoutubedislike.com/install
@Linuxor
Forwarded from Laravel News
Trying a new live preview: https://news.1rj.ru/str/iv?url=https://laravel-news.com/cache-smart-invalidation-laravel-in-practice-ep10&rhash=8fee474e8a1638
Laravel News
Cache Smart Invalidation - Laravel In Practice EP10
Your cache is fast, but it's lying. Laravel's flexible cache creates three keys per entry - and if you only clear one, stale metadata lingers. In this video, I show you how to build complete cache invalidation that clears both your memoization and flexible…
Forwarded from DevTwitter | توییت برنامه نویسی
اینکه بعضی وقت ها یه مشکلی داری و اون رو با یک پکیج حل میکنی و دیگران هم از اون خوششون میاد و استفاده می کنند واقعا حس خوبی داره
از اینکه اولین پکیجی که نوشتم با اینکه چیز خاصی نبود ولی تا الان 1300 دانلود داشته خیلی خوشحالم. ممنون از حمایت و استفاده تون
دیروز داکیومنت رو آپدیت کردم و فهرست مطالب هم اضافه کردم راحت تر بشه استفاده ازش
پکیج فیکر فارسی برای PHP - لینک گیت هاب
https://github.com/amyavari/persian-faker-php
@DevTwitter | <Ali Mohammad Yavari/>
از اینکه اولین پکیجی که نوشتم با اینکه چیز خاصی نبود ولی تا الان 1300 دانلود داشته خیلی خوشحالم. ممنون از حمایت و استفاده تون
دیروز داکیومنت رو آپدیت کردم و فهرست مطالب هم اضافه کردم راحت تر بشه استفاده ازش
پکیج فیکر فارسی برای PHP - لینک گیت هاب
https://github.com/amyavari/persian-faker-php
@DevTwitter | <Ali Mohammad Yavari/>