<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های abbas80</title>
        <link>https://virgool.io/feed/@m_15553325</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-04-15 08:56:37</pubDate>
        <image>
            <url>https://static.virgool.io/images/default-avatar.jpg</url>
            <title>abbas80</title>
            <link>https://virgool.io/@m_15553325</link>
        </image>

                    <item>
                <title>عملگر ternary در گو</title>
                <link>https://virgool.io/@m_15553325/%D8%B9%D9%85%D9%84%DA%AF%D8%B1-ternary-%D8%AF%D8%B1-%DA%AF%D9%88-uizuazb9e05f</link>
                <description> در این فسمت می حواهیم به عملگر سه تایی (ternary) آشنا بشیم و آنرا در زبان گو پیاده کنیم.عملگر سه تایی یا (ternary operator) دارا سه بخش است یه چیزی شبیه این:result = cond ? val1 : val2cond: شرظ مورد نظرval1: مقداری که اگه شرط درست باشدval2:مقداری که اگه شرط غلط باشهولی همچین سینتکسی تو گو نداریم --به جایش مجبوریم از if/else استفاده کنیم        x := 2
        var res string
        if x &gt;= 0 {
                res = &amp;quotPositive&amp;quot
        } else {
                res = &amp;quotNegative&amp;quot
        } // Whyولی آیا بهتر می توای این کد زا نوشت ...در ادامه به چندین روش جایگرین می نگریمروش اول: متغیر پیش فرض (default value)اول به متغیرمون یگی از مقدارها رو می دهیم و اگه شرط درست بود مقدار دیگر را در ان می ریزیم	x := 16
	res := &amp;quotodd&amp;quot
	if x%2 == 0 {
		res = &amp;quoteven&amp;quot
	}روش دوم: تعریف تابع جدا (seperate function)شرطمون رو در تابعی (یا متدی) جدا می نویسیم و از آن استفاده می کنیمfunc main() {
    ...
	x, y := 12, 6
	res := less(x, y)
	...
}
func less(a, b int) int {
    if a &lt; b {
		return a
	}
	return b
}
جمع بندیزبان گو عملگر سه تایی (یا ternary operator) ندارد با این وجود کار های دیگری وجود دارد که آنرا شبیه سازی کنیم.من پیشتر از تابع استفاده می کنمامیدوارم لذت برده باشیم تشکر ;)  </description>
                <category>abbas80</category>
                <author>abbas80</author>
                <pubDate>Mon, 29 Jul 2024 12:06:48 +0330</pubDate>
            </item>
                    <item>
                <title>یک پی دی اف خوان جمع و جور با پایتون</title>
                <link>https://virgool.io/@m_15553325/%DB%8C%DA%A9-%D9%BE%DB%8C-%D8%AF%DB%8C-%D8%A7%D9%81-%D8%AE%D9%88%D8%A7%D9%86-%D8%AC%D9%85%D8%B9-%D9%88-%D8%AC%D9%88%D8%B1-%D8%A8%D8%A7-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-tmxpeimxa3xm</link>
                <description>چند وقت بود که میخواستم یک PDF خوان ساده با پایتون داشته باشم که با کتابخانه های pyPDF2 و pytts3 آشنا شدم٬ با اولی میشه کارهای جالبی با پی دی اف کرد و دومی متنی رو تبدیل به صدا می کند.پس کد زیر رو بعد چندی ارور و دیپندنسی٬ اجرا کردمنسخه صفر# importing the modules
import PyPDF2
import pyttsx3

# path, and pages of the PDF file
path = &#039;nodejs.pdf&amp;quot
pdf = open(path, &amp;quotrb&amp;quot)

# creating a PdfFileReader object
pdfReader = PyPDF2.PdfReader(pdf)

# the page with which you want to start
# breakpoint()
from_page = pdfReader.pages[1]
# extracting the text from the PDF
text = from_page.extract_text()

# reading the text
speak = pyttsx3.init()
speak.say(text)
speak.runAndWait()بعد با خودم فکر کردم &#x27;چه کاریه فایل و صفحه رو بصورت هارد کد وارد کنیم&#x27;؛ پس ورودی های مورد نظر رو از طریق خط فرمان با ماژول os گرفتم: اینجورینسخه اولimport os
import sys
...
path = sys.argv[1] #NOTE: argv[0] is `python[3]`
pages = sys.argv[2]بعد اسکریپتم باید بازه ای از صفحاتو بپذیره ٬تقریبا با فرمت لیست پایتون٬ {هیج جی نشده برنامه مون از ۲۵ خط بیشتر شده٬;) }...
first, last = pages, pages
if pages.count(&amp;quot:&amp;quot):
    first, last = pages.split(&amp;quot:&amp;quot)
if not (first.isnumeric() and last.isnumeric()):
    raise TypeError(f&amp;quotargument pages must be integer, got {first, last}&amp;quot)
first, last = int(first), int(last)
... # it&#039;s such a mess!پس چطوره کمی کد رو بهبود بدیم؟نسخه دوم (فعلا به روز)بنابراین خواندن ورودی و تبدیل متن به صدا را به دو تابع مجزا انتقال دادم.def parse_input(path, pages):
    ranges = pages.split(&#039;-&#039;) # for indicating range of pages
    pages= []
    for t in ranges:
        # TODO: regard the case `:n`, `n:`
        if t == &#039;&#039;: # im case -gt `-`
            continue
        page=t.split(&#039;:&#039;)
        if len(page) == 1:#one page
            page.append(page[0])
        elif len(page) &gt; 2:
            raise SyntaxError(&amp;quotthere must be one `:` in page argument&amp;quot)
        pages.append(page)
    pages = [list(map(int,page)) for page in pages]
    path = Path(os.getcwd(),path) # full path
    return path, pages
def pdf_speak(pdfReader, first, last):
    for page in range(first-1,last): # page adjustment
        from_page = pdfReader.pages[page]
        # extracting the text from the PDF
        text = from_page.extract_text()
        if text != &#039;&#039;: #NOTICE: check to prevent speak error
            speak.say(text)

    # reading the text
    speak.runAndWait()
کد کامل رو میتونید از گیت هاب ببینید و اگه دوست داشتین میتونین ستاره✨ بدید یا چنگال🍴 بزنیدتشکر :-)</description>
                <category>abbas80</category>
                <author>abbas80</author>
                <pubDate>Thu, 18 Jul 2024 12:17:04 +0330</pubDate>
            </item>
                    <item>
                <title>نگاهی مختصر به concurrency در Go: چنل ها</title>
                <link>https://virgool.io/@m_15553325/%D9%86%DA%AF%D8%A7%D9%87%DB%8C-%D9%85%D8%AE%D8%AA%D8%B5%D8%B1-%D8%A8%D9%87-concurrency-%D8%AF%D8%B1-go-%DA%86%D9%86%D9%84-%D9%87%D8%A7-of2ookpvpni2</link>
                <description>آشنایی با channel هادر مطلب قبلی کمی درمورد قابلیت های گو در همزمانی صحبت کردیم و اولین قدم هایمان را رفتیم٬ در این جا در مورد چنل ها گمی بیشتر حرف می زنیمچنل ها (channels) یک راه ارتباط است برای گوروتین ها بطوری که داده ای را که در گوروتین ها و تابع اصلی احتیاج داریم ذخیره می کنیم و در مواقع بعد آنرا دریافت می کنیمیک برنامه جمع کوچیک که از چنل ها در ان استفاده شده می نویسیمpackage main

import (
	&amp;quotfmt&amp;quot
	&amp;quottime&amp;quot
)

var (
	input = 10
)

func main() {
	a := make(chan int)
	b := make(chan int)
	mid := input / 2
	go sumIt(0, mid, a) // first numbers
	go sumIt(mid+1, input, b) // last numbers
	result := &lt;-a + &lt;-b // receiving data ; sumUp
	fmt.Println(result)
}

func sumIt(start, stop int, res chan int) {
	defer close(res) // make sure to close channel
	sum := 0
	for i := start; i &lt;= stop; i++ {
		sum += i
		fmt.Printf(&amp;quotnum:%d,\tsum:%d\n&amp;quot, i, sum)
		time.Sleep(100 * time.Millisecond)
	}
	res &lt;- sum // sending data
}این برنامه جمع را با دو تابع انجام می دهد!ch := make(chan string)
go fun(ch)شیوه استفاده از channels: اول یک متغیر از نوع چنلو با هر دیتا تایپی دوست دارید٬ با تابع make ایجاد می کنیم و اون رو به تابع پاس می دهیمfunc fun(ch chan string) {
ch &lt;- &amp;quotGo is fun!&amp;quot
}در تابع fun از پارامتر ch بهره میبریم و داده مورد نظر را می فرستیم (یا ذخیره می کنیم)ch := make(chan string)
go fun(ch)
fmt.Println(&lt;-ch)و در تابع اصلی داده را دریافت کرده و آنرا نمایش می دهیم!!توجه : -&gt; برای ارسال و دریافت داده ها به کار میرود٬ اگه بعد از متغیر باشد داده ارسال میشود واگه قبلش باشه داده دریافت میشودتوجه : -&gt; فقط یکبار می توانیم از آن داده ارسال و دریافت کنیم (نه بیشتر) مگر در شرایط خاص!توجه : -&gt; باعث میشود که دریافت کننده صبر کند تا داده مورد نظر ارسال کننده بفرستدشرح deadlockبعضی وقت ها تو برنامه مون شرایظی پیش می آید که هیج گوروتینی اجرا نمی شود و همه متوقف شده اند. راه های مختلفی برای deadlock درست کردن؛ مثلا همان برنامه قبل٬ اگه فقط تو تابع main یا تابع fun دستکاری کنیم خطا میده.func fun(ch chan string) {
fmt.Println(&amp;quotGo is fun!&amp;quot) // no sending !
} ch := make(chan int)
go fun(ch)
fmt.Println(&lt;-ch)
fmt.Println(&lt;-ch) // receiving twice !و با همجین جیزی مواجهه میشویم!خطا: توقف همه گورتینها  شايد از راه حل ها استفاده از buffered channels باشد!نگاهی به buffered channelsمانند چنل های معمولی اند ولی طرفیت چنل را محدود میکنند٬ یک پارامتر به آن اضافه می کنیم (پیش فرضش 0 است) و این باعث تغییر بافر (یا ظرفیت) به اندازه دلخواه باشد.یه مثال کوجکfunc main() {
	ch := make(chan string, 2)
	ch &lt;- &amp;quotGolang&amp;quot
	ch &lt;- &amp;quotchannels&amp;quot
	fmt.Println(&lt;-ch)
	fmt.Println(&lt;-ch)
}نکته -&gt; ارسال کننده وقت پرشدن چنل هیج جی نمی تونه بفرسته؛ دریافت کننده تا زمان خالی شدن چنل می تونه داده بگیرهجمع بندیتو این مطلب آموختیم که جنلها (channels) داده ها را به گوروتین های مختلف با کمترین دردسر انتقال می دهند٬ فقط کافیه یک متغیر با تایپ همسان تعریف کنیم بعد با &#x27;-&gt;&#x27; می تونیم داده را ذخیره (ارسال) و رها (دریافت) کنیم٬ البته میتونیم ظرفیت جنل هایم مشخص کنیم ...امیدوارم لذت برده باشید :-)</description>
                <category>abbas80</category>
                <author>abbas80</author>
                <pubDate>Sat, 22 Jun 2024 08:44:43 +0330</pubDate>
            </item>
                    <item>
                <title>نگاهی مختصر به concurrency در Go: مقدمه</title>
                <link>https://virgool.io/@m_15553325/%D9%86%DA%AF%D8%A7%D9%87%DB%8C-%D9%85%D8%AE%D8%AA%D8%B5%D8%B1-%D8%A8%D9%87-concurrency-%D8%AF%D8%B1-go-%D9%85%D9%82%D8%AF%D9%85%D9%87-g58k6n7coemc</link>
                <description>همزمانی یا همان concurrency بطور کلی اجرای کدها بصورت غیر خطی است و در زبان کو براحتی می توان از آن استفاده کرد.یعنی وقتی اجرای دستوری زمان بگیرد  برنامه مون بخاطرش موفق نمی شود و به اجرای دستورات بعدی می رود٬ بعدا با مثال بیشتر آشنا خواهید شدزبان گو concurrency را با goroutines (گوروتین ها) هندل می کند٬ گوریتین ها مزایای زیادی نسبت به ترد های سیستم عامل دارد مثلا: حجم کمتر٬ سربار کمتر٬ پیاده سازی آسانتر٬ سرعت پیشتر و ...حالا چجوری این گوروتین ها رو پیاده سازی کنیم؟کیورد goاول یک برنامه معمولی می نویسیمpackage main

import &amp;quotfmt&amp;quot

func count(n int) {
	for i := 0; i &lt; n; i++ {
		fmt.Println(i, n)
		time.Sleep(500 * time.Millisecond)
	}
}

func main() {
	 count(3)
}مثل آب خوردن فقط کافیه اول خط کلمه کلیدی go را اضافه کنیم!
func main() {
	go count(3) // just this
}
هیجی !!همانطور که می بینید هیج خروجی نشان نداد ؛/ چون هر برنامه توسظ یک گوروتین اصلی (main) اجرا می شود و هنگامی که کارش تمام می شود گوروتین های دیگه هم متوقف می کند.فعلا دستی خودمون حلش می کنیم تا ببینیم چی میشه :|
func main() {
	go count(3)
	time.Sleep(2*time.Second) // ok ;)
}
خب٬ بعدش یک goroutine دیگه اضافه می کنیم
func main() {
	go count(3)
	go count(5)
	time.Sleep(5*time.Second) // just to make sure;
}
شما می تونید (به همین اسونی) ترد اضافه کنید اما٬ راه حلی بهتر از رفع این باگ وجود دارد؟sync/WaitGrouppackage main

import (
	&amp;quotfmt&amp;quot
	&amp;quotsync&amp;quot
	&amp;quottime&amp;quot
)

func count(n int) {
	for i := 0; i &lt; n; i++ {
		fmt.Println(i, n)
		time.Sleep(200 * time.Millisecond)
	}
}

func main() {
	var wg sync.WaitGroup
	wg.Add(1)

	go func() {
		defer wg.Done()
		count(4)
	}()
	wg.Wait()
}ابتدا ما پکیج sync را وارد کردیم٬ سپس در تابع main یک متغیر از sync.WaitGroup ساختیم و با متد Add٬ تعداد گوروتین ها را مشخض کردیم (این به این معنیست که ما منتظر چند گوروتین هستیم) بعد ما خط فراخوانی تابع را بصورت یک تابع ناشناس درآوردیم تا همونجا از آن استفاده کنیم بعد به صورت defer متد Done از wg را صدا میزنیم تا بفهمانیم کارمون تموم شده ودر آخر متد wg.Wait را برای منتظر ماندن گوروتین main سدا زدیم.کار waitGroup اینه که فرایند main در حال اجرا نگه دارد تا مانع اتمام برنامه شود٬ ولی اگه خواستیم از توابع دادهی را رد و بدل چاره چیست؟خب كار با چنل ها و چیز های دیگه رو در پست بعدی مشاهده خواهید کرد ولی تا اینجا رسیدیم بد نیست یک جمع بندی انجام بدیمجمع بندیزبان گو برای کارهای همزمانی (concurrency) زبان جمع و جوری است بخصوص با ویژگی خفن گوروتین ها (goroutines) میشه براحتی انرا پیاده سازی کرد٬ از ویژگی های دیگر گولنگ WaitGroup است که مانع پایان یافتن گوروتین اصلی قبل گوروتین های دیگه استخب امیدوارم مطلب مفید باشد٬ تا وقتی دیگر بدرود :-)</description>
                <category>abbas80</category>
                <author>abbas80</author>
                <pubDate>Tue, 18 Jun 2024 10:55:34 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت Unknown و Any در تایپ اسکریبت</title>
                <link>https://virgool.io/@m_15553325/%D8%AA%D9%81%D8%A7%D9%88%D8%AA-unknown-%D9%88-any-%D8%AF%D8%B1-%D8%AA%D8%A7%DB%8C%D9%BE-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D8%A8%D8%AA-szozpijdvtvn</link>
                <description>یکی از امکانات جالب Typescript تایپ سیفتی بودنش است٬ یعنی یک متغیر در طول برنامه فقط یک تایپ دارد (مثلا number است) و به تایپ دیگر (مثلا string) تفییر نمی کند و این خودش باعث جلوگیری از بسیاری باگ ها می شودولی بعضی وقت ها نمیدونیم تایپ متعیرمون رو چی بزاریم یا اصلا تایپش مشخص نسیت که در این مواقع دست به دامن &#x60;any‍‍&#x60; می شویم٬ حالا &#x60;any‍‍&#x60; جیست؟تایپ anyاین تایپ می تونه هرجیزی باشه (number, string, یا object) یا به عبارت دیگر شامل همه تایپ های دیگر است پس متغیر می تواند هر داده ای از هر تایپی داشته باشدlet num1 = 14
console.log(typeof(num1)) // number
num1 = &#039;14&#039; // Errorارور ناسازگاری تایپهمانطور که می بینید با اجرای کد به ارور بر می خوریم ولی با any این نوع ارور ها وجود نداردlet num2: any = 24
console.log(typeof(num2)) // number
num2 = &#039;24&#039;  //! No errorو بدین ترتیب هیچ مشکلی پیش نمی آید :-)بدون شرححالا unknown چه تایپی هست?!تایپ unknownاما درمورد unknown این هم از جهاتی مثل any استlet num2: unknown = 24
console.log(typeof(num2)) // number
num2 = &#039;24&#039;  //! No errorولی فرقش از آنجا معلوم می شود که در توابع استفاده شودfunction addOne(num: any): number {
	return num + 1
}
console.log(addOne(13)) // 14console.log(addOne(&#039;13&#039;)) //  &#039;131&#039;به نتیحه دلخواهمون نریسدیم ;.(function addOne(num: unknown): number {
	return num + 1
}
console.log(addOne(13)) // Errorconsole.log(addOne(&#039;13&#039;)) //  Errorعلاج کار قبل از وقوعحالا با unknown از این باگ فاحش مطلع شدیم ولی هنوز یک مشکل اساسی استچگونه از unknown استفاده کنیم؟برای حل این مشکل یک شرط کوچولو کافی است!function addOne(num: unknown): number {
	if (typeof(num) == &#039;number&#039;){
		return num + 1
	} // rest of function is optional
	return 1
}
console.log(addOne(13)) // 14console.log(addOne(&#039;13&#039;)) //  1این شرط چک می کند که آیا متغیر تایپ مورد نطر رو داره یا نهاگر نه٬ از خط می گذرد (بدون هیچ باگ و ارور)نکته: شما می تونید بعد از شرط هر کدی رو بذازید یا حتی ارور خودتون رو برگردونیدخیلی بهتر شدجمع بندیخلاصه به نطرم unknown از any بهتر است و کمتر با باگ ها دست و پنجه نرم می کنید ولی تا آنجا ممکن است از این دو اجتناب کنید (بخصوص any) و از تایپ های دیگه استفاده کنید و ...صبر کنید تا ترفندی یاد بدهم که زندگی شما رو راحت تر می کند فقط کافیه تو فایل tsconfig.json این دو خط کد رو اضافه کنیدnoImplicitAny: true // for no any in projectstrict: true // for checking type strictlyتا هرموقع از any استفاده می کنید اجازه نده:موفق باشید ! </description>
                <category>abbas80</category>
                <author>abbas80</author>
                <pubDate>Fri, 14 Jun 2024 13:30:02 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش نحوه نصب node js در ubuntu</title>
                <link>https://virgool.io/@m_15553325/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D9%86%D8%AD%D9%88%D9%87-%D9%86%D8%B5%D8%A8-node-js-%D8%AF%D8%B1-ubuntu-nbvkwxcjx6w2</link>
                <description>امروز می حواهیم با نصب نود جی اس در اوبونتو آشنا شویم.اما قبل همه چیز واقعا نود جی اس (NodeJs) چیست؟ خلاصه نود جی اس٬ یک محیط اجرایی (runtime environment) است که کد جاوا اسکریپت (Javascript) را خارج از مرورگر اجرا می کند.حالا بپردازیم به قضیه اصلی!در واقع چندین روش برای این کار وجود دارد که من دوتا از آنها را آورده ام و به همراه یک روش جالب!روش اول: از طریق مخزناولین راه٬ استفاده از مخزن خود اوبونتو (یعنی apt) است.ابتدا ٬ با این دستور٬ مخزن را بروز کنیدsudo apt updateبعد نود جی اس را با این دستور نصب کنیدsudo apt install nodejs
روش دوم: از طریق سایت nodejs.orgراه دیگر اینست که به سایت nodejs.org وارد شویمدر قسمت Downloads کلیک می کنیمدر این قسمت بر اساس نسخه نود جی اس و معماری کامپیوترمون بر دکمه دانلود کلیک می کنیدروش سوم: از طریق سورس کداما در روش آخر باید سورس کد را از این طریق دریافت کنیمgit fetch https://github.com/nodejs/node.gitبعد پیش نیاز ها را نصب می کنیمsudo apt update &amp;&amp; sudoapt install python3 g++ make python3-pipو سپس داخل پوشه شوید و کد منبع را با این دستور بیلد کنید./coverage
make -j4آپشن j تعداد ورکرها را نشان میدهدو اما روش جالب مونده که بزودی خواهیم دیدروش جالب: از طریق nvmاین روش باعث می شود به چندین نسخه از نود جی اس به طور همزمان در سیستممان داشته باشیمخب اول از همه nvm را نصب می کنیمcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bashبرای نصب نسخه مورد نظر دستور زیر را میزنیمnvm install 22 # node version: 22و برای تعویض بین نسخه ها از این دستور استفاده می کنیمnvm use 22 # node version: 22خب امیدوارم از این پست لذت برده و نهایت استفاده را ببرید</description>
                <category>abbas80</category>
                <author>abbas80</author>
                <pubDate>Fri, 07 Jun 2024 23:15:30 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت برنامه نویسی با طراحی سایت</title>
                <link>https://virgool.io/@m_15553325/web-development-and-design-diffrence-hlumjavo8wu1</link>
                <description>شاید در اینترنت درمورد توسعه وب جستجو کردهاید, و به دو موضوع طراحی سایت و برنامه نویسی سایت برخورده اید. تا به حال با خود فکر کرده اید تفاوت این دو در چیست, و کدام مسیر برای هدفتان مناسب است. پس لطفا ادامه مطلب را بخوانید۱ - شیوه ی کاربرنامه نویسی پیشتر با کد و نخوه نوشتن و اجرای آن کار دارد, اما طراحی سایت با دیزاین و رنگ ها و فونت و اندازه ی خط و استایل المنت های سایت سر و کار دارد. بطور کلی میتوان گفت که برنامه نویسی روشی منطقی دارد و طراحی سایت به هنر گرایش دارد.۲ - مفاهیم پایه در برنامه نویسی فرایند طرح مسئله, ىياده سازی آن و رفع اشکال است. در طراحی سایت طبق دانش هایی و الهام گرفتن المنت ها و ساختار های سایت را طراهی می کنیم. پس در نتیجه برنامه نویسی دارای مفهوم حل مسئله و طراحی سایت مفهوم خلاقیت را در بر دارد.۳ - inspect elementبرای برنامه نویسی بیشتر باید از Console برای دیباگ استفاده کرد ولی برای طراحی سایت از Element برای دیباگ بهره می برند.۴ - محیط کاریبرنامه نویسان کد های خود را در کدادیتور مثل: Vscode, sublime و Notepad++ یا IDE مانند: Visual studio, Intellij idea و Pycharm می نویسند و در مرورگر اجرا می گیرند. طراحان سایت در نرم افزار طراحی مثل: Adobe XD, Figma  Canva سایت خود را طراحی و آن را در مرورگر انتقال می دهند.۵ - زبان کامپیوترحاوا اسکریبت(JavaScript) زبانیست که برای برنامه نویسان خصوصا فرانت-اند مناسب است, و اگر بک-اند را حساب آوریم زبان های پی اچ پی(PHP), سی شارپ(C#) و پایتون را نیز می توان گنجاند. اچ تی ام ال(HTML) و سی اس اس(CSS) که زبان های نشانگر هستند برای یک طراح سایت مناسب است و خوب است آنها را بداند.خلاصهاگر می خواهید در مسایل چالش ایجاد کنید و از پس حل مسایل بر آیید, می توانید برنامه نویسی وب را دنبال کنید. و اگر فردی خلاق و علاقه مند به هنر می باشید طراحی سایت را انتخاب کنید.</description>
                <category>abbas80</category>
                <author>abbas80</author>
                <pubDate>Thu, 21 Dec 2023 09:14:37 +0330</pubDate>
            </item>
            </channel>
</rss>