<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>تعلّم Go بالاختبارات</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/</link><description>Recent content on تعلّم Go بالاختبارات</description><generator>Hugo</generator><language>ar</language><atom:link href="https://zeyadsleem.github.io/learn-go-with-tests-ar/index.xml" rel="self" type="application/rss+xml"/><item><title>تثبيت Go وتجهيز بيئة عمل منتجة</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/install-go/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/install-go/</guid><description>&lt;h1 id="تثبيت-go-وتجهيز-بيئة-عمل-منتجة"&gt;تثبيت Go وتجهيز بيئة عمل منتجة&lt;a class="anchor" href="#%d8%aa%d8%ab%d8%a8%d9%8a%d8%aa-go-%d9%88%d8%aa%d8%ac%d9%87%d9%8a%d8%b2-%d8%a8%d9%8a%d8%a6%d8%a9-%d8%b9%d9%85%d9%84-%d9%85%d9%86%d8%aa%d8%ac%d8%a9"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;تعليمات تثبيت Go الرسمية متاحة &lt;a href="https://golang.org/doc/install"&gt;هنا&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="بيئة-go"&gt;بيئة Go&lt;a class="anchor" href="#%d8%a8%d9%8a%d8%a6%d8%a9-go"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h3 id="وحدات-go-modules"&gt;وحدات Go (Modules)&lt;a class="anchor" href="#%d9%88%d8%ad%d8%af%d8%a7%d8%aa-go-modules"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;أضافت Go 1.11 &lt;a href="https://go.dev/wiki/Modules"&gt;الوحدات&lt;/a&gt;، وهي وضع البناء الافتراضي منذ Go 1.16، لذلك لا يُنصح باستخدام &lt;code&gt;GOPATH&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;تحل الوحدات مشكلات إدارة الاعتماديات (dependencies) واختيار الإصدارات والبناء القابل للتكرار (reproducible builds)، كما أنها تتيح تشغيل كود Go خارج &lt;code&gt;GOPATH&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;قليل من السياق: ماذا كان قبل الوحدات؟&lt;/strong&gt; قبل Go 1.11، كانت أدوات Go تعتمد على قاعدة اسمها &lt;code&gt;GOPATH&lt;/code&gt;، وهو متغير بيئة يشير إلى مجلد واحد على جهازك (عادة &lt;code&gt;~/go&lt;/code&gt;) يجب أن يعيش داخله كل كود Go. كل مشروع وكل اعتمادية وكل حزمة مترجَمة كانت تُخزَّن تحت ذلك المجلد. أي أنك لم تكن تستطيع إنشاء مجلد في أي مكان والبدء في كتابة Go، لأن المترجم لن يعرف كيف يحل الـ imports خارج &lt;code&gt;GOPATH&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>مرحبًا بالعالم</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/hello-world/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/hello-world/</guid><description>&lt;h1 id="مرحبا-بالعالم"&gt;مرحبًا بالعالم&lt;a class="anchor" href="#%d9%85%d8%b1%d8%ad%d8%a8%d8%a7-%d8%a8%d8%a7%d9%84%d8%b9%d8%a7%d9%84%d9%85"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/hello-world"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;من التقاليد أن يكون أول برنامج تكتبه بأي لغة جديدة هو &lt;a href="https://en.m.wikipedia.org/wiki/%22Hello,_World!%22_program"&gt;Hello, World&lt;/a&gt;.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;أنشئ مجلدًا في أي مكان تريده&lt;/li&gt;&#10;&lt;li&gt;ضع داخله ملفًا جديدًا اسمه &lt;code&gt;hello.go&lt;/code&gt; واكتب فيه الكود التالي&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, world&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ولتشغيله اكتب &lt;code&gt;go run hello.go&lt;/code&gt;.&lt;/p&gt;&#10;&lt;h2 id="كيف-يعمل-هذا"&gt;كيف يعمل هذا؟&lt;a class="anchor" href="#%d9%83%d9%8a%d9%81-%d9%8a%d8%b9%d9%85%d9%84-%d9%87%d8%b0%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;عند كتابة برنامج في Go، سيكون لديك حزمة &lt;code&gt;main&lt;/code&gt; معرَّفة بداخلها دالة &lt;code&gt;main&lt;/code&gt;. والحزم (packages) هي طريقة لتجميع كود Go المرتبط ببعضه.&lt;/p&gt;</description></item><item><title>الأعداد الصحيحة</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/integers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/integers/</guid><description>&lt;h1 id="الأعداد-الصحيحة"&gt;الأعداد الصحيحة&lt;a class="anchor" href="#%d8%a7%d9%84%d8%a3%d8%b9%d8%af%d8%a7%d8%af-%d8%a7%d9%84%d8%b5%d8%ad%d9%8a%d8%ad%d8%a9"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/integers"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;تعمل الأعداد الصحيحة كما تتوقع. لنكتب دالة &lt;code&gt;Add&lt;/code&gt; لتجربة الأمر. أنشئ ملف اختبار اسمه &lt;code&gt;adder_test.go&lt;/code&gt; واكتب فيه هذا الكود.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;ملاحظة:&lt;/strong&gt; يمكن لملفات مصدر Go أن تحتوي على &lt;code&gt;package&lt;/code&gt; واحدة فقط لكل مجلد. تأكد من تنظيم ملفاتك في حزم خاصة بها. &lt;a href="https://dave.cheney.net/2014/12/01/five-suggestions-for-setting-up-a-go-project"&gt;إليك شرحًا جيدًا لهذا.&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;ورُبما يبدو مجلد مشروعك هكذا:&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;learnGoWithTests&#10; |&#10; |-&amp;gt; helloworld&#10; | |- hello.go&#10; | |- hello_test.go&#10; |&#10; |-&amp;gt; integers&#10; | |- adder_test.go&#10; |&#10; |- go.mod&#10; |- README.md&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="اكتب-الاختبار-أولا"&gt;اكتب الاختبار أولًا&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d8%a3%d9%88%d9%84%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;integers&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;TestAdder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;expected &amp;#39;%d&amp;#39; but got &amp;#39;%d&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ستلاحظ أننا نستخدم &lt;code&gt;%d&lt;/code&gt; بدلًا من &lt;code&gt;%q&lt;/code&gt; في نصوص التنسيق، لأننا نريد طباعة عدد صحيح لا نص.&lt;/p&gt;</description></item><item><title>التكرار</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/iteration/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/iteration/</guid><description>&lt;h1 id="التكرار"&gt;التكرار&lt;a class="anchor" href="#%d8%a7%d9%84%d8%aa%d9%83%d8%b1%d8%a7%d8%b1"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/for"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;لتكرار عمل ما في Go، ستحتاج إلى &lt;code&gt;for&lt;/code&gt;. فلا توجد في Go كلمات مفتاحية مثل &lt;code&gt;while&lt;/code&gt; و&lt;code&gt;do&lt;/code&gt; و&lt;code&gt;until&lt;/code&gt;، وكل ما يمكنك استخدامه هو &lt;code&gt;for&lt;/code&gt;. وهذا شيء جيد!&lt;/p&gt;&#10;&lt;p&gt;لنكتب اختبارًا لدالة تكرر حرفًا خمس مرات.&lt;/p&gt;&#10;&lt;p&gt;لا يوجد جديد حتى الآن، لذا جرّب كتابته بنفسك للتدريب.&lt;/p&gt;&#10;&lt;h2 id="اكتب-الاختبار-أولا"&gt;اكتب الاختبار أولًا&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d8%a3%d9%88%d9%84%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;iteration&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;TestRepeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;repeated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;a&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;aaaaa&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;repeated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;expected %q but got %q&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;repeated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="جرب-تشغيل-الاختبار"&gt;جرّب تشغيل الاختبار&lt;a class="anchor" href="#%d8%ac%d8%b1%d8%a8-%d8%aa%d8%b4%d8%ba%d9%8a%d9%84-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;./repeat_test.go:6:14: undefined: Repeat&lt;/code&gt;&lt;/p&gt;</description></item><item><title>المصفوفات والشرائح</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/arrays-and-slices/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/arrays-and-slices/</guid><description>&lt;h1 id="المصفوفات-والشرائح"&gt;المصفوفات والشرائح&lt;a class="anchor" href="#%d8%a7%d9%84%d9%85%d8%b5%d9%81%d9%88%d9%81%d8%a7%d8%aa-%d9%88%d8%a7%d9%84%d8%b4%d8%b1%d8%a7%d8%a6%d8%ad"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/arrays"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;تتيح لك المصفوفات (arrays) تخزين عدة عناصر من النوع نفسه في متغير واحد بترتيب معين.&lt;/p&gt;&#10;&lt;p&gt;وعندما يكون لديك مصفوفات، فمن الشائع جدًا أن تحتاج إلى المرور عليها عنصرًا عنصرًا. لذا دعنا نستخدم &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/iteration/"&gt;معرفتنا الجديدة بـ &lt;code&gt;for&lt;/code&gt;&lt;/a&gt; لبناء دالة &lt;code&gt;Sum&lt;/code&gt; تأخذ مصفوفة أرقام وتُرجع المجموع.&lt;/p&gt;&#10;&lt;p&gt;لنستخدم مهاراتنا في التطوير الموجه بالاختبار.&lt;/p&gt;&#10;&lt;h2 id="اكتب-الاختبار-أولا"&gt;اكتب الاختبار أولًا&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d8%a3%d9%88%d9%84%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;أنشئ مجلدًا جديدًا للعمل فيه. ثم أنشئ ملفًا جديدًا اسمه &lt;code&gt;sum_test.go&lt;/code&gt; وضع فيه ما يلي:&lt;/p&gt;</description></item><item><title>Structs والـ Methods والـ Interfaces</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/structs-methods-and-interfaces/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/structs-methods-and-interfaces/</guid><description>&lt;h1 id="structs-والـ-methods-والـ-interfaces"&gt;Structs والـ Methods والـ Interfaces&lt;a class="anchor" href="#structs-%d9%88%d8%a7%d9%84%d9%80-methods-%d9%88%d8%a7%d9%84%d9%80-interfaces"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/structs"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;لنفترض أننا نحتاج إلى بعض كود الهندسة لحساب محيط مستطيل بمعلومية الارتفاع والعرض. يمكننا كتابة دالة &lt;code&gt;Perimeter(width float64, height float64)&lt;/code&gt;، حيث &lt;code&gt;float64&lt;/code&gt; مخصصة للأعداد العشرية مثل &lt;code&gt;123.45&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;ومن المفترض أن تكون دورة التطوير الموجه بالاختبار مألوفة لك تمامًا الآن.&lt;/p&gt;&#10;&lt;h2 id="اكتب-الاختبار-أولا"&gt;اكتب الاختبار أولًا&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d8%a3%d9%88%d9%84%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;TestPerimeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Perimeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;40.0&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;got&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;got %.2f want %.2f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;got&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;want&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;هل لاحظت نص التنسيق الجديد؟ الحرف &lt;code&gt;f&lt;/code&gt; مخصص لـ &lt;code&gt;float64&lt;/code&gt;، و&lt;code&gt;.2&lt;/code&gt; تعني طباعة منزلتين عشريتين.&lt;/p&gt;</description></item><item><title>المؤشرات والأخطاء</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/pointers-and-errors/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/pointers-and-errors/</guid><description>&lt;h1 id="المؤشرات-والأخطاء"&gt;المؤشرات والأخطاء&lt;a class="anchor" href="#%d8%a7%d9%84%d9%85%d8%a4%d8%b4%d8%b1%d8%a7%d8%aa-%d9%88%d8%a7%d9%84%d8%a3%d8%ae%d8%b7%d8%a7%d8%a1"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/pointers"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;تعرّفنا في القسم السابق على الـ structs التي تتيح لنا تجميع عدد من القيم المرتبطة بمفهوم واحد.&lt;/p&gt;&#10;&lt;p&gt;وقد ترغب في مرحلة ما في استخدام الـ structs لإدارة الحالة (state)، مع كشف methods تتيح للمستخدمين تغيير تلك الحالة بالطريقة التي تتحكم بها أنت.&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;قطاع التقنية المالية (fintech) يعشق Go&lt;/strong&gt; و&amp;hellip; البيتكوين؟ فلنُظهر إذن ما يمكننا بناؤه من نظام مصرفي مذهل.&lt;/p&gt;&#10;&lt;p&gt;لننشئ struct اسمه &lt;code&gt;Wallet&lt;/code&gt; يتيح لنا إيداع &lt;code&gt;Bitcoin&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>الـ Maps</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/maps/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/maps/</guid><description>&lt;h1 id="الـ-maps"&gt;الـ Maps&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-maps"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/maps"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;في &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/arrays-and-slices/"&gt;المصفوفات والشرائح&lt;/a&gt;، رأيت كيف تخزّن القيم بالترتيب. والآن سننظر إلى طريقة لتخزين العناصر حسب &lt;code&gt;key&lt;/code&gt; (مفتاح) والبحث عنها بسرعة.&lt;/p&gt;&#10;&lt;p&gt;تتيح لك الـ Maps تخزين العناصر بطريقة تشبه القاموس؛ فيمكنك التفكير في الـ &lt;code&gt;key&lt;/code&gt; كأنها الكلمة، وفي الـ &lt;code&gt;value&lt;/code&gt; كأنه التعريف. وهل توجد طريقة أفضل لتعلّم الـ Maps من بناء قاموسنا الخاص؟&lt;/p&gt;&#10;&lt;p&gt;أولًا، بافتراض أن لدينا بالفعل بعض الكلمات وتعريفاتها في القاموس، فإذا بحثنا عن كلمة ينبغي أن يُرجع لنا تعريفها.&lt;/p&gt;</description></item><item><title>حقن الاعتماديات (Dependency Injection)</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/dependency-injection/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/dependency-injection/</guid><description>&lt;h1 id="حقن-الاعتماديات-dependency-injection"&gt;حقن الاعتماديات (Dependency Injection)&lt;a class="anchor" href="#%d8%ad%d9%82%d9%86-%d8%a7%d9%84%d8%a7%d8%b9%d8%aa%d9%85%d8%a7%d8%af%d9%8a%d8%a7%d8%aa-dependency-injection"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/di"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;من المفترض أنك قرأت &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/structs-methods-and-interfaces/"&gt;فصل الـ structs&lt;/a&gt; من قبل، لأننا سنحتاج إلى بعض الفهم للـ interfaces هنا.&lt;/p&gt;&#10;&lt;p&gt;هناك &lt;em&gt;الكثير&lt;/em&gt; من سوء الفهم حول حقن الاعتماديات في أوساط البرمجة. آمل أن يوضح لك هذا الدليل أنّ:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;لا تحتاج إلى إطار عمل (framework)&lt;/li&gt;&#10;&lt;li&gt;وأنه لا يزيد تصميمك تعقيدًا&lt;/li&gt;&#10;&lt;li&gt;وأنه يسهّل الاختبار&lt;/li&gt;&#10;&lt;li&gt;وأنه يتيح لك كتابة دوال عامة رائعة.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;نريد كتابة دالة تسلّم على شخص، تمامًا كما فعلنا في فصل hello-world، لكننا هذه المرة سنختبر &lt;em&gt;الطباعة الفعلية&lt;/em&gt;.&lt;/p&gt;</description></item><item><title>الـ Mocking</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/mocking/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/mocking/</guid><description>&lt;h1 id="الـ-mocking"&gt;الـ Mocking&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-mocking"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/mocking"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;طُلب منك كتابة برنامج يعدّ تنازليًا من 3، ويطبع كل رقم في سطر جديد (مع توقف لمدة ثانية واحدة)، وعندما يصل إلى الصفر يطبع &amp;ldquo;Go!&amp;rdquo; ويخرج.&lt;/p&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;3&#10;2&#10;1&#10;Go!&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;سنعالج هذا بكتابة دالة اسمها &lt;code&gt;Countdown&lt;/code&gt; ثم نضعها داخل برنامج &lt;code&gt;main&lt;/code&gt; ليصبح الأمر هكذا:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nf"&gt;Countdown&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ومع أن هذا برنامج بسيط للغاية، فإن اختباره اختبارًا كاملًا سيقتضي منا كما في كل مرة اتباع منهج &lt;em&gt;تكراري&lt;/em&gt; و_موجه بالاختبار_.&lt;/p&gt;</description></item><item><title>التزامن (Concurrency)</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/concurrency/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/concurrency/</guid><description>&lt;h1 id="التزامن-concurrency"&gt;التزامن (Concurrency)&lt;a class="anchor" href="#%d8%a7%d9%84%d8%aa%d8%b2%d8%a7%d9%85%d9%86-concurrency"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/concurrency"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;إليك البداية: كتب زميل لك دالة اسمها &lt;code&gt;CheckWebsites&lt;/code&gt; تفحص حالة قائمة من عناوين URL.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;concurrency&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WebsiteChecker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;CheckWebsites&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WebsiteChecker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;wc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;تُرجع الدالة خريطة (map) تربط كل عنوان URL تم فحصه بقيمة منطقية (boolean): &lt;code&gt;true&lt;/code&gt; لاستجابة جيدة، و&lt;code&gt;false&lt;/code&gt; لاستجابة سيئة.&lt;/p&gt;</description></item><item><title>الـ Select</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/select/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/select/</guid><description>&lt;h1 id="الـ-select"&gt;الـ Select&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-select"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/select"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;طُلب منك أن تكتب دالة اسمها &lt;code&gt;WebsiteRacer&lt;/code&gt; تأخذ رابطين (URLs) و&amp;quot;تتسابق&amp;quot; بينهما بإرسال طلب HTTP GET إلى كل منهما، ثم تُرجع الرابط الذي عاد أولًا. وإذا لم يعد أي منهما خلال 10 ثوانٍ، فعليها أن تُرجع &lt;code&gt;error&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;ولهذا سنستخدم:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;net/http&lt;/code&gt; لإجراء استدعاءات HTTP.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;net/http/httptest&lt;/code&gt; لمساعدتنا في اختبارها.&lt;/li&gt;&#10;&lt;li&gt;الـ goroutines.&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;select&lt;/code&gt; لمزامنة العمليات.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="اكتب-الاختبار-أولا"&gt;اكتب الاختبار أولًا&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d8%a3%d9%88%d9%84%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;لنبدأ بشيء بسيط (naive) لننطلق منه.&lt;/p&gt;</description></item><item><title>الـ Reflection</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/reflection/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/reflection/</guid><description>&lt;h1 id="الـ-reflection"&gt;الـ Reflection&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-reflection"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/reflection"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://x.com/peterbourgon/status/1011403901419937792?s=09"&gt;من X&lt;/a&gt;&lt;/p&gt;&#10;&lt;blockquote class=''&gt;&#10;&lt;p&gt;تحدي golang: اكتب دالة &lt;code&gt;walk(x interface{}, fn func(string))&lt;/code&gt; تأخذ struct اسمه &lt;code&gt;x&lt;/code&gt; وتستدعي &lt;code&gt;fn&lt;/code&gt; على كل حقول النصوص الموجودة بداخله. مستوى الصعوبة: العودية.&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;p&gt;لفعل ذلك سنحتاج إلى استخدام &lt;em&gt;الـ Reflection&lt;/em&gt;.&lt;/p&gt;&#10;&lt;blockquote class=''&gt;&#10;&lt;p&gt;الـ Reflection في الحوسبة هو قدرة برنامج على فحص بنيته الخاصة، ولا سيما عبر الأنواع؛ وهو شكل من أشكال البرمجة الفوقية (metaprogramming). وهو أيضًا مصدر كبير للحيرة.&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;p&gt;من &lt;a href="https://blog.golang.org/laws-of-reflection"&gt;مدونة Go: الـ Reflection&lt;/a&gt;&lt;/p&gt;</description></item><item><title>الـ Sync</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/sync/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/sync/</guid><description>&lt;h1 id="الـ-sync"&gt;الـ Sync&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-sync"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/sync"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;نريد أن نصنع عدّادًا (counter) يمكن استخدامه بأمان في الـ concurrency.&lt;/p&gt;&#10;&lt;p&gt;سنبدأ بعدّاد غير آمن ونتحقق من أن سلوكه سليم في بيئة أحادية الـ thread.&lt;/p&gt;&#10;&lt;p&gt;ثم نستعرض عدم أمانه عبر اختبار تُحاول فيه عدة goroutines استخدام العدّاد في الوقت نفسه، ثم نصلح المشكلة.&lt;/p&gt;&#10;&lt;h2 id="اكتب-الاختبار-أولا"&gt;اكتب الاختبار أولًا&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d8%a3%d9%88%d9%84%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;نريد أن تمنحنا واجهة برمجتنا (API) method لزيادة العدّاد ثم استرجاع قيمته.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;TestCounter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;incrementing the counter 3 times leaves it at 3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Inc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Inc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Inc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;got %d, want %d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="جرب-تشغيل-الاختبار"&gt;جرّب تشغيل الاختبار&lt;a class="anchor" href="#%d8%ac%d8%b1%d8%a8-%d8%aa%d8%b4%d8%ba%d9%8a%d9%84-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;pre tabindex="0"&gt;&lt;code&gt;./sync_test.go:9:14: undefined: Counter&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="اكتب-أصغر-قدر-من-الكود-ليعمل-الاختبار-وافحص-مخرجاته-الفاشلة"&gt;اكتب أصغر قدر من الكود ليعمل الاختبار وافحص مخرجاته الفاشلة&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a3%d8%b5%d8%ba%d8%b1-%d9%82%d8%af%d8%b1-%d9%85%d9%86-%d8%a7%d9%84%d9%83%d9%88%d8%af-%d9%84%d9%8a%d8%b9%d9%85%d9%84-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d9%88%d8%a7%d9%81%d8%ad%d8%b5-%d9%85%d8%ae%d8%b1%d8%ac%d8%a7%d8%aa%d9%87-%d8%a7%d9%84%d9%81%d8%a7%d8%b4%d9%84%d8%a9"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;لنعرّف &lt;code&gt;Counter&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>الـ Context</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/context/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/context/</guid><description>&lt;h1 id="الـ-context"&gt;الـ Context&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-context"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/context"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;كثيرًا ما تُطلق البرمجيات عمليات طويلة الأمد وشرهة للموارد (وغالبًا في صورة goroutines). وإذا أُلغيت العملية التي تسببت في ذلك أو فشلت لسبب ما، فستحتاج إلى إيقاف هذه العمليات بطريقة متسقة في كل أنحاء تطبيقك.&lt;/p&gt;&#10;&lt;p&gt;وإذا لم تدِر ذلك، فقد يبدأ تطبيقك الـ Go السريع الذي تفتخر به في الظهور بمشكلات أداء يصعب تتبعها.&lt;/p&gt;&#10;&lt;p&gt;في هذا الفصل سنستخدم حزمة &lt;code&gt;context&lt;/code&gt; لمساعدتنا في إدارة العمليات طويلة الأمد.&lt;/p&gt;</description></item><item><title>مقدمة إلى الاختبارات القائمة على الخصائص (Property Based Tests)</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/roman-numerals/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/roman-numerals/</guid><description>&lt;h1 id="الأرقام-الرومانية"&gt;الأرقام الرومانية&lt;a class="anchor" href="#%d8%a7%d9%84%d8%a3%d8%b1%d9%82%d8%a7%d9%85-%d8%a7%d9%84%d8%b1%d9%88%d9%85%d8%a7%d9%86%d9%8a%d8%a9"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/roman-numerals"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;قد تطلب بعض الشركات منك أداء &lt;a href="http://codingdojo.org/kata/RomanNumerals/"&gt;تمرين الأرقام الرومانية (Roman Numeral Kata)&lt;/a&gt; ضمن عملية المقابلة. وسيوضح لك هذا الفصل كيف تتعامل معه مستعينًا بالتطوير الموجه بالاختبار (TDD).&lt;/p&gt;&#10;&lt;p&gt;سنكتب دالة تحوّل &lt;a href="https://en.wikipedia.org/wiki/Arabic_numerals"&gt;عددًا عربيًا&lt;/a&gt; (الأعداد من 0 إلى 9) إلى رقم روماني.&lt;/p&gt;&#10;&lt;p&gt;إن لم تكن قد سمعت عن &lt;a href="https://en.wikipedia.org/wiki/Roman_numerals"&gt;الأرقام الرومانية&lt;/a&gt;، فهي الطريقة التي كان الرومان يكتبون بها الأعداد.&lt;/p&gt;&#10;&lt;p&gt;تبنيها بلصق رموز بعضها ببعض، وتلك الرموز تمثل أعدادًا.&lt;/p&gt;</description></item><item><title>الرياضيات</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/math/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/math/</guid><description>&lt;h1 id="الرياضيات"&gt;الرياضيات&lt;a class="anchor" href="#%d8%a7%d9%84%d8%b1%d9%8a%d8%a7%d8%b6%d9%8a%d8%a7%d8%aa"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/math"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;مهما بلغت قوة الحواسيب الحديثة في إجراء عمليات جمع هائلة بسرعة البرق، فنادرًا ما يستخدم المطور العادي أي رياضيات في عمله. لكن ليس اليوم! سنستخدم اليوم الرياضيات لحل مشكلة &lt;em&gt;حقيقية&lt;/em&gt;. وليست رياضيات مملة - سنستخدم حساب المثلثات والمتجهات وكل تلك الأشياء التي كنت تقول دائمًا إنك لن تحتاج إليها بعد الثانوية.&lt;/p&gt;&#10;&lt;h2 id="المشكلة"&gt;المشكلة&lt;a class="anchor" href="#%d8%a7%d9%84%d9%85%d8%b4%d9%83%d9%84%d8%a9"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;تريد أن تصنع صورة SVG لساعة. لا ساعة رقمية - لا، فتلك ستكون سهلة - بل ساعة &lt;em&gt;عقارب&lt;/em&gt;، لها عقارب. ولا تبحث عن شيء فخم، فقط دالة لطيفة تأخذ &lt;code&gt;Time&lt;/code&gt; من حزمة &lt;code&gt;time&lt;/code&gt; وتُخرج SVG لساعة بكل عقاربها - الساعات والدقائق والثواني - مشيرة في الاتجاه الصحيح. فما مدى صعوبة ذلك؟&lt;/p&gt;</description></item><item><title>قراءة الملفات</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/reading-files/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/reading-files/</guid><description>&lt;h1 id="قراءة-الملفات"&gt;قراءة الملفات&lt;a class="anchor" href="#%d9%82%d8%b1%d8%a7%d8%a1%d8%a9-%d8%a7%d9%84%d9%85%d9%84%d9%81%d8%a7%d8%aa"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/reading-files"&gt;&lt;strong&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=nXts4dEJnkU"&gt;هذا فيديو لي وأنا أعمل على المسألة وأجيب عن أسئلة بث Twitch&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;في هذا الفصل سنتعلم كيف نقرأ بعض الملفات، ونستخرج منها بعض البيانات، ونفعل شيئًا مفيدًا.&lt;/p&gt;&#10;&lt;p&gt;تخيّل أنك تعمل مع صديقك على بناء برمجيات تدوين. الفكرة أن يكتب الكاتب منشوراته بصيغة markdown، مع بعض البيانات الوصفية (metadata) في أعلى الملف. وعند بدء التشغيل، سيقرأ خادم الويب مجلدًا ليبني بعض &lt;code&gt;Post&lt;/code&gt;s، ثم تستخدم دالة &lt;code&gt;NewHandler&lt;/code&gt; منفصلة تلك &lt;code&gt;Post&lt;/code&gt;s كمصدر بيانات لخادم المدونة.&lt;/p&gt;</description></item><item><title>القوالب (Templating)</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/html-templates/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/html-templates/</guid><description>&lt;h1 id="القوالب-templating"&gt;القوالب (Templating)&lt;a class="anchor" href="#%d8%a7%d9%84%d9%82%d9%88%d8%a7%d9%84%d8%a8-templating"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/blogrenderer"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;نعيش في عالم يريد فيه الجميع بناء تطبيقات ويب بأحدث صيحة رائجة من إطارات عمل الواجهات الأمامية، مبنية فوق غيغابايتات من JavaScript المُحوَّلة (transpiled)، وتعمل مع نظام بناء بالغ التعقيد؛ &lt;a href="https://quii.dev/The_Web_I_Want"&gt;لكن ربما لا يكون ذلك ضروريًا دائمًا&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;وأود القول إن معظم مطوري Go يقدّرون سلسلة أدوات بسيطة ومستقرة وسريعة، لكن عالم الواجهات الأمامية كثيرًا ما يخفق في تقديم ذلك.&lt;/p&gt;&#10;&lt;p&gt;كثيرة هي المواقع التي لا تحتاج إلى أن تكون &lt;a href="https://en.wikipedia.org/wiki/Single-page_application"&gt;تطبيقات صفحة واحدة (SPA)&lt;/a&gt;. &lt;strong&gt;فـ HTML و CSS طريقتان رائعتان لتقديم المحتوى&lt;/strong&gt;، ويمكنك استخدام Go لبناء موقع يقدّم HTML.&lt;/p&gt;</description></item><item><title>الـ Generics</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/generics/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/generics/</guid><description>&lt;h1 id="الـ-generics"&gt;الـ Generics&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-generics"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/generics"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;سيقدّم لك هذا الفصل مقدمة عن الـ generics، ويُزيل أي تحفظات قد تكون لديك تجاهها، ويعطيك فكرة عن كيفية تبسيط بعض كودك في المستقبل. وبعد قراءته ستعرف كيف تكتب:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;دالة تأخذ وسائط من نوع generic&lt;/li&gt;&#10;&lt;li&gt;نوع بيانات generic&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="دوال-المساعدة-في-اختباراتنا-assertequal-assertnotequal"&gt;دوال المساعدة في اختباراتنا (&lt;code&gt;AssertEqual&lt;/code&gt;, &lt;code&gt;AssertNotEqual&lt;/code&gt;)&lt;a class="anchor" href="#%d8%af%d9%88%d8%a7%d9%84-%d8%a7%d9%84%d9%85%d8%b3%d8%a7%d8%b9%d8%af%d8%a9-%d9%81%d9%8a-%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1%d8%a7%d8%aa%d9%86%d8%a7-assertequal-assertnotequal"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;لاستكشاف الـ generics سنكتب بعض دوال المساعدة (test helpers).&lt;/p&gt;&#10;&lt;h3 id="التحقق-من-الأعداد-الصحيحة"&gt;التحقق من الأعداد الصحيحة&lt;a class="anchor" href="#%d8%a7%d9%84%d8%aa%d8%ad%d9%82%d9%82-%d9%85%d9%86-%d8%a7%d9%84%d8%a3%d8%b9%d8%af%d8%a7%d8%af-%d8%a7%d9%84%d8%b5%d8%ad%d9%8a%d8%ad%d8%a9"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;لنبدأ بشيء بسيط ثم نتقدم خطوة بخطوة نحو هدفنا&lt;/p&gt;</description></item><item><title>إعادة زيارة المصفوفات والشرائح مع الـ Generics</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/revisiting-arrays-and-slices-with-generics/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/revisiting-arrays-and-slices-with-generics/</guid><description>&lt;h1 id="إعادة-زيارة-المصفوفات-والشرائح-مع-الـ-generics"&gt;إعادة زيارة المصفوفات والشرائح مع الـ Generics&lt;a class="anchor" href="#%d8%a5%d8%b9%d8%a7%d8%af%d8%a9-%d8%b2%d9%8a%d8%a7%d8%b1%d8%a9-%d8%a7%d9%84%d9%85%d8%b5%d9%81%d9%88%d9%81%d8%a7%d8%aa-%d9%88%d8%a7%d9%84%d8%b4%d8%b1%d8%a7%d8%a6%d8%ad-%d9%85%d8%b9-%d8%a7%d9%84%d9%80-generics"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/arrays"&gt;كود هذا الفصل تكملة لفصل المصفوفات والشرائح، وتجده هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;ألقِ نظرة على كل من &lt;code&gt;SumAll&lt;/code&gt; و&lt;code&gt;SumAllTails&lt;/code&gt; اللتين كتبناهما في &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/arrays-and-slices/"&gt;المصفوفات والشرائح&lt;/a&gt;. وإذا لم تكن تحتفظ بنسختك، فانسخ الكود من فصل &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/arrays-and-slices/"&gt;المصفوفات والشرائح&lt;/a&gt; مع الاختبارات.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Sum calculates the total from a slice of numbers.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// SumAllTails calculates the sums of all but the first number given a collection of slices.&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;SumAllTails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbersToSum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sums&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;numbersToSum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;sums&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sums&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;sums&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sums&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sums&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;هل ترى نمطًا متكررًا؟&lt;/p&gt;</description></item><item><title>مقدمة إلى اختبارات القبول</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/intro-to-acceptance-tests/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/intro-to-acceptance-tests/</guid><description>&lt;h1 id="مقدمة-إلى-اختبارات-القبول"&gt;مقدمة إلى اختبارات القبول&lt;a class="anchor" href="#%d9%85%d9%82%d8%af%d9%85%d8%a9-%d8%a5%d9%84%d9%89-%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1%d8%a7%d8%aa-%d8%a7%d9%84%d9%82%d8%a8%d9%88%d9%84"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;في &lt;code&gt;$WORK&lt;/code&gt;، كنا نواجه حاجة متكررة إلى &amp;ldquo;الإيقاف الرشيق&amp;rdquo; (graceful shutdown) لخدماتنا. فالإيقاف الرشيق يضمن أن نظامك يُنهي عمله كما ينبغي قبل إنهائه. ومثال من الحياة الواقعية: شخص يحاول إنهاء مكالمة هاتفية على نحو لائق قبل الانتقال إلى الاجتماع التالي، بدلًا من إغلاقها في منتصف الجملة.&lt;/p&gt;&#10;&lt;p&gt;سيقدّم هذا الفصل مقدمة عن الإيقاف الرشيق في سياق خادم HTTP، وعن كيفية كتابة &amp;ldquo;اختبارات القبول&amp;rdquo; (acceptance tests) لتمنح نفسك ثقة في سلوك كودك.&lt;/p&gt;</description></item><item><title>توسيع نطاق اختبارات القبول</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/scaling-acceptance-tests/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/scaling-acceptance-tests/</guid><description>&lt;h1 id="توسيع-نطاق-اختبارات-القبول"&gt;توسيع نطاق اختبارات القبول&lt;a class="anchor" href="#%d8%aa%d9%88%d8%b3%d9%8a%d8%b9-%d9%86%d8%b7%d8%a7%d9%82-%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1%d8%a7%d8%aa-%d8%a7%d9%84%d9%82%d8%a8%d9%88%d9%84"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;هذا الفصل تكملة لفصل &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/intro-to-acceptance-tests/"&gt;مقدمة إلى اختبارات القبول&lt;/a&gt;. ويمكنك العثور على &lt;a href="https://github.com/quii/go-specs-greet"&gt;كود هذا الفصل النهائي على GitHub&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p&gt;اختبارات القبول ضرورية، وهي تؤثر تأثيرًا مباشرًا في قدرتك على تطوير نظامك بثقة عبر الزمن، وبكلفة تغيير معقولة.&lt;/p&gt;&#10;&lt;p&gt;وهي أيضًا أداة بديعة تساعدك في التعامل مع الكود القديم (legacy code). فحين تواجه قاعدة كود ضعيفة بلا أي اختبارات، قاوم الرغبة في البدء بإعادة الهيكلة. واكتب بدلًا من ذلك بعض اختبارات القبول لتصنع لنفسك شبكة أمان تتيح لك تغيير داخل النظام بحرية دون التأثير في سلوكه الخارجي الوظيفي. فاختبارات القبول لا تهتم بالجودة الداخلية، لذا فهي مناسبة جدًا لهذه المواقف.&lt;/p&gt;</description></item><item><title>العمل بدون الـ Mocks والـ Stubs والـ Spies</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/working-without-mocks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/working-without-mocks/</guid><description>&lt;h1 id="العمل-بدون-الـ-mocks-والـ-stubs-والـ-spies"&gt;العمل بدون الـ Mocks والـ Stubs والـ Spies&lt;a class="anchor" href="#%d8%a7%d9%84%d8%b9%d9%85%d9%84-%d8%a8%d8%af%d9%88%d9%86-%d8%a7%d9%84%d9%80-mocks-%d9%88%d8%a7%d9%84%d9%80-stubs-%d9%88%d8%a7%d9%84%d9%80-spies"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;يتعمّق هذا الفصل في عالم الـ test doubles، ويستكشف كيف تؤثر في عملية الاختبار والتطوير. سنكشف حدود الـ mocks والـ stubs والـ spies التقليدية، ثم نقدّم نهجًا أكثر كفاءة وقابلية للتكيّف باستخدام الـ fakes والـ contracts.&lt;/p&gt;&#10;&lt;h2 id="باختصار"&gt;باختصار&lt;a class="anchor" href="#%d8%a8%d8%a7%d8%ae%d8%aa%d8%b5%d8%a7%d8%b1"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;الـ Mocks والـ spies والـ stubs تشجعك على ترميز افتراضاتك حول سلوك اعتمادياتك بشكل ارتجالي (ad-hoc) في كل اختبار.&lt;/li&gt;&#10;&lt;li&gt;وهذه الافتراضات لا يُتحقق منها عادةً إلا يدويًا، ما يهدد فائدة مجموعة اختباراتك.&lt;/li&gt;&#10;&lt;li&gt;أما الـ fakes والـ contracts فتمنحاننا طريقة أكثر استدامة لإنشاء test doubles بافتراضات مُتحقق منها، وبإعادة استخدام أفضل من البدائل الأخرى.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;هذا الفصل أطول من المعتاد، فلنأخذ نفسًا قصيرًا، ابدأ باستكشاف &lt;a href="https://github.com/quii/go-fakes-and-contracts"&gt;مستودع الأمثلة&lt;/a&gt;. وبالأخص، ألقِ نظرة على &lt;a href="https://github.com/quii/go-fakes-and-contracts/blob/main/domain/planner/planner_test.go"&gt;اختبار planner&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>قائمة تحقق إعادة الهيكلة</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/refactoring-checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/testing-fundamentals/refactoring-checklist/</guid><description>&lt;h1 id="خطوة-إعادة-الهيكلة-قائمة-تحقق-البداية"&gt;خطوة إعادة الهيكلة، قائمة تحقق البداية&lt;a class="anchor" href="#%d8%ae%d8%b7%d9%88%d8%a9-%d8%a5%d8%b9%d8%a7%d8%af%d8%a9-%d8%a7%d9%84%d9%87%d9%8a%d9%83%d9%84%d8%a9-%d9%82%d8%a7%d8%a6%d9%85%d8%a9-%d8%aa%d8%ad%d9%82%d9%82-%d8%a7%d9%84%d8%a8%d8%af%d8%a7%d9%8a%d8%a9"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;إعادة الهيكلة (refactoring) مهارة تصبح، بفعل التدريب الكافي، طبيعة ثانية سهلة في معظم الحالات.&lt;/p&gt;&#10;&lt;p&gt;وكثيرًا ما يُخلط بين هذا النشاط وتغييرات تصميمية أكبر، لكنهما منفصلان. والتمييز بين إعادة الهيكلة وغيرها من أنشطة البرمجة مفيد لأنه يتيح لي العمل بوضوح وانضباط.&lt;/p&gt;&#10;&lt;h2 id="إعادة-الهيكلة-مقابل-أنشطة-أخرى"&gt;إعادة الهيكلة مقابل أنشطة أخرى&lt;a class="anchor" href="#%d8%a5%d8%b9%d8%a7%d8%af%d8%a9-%d8%a7%d9%84%d9%87%d9%8a%d9%83%d9%84%d8%a9-%d9%85%d9%82%d8%a7%d8%a8%d9%84-%d8%a3%d9%86%d8%b4%d8%b7%d8%a9-%d8%a3%d8%ae%d8%b1%d9%89"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;إعادة الهيكلة ليست سوى تحسين للكود الموجود &lt;u&gt;دون تغيير السلوك&lt;/u&gt;؛ ولذلك لا ينبغي أن تضطر الاختبارات إلى التغيير.&lt;/p&gt;&#10;&lt;p&gt;ولهذا فهي الخطوة الثالثة في دورة التطوير الموجه بالاختبار (TDD). فبعد أن تضيف سلوكًا واختبارًا يسنده، ينبغي أن تكون إعادة الهيكلة نشاطًا لا يتطلب أي تغيير في كود اختبارك. &lt;strong&gt;أنت تفعل شيئًا آخر&lt;/strong&gt; إذا كنت &amp;ldquo;تعيد هيكلة&amp;rdquo; كود ما وتضطر إلى تغيير الاختبارات في الوقت نفسه.&lt;/p&gt;</description></item><item><title>مقدمة</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/app-intro/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/app-intro/</guid><description>&lt;h1 id="بناء-تطبيق"&gt;بناء تطبيق&lt;a class="anchor" href="#%d8%a8%d9%86%d8%a7%d8%a1-%d8%aa%d8%b7%d8%a8%d9%8a%d9%82"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;الآن، وبعد أن استوعبت — كما نأمل — قسم &lt;em&gt;أساسيات Go&lt;/em&gt;، أصبحت لديك قاعدة صلبة في أغلب ميزات لغة Go وكيفية ممارسة التطوير الموجه بالاختبار.&lt;/p&gt;&#10;&lt;p&gt;سيتناول هذا القسم القادم بناء تطبيق.&lt;/p&gt;&#10;&lt;p&gt;كل فصل سيبني على الفصل السابق، موسّعًا وظائف التطبيق كما يملي علينا مالك المنتج (product owner).&lt;/p&gt;&#10;&lt;p&gt;سنقدّم مفاهيم جديدة تساعدك على كتابة كود رائع، لكن أغلب المادة الجديدة ستكون تعرّفًا بما يمكن إنجازه باستخدام المكتبة القياسية (standard library) في Go.&lt;/p&gt;</description></item><item><title>خادم HTTP</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/http-server/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/http-server/</guid><description>&lt;h1 id="خادم-http"&gt;خادم HTTP&lt;a class="anchor" href="#%d8%ae%d8%a7%d8%af%d9%85-http"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/http-server"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;طُلب منك إنشاء خادم ويب يستطيع المستخدمون من خلاله تتبع عدد المباريات التي فاز بها اللاعبون.&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;GET /players/{name}&lt;/code&gt; ينبغي أن تُرجع رقمًا يدل على إجمالي عدد مرات الفوز&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;POST /players/{name}&lt;/code&gt; ينبغي أن تسجّل فوزًا لذلك الاسم، ويزيد العدد مع كل &lt;code&gt;POST&lt;/code&gt; تالٍ&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;سنتبع نهج التطوير الموجه بالاختبار، فنصل إلى برنامج يعمل بأسرع ما نستطيع، ثم نجري تحسينات صغيرة متكررة حتى نصل إلى الحل. وباتباعنا هذا النهج:&lt;/p&gt;</description></item><item><title>JSON والتوجيه والدمج</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/json/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/json/</guid><description>&lt;h1 id="json-والتوجيه-والدمج"&gt;JSON والتوجيه والدمج&lt;a class="anchor" href="#json-%d9%88%d8%a7%d9%84%d8%aa%d9%88%d8%ac%d9%8a%d9%87-%d9%88%d8%a7%d9%84%d8%af%d9%85%d8%ac"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/json"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/http-server/"&gt;في الفصل السابق&lt;/a&gt; أنشأنا خادم ويب لتخزين عدد المباريات التي فاز بها اللاعبون.&lt;/p&gt;&#10;&lt;p&gt;ولمالك المنتج (product owner) متطلب جديد: نقطة نهاية (endpoint) جديدة اسمها &lt;code&gt;/league&lt;/code&gt; تُرجع قائمة بكل اللاعبين المخزَّنين. وتريد أن تُعاد هذه القائمة على هيئة JSON.&lt;/p&gt;&#10;&lt;h2 id="إليك-الكود-الذي-وصلنا-إليه-حتى-الآن"&gt;إليك الكود الذي وصلنا إليه حتى الآن&lt;a class="anchor" href="#%d8%a5%d9%84%d9%8a%d9%83-%d8%a7%d9%84%d9%83%d9%88%d8%af-%d8%a7%d9%84%d8%b0%d9%8a-%d9%88%d8%b5%d9%84%d9%86%d8%a7-%d8%a5%d9%84%d9%8a%d9%87-%d8%ad%d8%aa%d9%89-%d8%a7%d9%84%d8%a2%d9%86"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// server.go&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PlayerStore&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nf"&gt;GetPlayerScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nf"&gt;RecordWin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PlayerServer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PlayerStore&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;PlayerServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ServeHTTP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TrimPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/players/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MethodPost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;processWin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MethodGet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;PlayerServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;showScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPlayerScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fprint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;PlayerServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;processWin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RecordWin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusAccepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// in_memory_player_store.go&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;NewInMemoryPlayerStore&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;InMemoryPlayerStore&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;InMemoryPlayerStore&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{}}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;InMemoryPlayerStore&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;InMemoryPlayerStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;RecordWin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;InMemoryPlayerStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;GetPlayerScore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// main.go&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;PlayerServer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;NewInMemoryPlayerStore&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;:5000&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;يمكنك العثور على الاختبارات المقابلة في الرابط أعلى الفصل.&lt;/p&gt;</description></item><item><title>الـ IO والترتيب</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/io/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/io/</guid><description>&lt;h1 id="الإدخال-والإخراج-والترتيب"&gt;الإدخال والإخراج والترتيب&lt;a class="anchor" href="#%d8%a7%d9%84%d8%a5%d8%af%d8%ae%d8%a7%d9%84-%d9%88%d8%a7%d9%84%d8%a5%d8%ae%d8%b1%d8%a7%d8%ac-%d9%88%d8%a7%d9%84%d8%aa%d8%b1%d8%aa%d9%8a%d8%a8"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/io"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/json/"&gt;في الفصل السابق&lt;/a&gt; واصلنا تطوير تطبيقنا بإضافة نقطة نهاية (endpoint) جديدة هي &lt;code&gt;/league&lt;/code&gt;. وفي الطريق تعلّمنا كيفية التعامل مع JSON، وتضمين الأنواع (embedding types)، والتوجيه (routing).&lt;/p&gt;&#10;&lt;p&gt;مالكة المنتج (product owner) منزعجة بعض الشيء لأن البرنامج يفقد النتائج عند إعادة تشغيل الخادم؛ والسبب أن تنفيذنا للمخزن (store) موجود في الذاكرة. وهي أيضًا غير راضية لأننا لم نستنتج أن نقطة النهاية &lt;code&gt;/league&lt;/code&gt; ينبغي أن تُرجع اللاعبين مرتبين حسب عدد الانتصارات!&lt;/p&gt;</description></item><item><title>سطر الأوامر وهيكل المشروع</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/command-line/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/command-line/</guid><description>&lt;h1 id="سطر-الأوامر-وهيكل-المشروع"&gt;سطر الأوامر وهيكل المشروع&lt;a class="anchor" href="#%d8%b3%d8%b7%d8%b1-%d8%a7%d9%84%d8%a3%d9%88%d8%a7%d9%85%d8%b1-%d9%88%d9%87%d9%8a%d9%83%d9%84-%d8%a7%d9%84%d9%85%d8%b4%d8%b1%d9%88%d8%b9"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/command-line"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;يريد مالك المنتج (product owner) الآن أن &lt;em&gt;يتحوّل&lt;/em&gt; (pivot) بتقديم تطبيق ثانٍ - تطبيق سطر أوامر.&lt;/p&gt;&#10;&lt;p&gt;وفي الوقت الحالي، سيكفي أن يكون قادرًا على تسجيل فوز لاعب عندما يكتب المستخدم &lt;code&gt;Ruth wins&lt;/code&gt;. والقصد أن يصبح في النهاية أداة تساعد المستخدمين على لعب البوكر.&lt;/p&gt;&#10;&lt;p&gt;ويريد مالك المنتج أن تكون قاعدة البيانات مشتركة بين التطبيقين، حتى يتحدّث الدوري وفق الانتصارات المسجّلة في التطبيق الجديد.&lt;/p&gt;</description></item><item><title>الوقت</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/time/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/time/</guid><description>&lt;h1 id="الوقت"&gt;الوقت&lt;a class="anchor" href="#%d8%a7%d9%84%d9%88%d9%82%d8%aa"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/time"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;يريد منّا مالك المنتج (product owner) أن نوسّع وظائف تطبيق سطر الأوامر الخاص بنا بمساعدة مجموعة من الأشخاص على لعب البوكر تكساس هولدم (Texas-Holdem Poker).&lt;/p&gt;&#10;&lt;h2 id="معلومات-بالقدر-الكافي-عن-البوكر"&gt;معلومات بالقدر الكافي عن البوكر&lt;a class="anchor" href="#%d9%85%d8%b9%d9%84%d9%88%d9%85%d8%a7%d8%aa-%d8%a8%d8%a7%d9%84%d9%82%d8%af%d8%b1-%d8%a7%d9%84%d9%83%d8%a7%d9%81%d9%8a-%d8%b9%d9%86-%d8%a7%d9%84%d8%a8%d9%88%d9%83%d8%b1"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;لن تحتاج إلى معرفة الكثير عن البوكر، يكفي أن تعرف أنه في فترات زمنية معينة يجب إبلاغ جميع اللاعبين بقيمة &amp;ldquo;الرهان الإجباري&amp;rdquo; (blind) المتزايدة باطراد.&lt;/p&gt;&#10;&lt;p&gt;سيساعدنا تطبيقنا على تتبّع موعد ارتفاع قيمة الرهان الإجباري، ومقدارها الجديد.&lt;/p&gt;</description></item><item><title>إعادة زيارة الوقت مع testing/synctest</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/revisiting-time-with-synctest/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/revisiting-time-with-synctest/</guid><description>&lt;h1 id="إعادة-زيارة-الوقت-مع-testingsynctest"&gt;إعادة زيارة الوقت مع testing/synctest&lt;a class="anchor" href="#%d8%a5%d8%b9%d8%a7%d8%af%d8%a9-%d8%b2%d9%8a%d8%a7%d8%b1%d8%a9-%d8%a7%d9%84%d9%88%d9%82%d8%aa-%d9%85%d8%b9-testingsynctest"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/synctest"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;في &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/time/"&gt;فصل الوقت&lt;/a&gt; منحنا تطبيق البوكر الطرفي (poker CLI) القدرة على جدولة تنبيهات &amp;ldquo;الرهان الأعمى يرتفع الآن&amp;rdquo; باستخدام &lt;code&gt;time.AfterFunc&lt;/code&gt;. كان اختبار هذا صعبًا: فـ &lt;code&gt;time.AfterFunc&lt;/code&gt; يشغّل دالة الاستدعاء (callback) في goroutine خاصة به بعد مرور مدة حقيقية، ولا يمكنك مقارنة الدوال في Go، لذا لم نستطع بسهولة فحص ما تمت جدولته.&lt;/p&gt;&#10;&lt;p&gt;حللنا ذلك بأداة مألوفة: حقن الاعتماديات (dependency injection). عرّفنا واجهة (interface) اسمها &lt;code&gt;BlindAlerter&lt;/code&gt;، وفي اختباراتنا استبدلنا التنفيذ الحقيقي بـ spy يسجّل فقط ما طُلب منه جدولته، هكذا تقريبًا:&lt;/p&gt;</description></item><item><title>الـ WebSockets</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/websockets/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/websockets/</guid><description>&lt;h1 id="الـ-websockets"&gt;الـ WebSockets&lt;a class="anchor" href="#%d8%a7%d9%84%d9%80-websockets"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/websockets"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;في هذا الفصل سنتعلّم كيف نستخدم WebSockets لتحسين تطبيقنا.&lt;/p&gt;&#10;&lt;h2 id="مراجعة-سريعة-للمشروع"&gt;مراجعة سريعة للمشروع&lt;a class="anchor" href="#%d9%85%d8%b1%d8%a7%d8%ac%d8%b9%d8%a9-%d8%b3%d8%b1%d9%8a%d8%b9%d8%a9-%d9%84%d9%84%d9%85%d8%b4%d8%b1%d9%88%d8%b9"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;لدينا تطبيقان في قاعدة كود البوكر&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;em&gt;تطبيق سطر الأوامر&lt;/em&gt;. يطلب من المستخدم إدخال عدد اللاعبين في اللعبة. ومنذ تلك اللحظة يبلّغ اللاعبين بقيمة &amp;ldquo;الرهان الإجباري&amp;rdquo; (blind bet) التي تزداد بمرور الوقت. ويمكن للمستخدم في أي لحظة إدخال &lt;code&gt;&amp;quot;{Playername} wins&amp;quot;&lt;/code&gt; لإنهاء اللعبة وتسجيل الفائز في مخزن (store).&lt;/li&gt;&#10;&lt;li&gt;&lt;em&gt;تطبيق الويب&lt;/em&gt;. يتيح للمستخدمين تسجيل الفائزين في الألعاب ويعرض جدول الترتيب. ويتشارك المخزن نفسه مع تطبيق سطر الأوامر.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="الخطوات-التالية"&gt;الخطوات التالية&lt;a class="anchor" href="#%d8%a7%d9%84%d8%ae%d8%b7%d9%88%d8%a7%d8%aa-%d8%a7%d9%84%d8%aa%d8%a7%d9%84%d9%8a%d8%a9"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;مالكة المنتج (product owner) سعيدة جدًا بتطبيق سطر الأوامر، لكنها تفضّل لو استطعنا نقل تلك الوظائف إلى المتصفح. فهي تتخيّل صفحة ويب بها مربع نص يتيح للمستخدم إدخال عدد اللاعبين، وعندما يرسل النموذج (form) تعرض الصفحة قيمة الرهان الإجباري وتحدّثها تلقائيًا عند الحاجة. وكما في تطبيق سطر الأوامر، يمكن للمستخدم إعلان الفائز فيُحفظ في قاعدة البيانات.&lt;/p&gt;</description></item><item><title>تنفيذ أوامر النظام (OS Exec)</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/os-exec/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/os-exec/</guid><description>&lt;h1 id="تنفيذ-أوامر-النظام-os-exec"&gt;تنفيذ أوامر النظام (OS Exec)&lt;a class="anchor" href="#%d8%aa%d9%86%d9%81%d9%8a%d8%b0-%d8%a3%d9%88%d8%a7%d9%85%d8%b1-%d8%a7%d9%84%d9%86%d8%b8%d8%a7%d9%85-os-exec"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/q-and-a/os-exec"&gt;يمكنك العثور على كل الكود هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;يسأل &lt;a href="https://www.reddit.com/user/keith6014"&gt;keith6014&lt;/a&gt; على &lt;a href="https://www.reddit.com/r/golang/comments/aaz8ji/testdata_and_function_setup_help/"&gt;reddit&lt;/a&gt;&lt;/p&gt;&#10;&lt;blockquote class=''&gt;&#10;&lt;p&gt;أُنفّذ أمرًا باستخدام os/exec.Command() يُنتج بيانات XML. وسيُنفَّذ هذا الأمر داخل دالة اسمها GetData().&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;blockquote class=''&gt;&#10;&lt;p&gt;ولكي أختبر GetData()، لديّ بعض بيانات الاختبار (testdata) التي أنشأتها.&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;blockquote class=''&gt;&#10;&lt;p&gt;في ملف _test.go لديّ TestGetData يستدعي GetData()، لكنه سيستخدم os.exec، وأريد بدلًا من ذلك أن يستخدم بيانات اختباري.&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;blockquote class=''&gt;&#10;&lt;p&gt;فما الطريقة الجيدة لتحقيق ذلك؟ هل ينبغي عند استدعاء GetData أن يكون لديّ وضع &amp;ldquo;test&amp;rdquo; بعلامة ما ليقرأ ملفًا، مثل GetData(mode string)؟&lt;/p&gt;</description></item><item><title>أنواع الأخطاء</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/error-types/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/error-types/</guid><description>&lt;h1 id="أنواع-الأخطاء"&gt;أنواع الأخطاء&lt;a class="anchor" href="#%d8%a3%d9%86%d9%88%d8%a7%d8%b9-%d8%a7%d9%84%d8%a3%d8%ae%d8%b7%d8%a7%d8%a1"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/q-and-a/error-types"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;إنشاء أنواع خاصة بك للأخطاء يمكن أن يكون طريقة أنيقة لترتيب كودك، وتجعل كودك أسهل استخدامًا واختبارًا.&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;يسأل Pedro على Gopher Slack&lt;/p&gt;&#10;&lt;blockquote class=''&gt;&#10;&lt;p&gt;إذا كنت أنشئ خطأ مثل &lt;code&gt;fmt.Errorf(&amp;quot;%s must be foo, got %s&amp;quot;, bar, baz)&lt;/code&gt;، فهل هناك طريقة لاختبار التساوي دون مقارنة قيمة النص؟&lt;/p&gt;&#10;&lt;/blockquote&gt;&lt;p&gt;لنصنع دالة تساعدنا على استكشاف هذه الفكرة.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// DumbGetter will get the string body of url if it gets a 200&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;DumbGetter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;problem fetching from %s, %v&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusCode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;did not get 200 from %s, got %d&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusCode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ignoring err for brevity&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;&#9;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ليس نادرًا أن تكتب دالة قد تفشل لأسباب مختلفة، ونريد أن نتأكد أننا نتعامل مع كل سيناريو بشكل صحيح.&lt;/p&gt;</description></item><item><title>قارئ يراعي الـ Context</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/context-aware-reader/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/context-aware-reader/</guid><description>&lt;h1 id="قارئ-يراعي-الـ-context"&gt;قارئ يراعي الـ Context&lt;a class="anchor" href="#%d9%82%d8%a7%d8%b1%d8%a6-%d9%8a%d8%b1%d8%a7%d8%b9%d9%8a-%d8%a7%d9%84%d9%80-context"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/q-and-a/context-aware-reader"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;يوضح هذا الفصل كيف نطوّر بالاختبار أولًا &lt;code&gt;io.Reader&lt;/code&gt; يراعي الـ context، كما كتبه Mat Ryer وDavid Hernandez في &lt;a href="https://pace.dev/blog/2020/02/03/context-aware-ioreader-for-golang-by-mat-ryer"&gt;مدونة The Pace Dev&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="قارئ-يراعي-الـ-context-1"&gt;قارئ يراعي الـ context؟&lt;a class="anchor" href="#%d9%82%d8%a7%d8%b1%d8%a6-%d9%8a%d8%b1%d8%a7%d8%b9%d9%8a-%d8%a7%d9%84%d9%80-context-1"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;أولًا، مقدمة سريعة عن &lt;code&gt;io.Reader&lt;/code&gt;.&lt;/p&gt;&#10;&lt;p&gt;إذا كنت قد قرأت فصولًا أخرى في هذا الكتاب فستكون قد صادفت &lt;code&gt;io.Reader&lt;/code&gt; عند فتح الملفات وترميز JSON ومهام شائعة أخرى متنوعة. إنه تجريد بسيط لقراءة البيانات من &lt;em&gt;شيء ما&lt;/em&gt;&lt;/p&gt;</description></item><item><title>إعادة زيارة معالجات HTTP</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/http-handlers-revisited/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/questions-and-answers/http-handlers-revisited/</guid><description>&lt;h1 id="إعادة-زيارة-معالجات-http"&gt;إعادة زيارة معالجات HTTP&lt;a class="anchor" href="#%d8%a5%d8%b9%d8%a7%d8%af%d8%a9-%d8%b2%d9%8a%d8%a7%d8%b1%d8%a9-%d9%85%d8%b9%d8%a7%d9%84%d8%ac%d8%a7%d8%aa-http"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/quii/learn-go-with-tests/tree/main/q-and-a/http-handlers-revisited"&gt;يمكنك العثور على كل كود هذا الفصل هنا&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;يحتوي هذا الكتاب بالفعل على فصل عن &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/build-an-application/http-server/"&gt;اختبار معالج HTTP&lt;/a&gt;، لكن هذا الفصل سيقدّم نقاشًا أوسع حول تصميم المعالجات، ليكون اختبارها بسيطًا.&lt;/p&gt;&#10;&lt;p&gt;سنلقي نظرة على مثال واقعي، وكيف يمكننا تحسين طريقة تصميمه بتطبيق مبادئ مثل مبدأ المسؤولية الواحدة (single responsibility principle) وفصل الاهتمامات (separation of concerns). ويمكن تحقيق هذه المبادئ باستخدام &lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/structs-methods-and-interfaces/"&gt;الواجهات (interfaces)&lt;/a&gt; و&lt;a href="https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/go-fundamentals/dependency-injection/"&gt;حقن الاعتماديات (dependency injection)&lt;/a&gt;. وبهذا سنوضح أن اختبار المعالجات أمر بسيط للغاية في الحقيقة.&lt;/p&gt;</description></item><item><title>لماذا اختبارات الوحدة وكيف تجعلها تعمل لصالحك</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/why/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/why/</guid><description>&lt;h1 id="لماذا-اختبارات-الوحدة-وكيف-تجعلها-تعمل-لصالحك"&gt;لماذا اختبارات الوحدة وكيف تجعلها تعمل لصالحك&lt;a class="anchor" href="#%d9%84%d9%85%d8%a7%d8%b0%d8%a7-%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1%d8%a7%d8%aa-%d8%a7%d9%84%d9%88%d8%ad%d8%af%d8%a9-%d9%88%d9%83%d9%8a%d9%81-%d8%aa%d8%ac%d8%b9%d9%84%d9%87%d8%a7-%d8%aa%d8%b9%d9%85%d9%84-%d9%84%d8%b5%d8%a7%d9%84%d8%ad%d9%83"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Kwtit8ZEK7U"&gt;إليك رابطًا لفيديو أتحدث فيه عن هذا الموضوع&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;وإذا لم تكن من محبي الفيديو، فإليك نسخة مكتوبة ومطوّلة عن الموضوع.&lt;/p&gt;&#10;&lt;h2 id="البرمجيات"&gt;البرمجيات&lt;a class="anchor" href="#%d8%a7%d9%84%d8%a8%d8%b1%d9%85%d8%ac%d9%8a%d8%a7%d8%aa"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;وعد البرمجيات هو أنها قابلة للتغيير. ولهذا تُسمى &lt;em&gt;soft&lt;/em&gt; ware؛ فهي طيّعة مقارنة بالعتاد (hardware). وينبغي أن يكون فريق الهندسة العظيم أصلًا مذهلًا للشركة، إذ يكتب أنظمة تستطيع أن تتطور مع الأعمال لتواصل تقديم القيمة.&lt;/p&gt;&#10;&lt;p&gt;فلماذا نحن بهذا السوء في ذلك؟ كم مشروعًا تسمع عنه يفشل فشلًا تامًا؟ أو يصبح &amp;ldquo;قديمًا&amp;rdquo; (legacy) ولا بد من إعادة كتابته بالكامل (وكثيرًا ما تفشل إعادة الكتابة أيضًا!)&lt;/p&gt;</description></item><item><title>الأنماط المضادة (Anti-patterns)</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/anti-patterns/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/anti-patterns/</guid><description>&lt;h1 id="الأنماط-المضادة-anti-patterns"&gt;الأنماط المضادة (Anti-patterns)&lt;a class="anchor" href="#%d8%a7%d9%84%d8%a3%d9%86%d9%85%d8%a7%d8%b7-%d8%a7%d9%84%d9%85%d8%b6%d8%a7%d8%af%d8%a9-anti-patterns"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;من وقت لآخر، تحتاج إلى مراجعة تقنياتك في التطوير الموجه بالاختبار (TDD) وتذكير نفسك بالسلوكيات التي ينبغي تجنبها.&lt;/p&gt;&#10;&lt;p&gt;عملية TDD بسيطة من حيث المفهوم، لكنك ستجدها وأنت تمارسها تتحدى مهاراتك في التصميم. &lt;strong&gt;لا تظن أن هذا يعني أن TDD صعب، فالصعب هو التصميم!&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;يسرد هذا الفصل عددًا من الأنماط المضادة في TDD والاختبار، وكيفية علاجها.&lt;/p&gt;&#10;&lt;h2 id="عدم-ممارسة-tdd-إطلاقا"&gt;عدم ممارسة TDD إطلاقًا&lt;a class="anchor" href="#%d8%b9%d8%af%d9%85-%d9%85%d9%85%d8%a7%d8%b1%d8%b3%d8%a9-tdd-%d8%a5%d8%b7%d9%84%d8%a7%d9%82%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;بالطبع، من الممكن كتابة برمجيات رائعة دون TDD، لكن كثيرًا من المشكلات التي رأيتها في تصميم الكود وجودة الاختبارات كان سيكون من الصعب جدًا الوصول إليها لو اتُّبع نهج منضبط في TDD.&lt;/p&gt;</description></item><item><title>المساهمة</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/contributing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/contributing/</guid><description>&lt;h1 id="المساهمة"&gt;المساهمة&lt;a class="anchor" href="#%d8%a7%d9%84%d9%85%d8%b3%d8%a7%d9%87%d9%85%d8%a9"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;المساهمات مرحّب بها جدًا. وآمل أن يصبح هذا بيتًا رائعًا لأدلة تعلّم Go عبر كتابة الاختبارات. فكّر في إرسال PR أو إنشاء issue، ويمكنك فعل ذلك &lt;a href="https://github.com/quii/learn-go-with-tests/issues"&gt;من هنا&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h2 id="ما-نبحث-عنه"&gt;ما نبحث عنه&lt;a class="anchor" href="#%d9%85%d8%a7-%d9%86%d8%a8%d8%ad%d8%ab-%d8%b9%d9%86%d9%87"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;تعليم ميزات Go (مثل أشياء كهذه: &lt;code&gt;if&lt;/code&gt; و&lt;code&gt;select&lt;/code&gt; والـ structs والـ methods وغيرها).&lt;/li&gt;&#10;&lt;li&gt;عرض وظائف مثيرة للاهتمام داخل المكتبة القياسية. وإظهار كم هو سهل اتباع TDD لخادم HTTP مثلًا.&lt;/li&gt;&#10;&lt;li&gt;إظهار كيف يمكن لأدوات Go، مثل قياس الأداء وكاشفات التسابق (race detectors) وغيرها، أن تساعدك في الوصول إلى برمجيات رائعة.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;وإذا لم تكن واثقًا من قدرتك على تقديم دليلك الخاص، فإن إنشاء issue لشيء تريد تعلّمه يظل مساهمة قيّمة.&lt;/p&gt;</description></item><item><title>قالب الفصل</title><link>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/template/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://zeyadsleem.github.io/learn-go-with-tests-ar/docs/meta/template/</guid><description>&lt;h1 id="قالب-الفصل"&gt;قالب الفصل&lt;a class="anchor" href="#%d9%82%d8%a7%d9%84%d8%a8-%d8%a7%d9%84%d9%81%d8%b5%d9%84"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;مقدمة موجزة&lt;/p&gt;&#10;&lt;h2 id="اكتب-الاختبار-أولا"&gt;اكتب الاختبار أولًا&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d8%a3%d9%88%d9%84%d8%a7"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h2 id="جرب-تشغيل-الاختبار"&gt;جرّب تشغيل الاختبار&lt;a class="anchor" href="#%d8%ac%d8%b1%d8%a8-%d8%aa%d8%b4%d8%ba%d9%8a%d9%84-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h2 id="اكتب-أصغر-قدر-من-الكود-ليعمل-الاختبار-وافحص-مخرجاته-الفاشلة"&gt;اكتب أصغر قدر من الكود ليعمل الاختبار وافحص مخرجاته الفاشلة&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d8%a3%d8%b5%d8%ba%d8%b1-%d9%82%d8%af%d8%b1-%d9%85%d9%86-%d8%a7%d9%84%d9%83%d9%88%d8%af-%d9%84%d9%8a%d8%b9%d9%85%d9%84-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1-%d9%88%d8%a7%d9%81%d8%ad%d8%b5-%d9%85%d8%ae%d8%b1%d8%ac%d8%a7%d8%aa%d9%87-%d8%a7%d9%84%d9%81%d8%a7%d8%b4%d9%84%d8%a9"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h2 id="اكتب-كودا-كافيا-لنجاح-الاختبار"&gt;اكتب كودًا كافيًا لنجاح الاختبار&lt;a class="anchor" href="#%d8%a7%d9%83%d8%aa%d8%a8-%d9%83%d9%88%d8%af%d8%a7-%d9%83%d8%a7%d9%81%d9%8a%d8%a7-%d9%84%d9%86%d8%ac%d8%a7%d8%ad-%d8%a7%d9%84%d8%a7%d8%ae%d8%aa%d8%a8%d8%a7%d8%b1"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h2 id="إعادة-الهيكلة"&gt;إعادة الهيكلة&lt;a class="anchor" href="#%d8%a5%d8%b9%d8%a7%d8%af%d8%a9-%d8%a7%d9%84%d9%87%d9%8a%d9%83%d9%84%d8%a9"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h2 id="كرر-مع-متطلبات-جديدة"&gt;كرّر مع متطلبات جديدة&lt;a class="anchor" href="#%d9%83%d8%b1%d8%b1-%d9%85%d8%b9-%d9%85%d8%aa%d8%b7%d9%84%d8%a8%d8%a7%d8%aa-%d8%ac%d8%af%d9%8a%d8%af%d8%a9"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;h2 id="الخلاصة"&gt;الخلاصة&lt;a class="anchor" href="#%d8%a7%d9%84%d8%ae%d9%84%d8%a7%d8%b5%d8%a9"&gt;&lt;/a&gt;&lt;/h2&gt;</description></item></channel></rss>