<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Perajit</title>
    <description>The latest articles on Forem by Perajit (@perajit).</description>
    <link>https://forem.com/perajit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3889814%2F9fd0b414-7ecd-47a0-9a41-67960fda3f4d.png</url>
      <title>Forem: Perajit</title>
      <link>https://forem.com/perajit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/perajit"/>
    <language>en</language>
    <item>
      <title>AWS vs GCP ตอนที่ 1: Network &amp; Security</title>
      <dc:creator>Perajit</dc:creator>
      <pubDate>Tue, 21 Apr 2026 14:31:30 +0000</pubDate>
      <link>https://forem.com/perajit/aws-vs-gcp-tnthii-1-network-security-43l2</link>
      <guid>https://forem.com/perajit/aws-vs-gcp-tnthii-1-network-security-43l2</guid>
      <description>&lt;p&gt;บทความนี้เขียนเพื่อพยายามสรุปเปรียบเทียบ AWS และ GCP จะเขียนออกแนวโน้ตส่วนตัว แบบสรุปคร่าวๆ ไม่ลงรายละเอียดเยอะ (เพราะก็ไม่ได้เชี่ยวชาญ 555)&lt;/p&gt;

&lt;p&gt;ที่คิดไว้ก็อยากเขียนหลายเรื่อง แต่ขอเริ่มจากเรื่อง Network ก่อนแล้วกัน&lt;/p&gt;

&lt;h1&gt;
  
  
  Network Architecture
&lt;/h1&gt;

&lt;p&gt;ก่อนอื่นต้องพูดถึงคำศัพท์กันก่อน&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ในแง่ภูมิศาสตร์&lt;/strong&gt;: &lt;em&gt;Global&lt;/em&gt;, &lt;em&gt;Region&lt;/em&gt;, &lt;em&gt;Zone&lt;/em&gt; (สำหรับ AWS เรียก &lt;em&gt;Availability Zone&lt;/em&gt; หรือ &lt;em&gt;AZ&lt;/em&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ในระบบ cloud แต่ละเจ้าจะแบ่งโครงสร้างพื้นฐานในเชิงภูมิศาสตร์ตามบริเวณที่มี data center&lt;/li&gt;
&lt;li&gt;Global คือทั้งโลก ประกอบด้วยหลายๆ Region ซึ่งเป็นที่ตั้งที่อยู่ห่างกันมาก&lt;/li&gt;
&lt;li&gt;แต่ละ Region จะประกอบด้วยหลาย Zone (สำหรับ AWS เรียก availability zone หรือ AZ) อีกที&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;ในแง่เครือข่าย&lt;/strong&gt;: &lt;em&gt;VPC&lt;/em&gt;, &lt;em&gt;Subnet&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC ที่เป็นวงเครือข่ายที่ resource ภายในสามารถมองเห็นกันได้แต่ภายนอกไม่สามารถมองเห็นเข้ามาได้ถ้าไม่ได้รับอนุญาต&lt;/li&gt;
&lt;li&gt;Subnet ส่วนย่อยของ VPC&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;ความแตกต่างที่ชัดเจนคือ&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;สำหรับ AWS&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC span เป็น Regional ไม่สามารถ span ข้าม Region ได้&lt;/li&gt;
&lt;li&gt;Subnet อยู่เฉพาะใน AZ เดียวเท่านั้น ไม่สามารถ span ข้าม AZ ได้&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ในขณะที่ GCP&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC span เป็น Global ครอบคลุมทั่วโลก&lt;/li&gt;
&lt;li&gt;Subnet เป็น Regional คือ span ครอบคลุมได้หลาย Zone
(เวลาวาง VM ยังต้องเลือก Zone แต่ IP Address มาจาก pool เดียวกันทั้ง Region)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ความแตกต่างนี้ทำให้ GCP สามารถคุยข้าม Region ได้เลยโดยไม่ต้องทำอะไรเพิ่ม ขณะที่ AWS ต้องมีขั้นตอนเพิ่มเติม (เช่น ทำ Peering) เพื่อให้คุยข้าม Region ได้&lt;/p&gt;

&lt;h1&gt;
  
  
  Network Routing
&lt;/h1&gt;

&lt;p&gt;การคุม traffic ใน Network จะใช้ Route Table (AWS) หรือ Routes (GCP)โดยมีความแตกต่างกันตามนี้&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS Route Table&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;อยู่ในเลเวล Subnet คือแต่ละ VPC จะมีได้หลาย Route Table และควบคุม traffic ของแต่ละ Subnet แยกกันด้วยการสร้าง Route Table ที่ต่างกันไปผูกไว้&lt;/li&gt;
&lt;li&gt;ถ้าไม่มีการผูก Route Table ที่สร้างแยกไว้ Subnet จะใช้ Main Route Table ซึ่งเป็นตารางกลางสำหรับทุก Subnet ซึ่งกำหนดให้ component ทุกตัวคุยกันผ่าน internal IP ได้ภายใน VPC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;GCP Routes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;มี Routes ตารางเดียวเป็นระดับ Global แชร์กันทั้งโลก&lt;/li&gt;
&lt;li&gt;สามารถสร้าง Route ให้มีผลเฉพาะสำหรับ VM บางตัวได้โดยการใส่ Network Tags&lt;/li&gt;
&lt;li&gt;เมื่อมีการสร้าง Subnet ใหม่ ระบบจะสร้าง Route สำหรับการติดต่อภายใน (local) ให้แบบ Global โดยอัตโนมัติ หมายความว่า component จากคนละ Region จะคุยกันผ่าน internal IP ได้เลย&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Network Security
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Network Security in AWS
&lt;/h3&gt;

&lt;p&gt;AWS แบ่งตัวควบคุม security เป็น 2 เลเยอร์ คือ ในระดับ Subnet และระดับ Instance&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Group&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ควบคุมระดับ Instance&lt;/li&gt;
&lt;li&gt;เป็นการควบคุมแบบ Stateful หมายความว่า มีการจำเส้นทางเข้าออกของ traffic ถ้าขาเข้าผ่านได้ ขาออกก็จะผ่านได้โดยอัตโนมัติ&lt;/li&gt;
&lt;li&gt;ควบคุมแค่ Allow เท่านั้น (white-list)&lt;/li&gt;
&lt;li&gt;ค่า default คือ Deny ขาเข้าทั้งหมด แต่ Allow ขาออกทั้งหมด ทำให้ instance สามารถเรียกออกไปข้างนอกได้เพื่อ install package ต่างๆ ได้&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Network ACL (NACL)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ควบคุมระดับ Subnet&lt;/li&gt;
&lt;li&gt;เป็นการควบคุมแบบ Stateless หมายความว่า ไม่มีการจำการเส้นทางเข้าออกของ traffic ต่อให้ขาเข้าผ่านเข้ามาได้แล้วมันก็ไม่ได้ยอมให้ขาออกผ่านได้เอง ต้องกำหนดกฎของ "ขาเข้า" (ingress) และ "ขาออก" (egress) แยกกัน&lt;/li&gt;
&lt;li&gt;ควบคุมได้ทั้ง Allow และ Deny (สามารถทำ black-list ได้)&lt;/li&gt;
&lt;li&gt;โดย default จะ allow ทั้งหมด ทั้งขาเข้าและขาออก&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;ใน AWS มักจะใช้ Security Group เป็นหลัก และใช้ NACL แค่เป็นด่านเสริมเพื่อ black-list IP ไม่พึงประสงค์&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Network Security in GCP
&lt;/h3&gt;

&lt;p&gt;มีตัวควบคุม security หลักๆ คือ Firewall Rules เป็นการควบคุมแบบ Stateful โดยมีค่า default เหมือนกับ Security Group (stateful เหมือนกัน) คืออนุญาตให้ทุกอย่างวิ่งออกได้ทั้งหมด แต่บล็อกทุกอย่างที่วิ่งเข้า&lt;/p&gt;

&lt;p&gt;ควบคุมได้ทั้ง Allow และ Deny ทำให้เราสามารถใช้ทำ black-list กับ white-list ได้โดยอาศัยการตั้งค่า Deny/Allow, Priority&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ทำ Deny (black-list)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;สร้างกฎโดยใช้ &lt;code&gt;Action: Deny&lt;/code&gt;, &lt;code&gt;Priority: 100&lt;/code&gt; &lt;em&gt;(ตัวเลขน้อยกว่ากฎ Allow หมายถึงสำคัญมากกว่า)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;ระบุ Source IP ที่ต้องการบล็อก&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;ทำ Allow (white-list)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;สร้างกฎโดยใช้ &lt;code&gt;Action: Allow&lt;/code&gt;, &lt;code&gt;Priority: 1000&lt;/code&gt; &lt;em&gt;(ตัวเลขมากกว่ากฎ Deny หมายถึงสำคัญน้อยกว่า)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;ระบุ Source IP ที่ต้องการให้ผ่าน&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Firewall Rules ทำงานที่ระดับ VPC แต่สามารถเซ็ตค่าให้ทำงานในระดับ Instance (เหมือน Security Group) หรือ Subnet (เหมือน NACL) ได้&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ควบคุมระดับ Instance (เทียบกับ Security Group)&lt;/strong&gt;: อาศัย Target Tags ระบุเป้าหมายกลุ่มของ VM ที่ต้องการบังคับใช้กฎ&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ควบคุมระดับ Subnet (เทียบกับ NACL)&lt;/strong&gt;: อาศัยการกำหนด Destination IP เป็น IP range ของ Subnet ที่ต้องการควบคุม&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cloud</category>
      <category>network</category>
      <category>aws</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Interface ใน Go ฉบับรวบยอด</title>
      <dc:creator>Perajit</dc:creator>
      <pubDate>Tue, 21 Apr 2026 01:27:11 +0000</pubDate>
      <link>https://forem.com/perajit/interface-in-go-chbabrwbyd-1c3e</link>
      <guid>https://forem.com/perajit/interface-in-go-chbabrwbyd-1c3e</guid>
      <description>&lt;h1&gt;
  
  
  Interface กับ OOP
&lt;/h1&gt;

&lt;p&gt;จากบทความที่แล้ว เราทำ OOP ด้วยการผูก method ให้ struct ผ่าน receiver ทีนี้ถ้าเราอยากจัดการกับ struct หลายประเภทที่มีพฤติกรรมเหมือนกันในที่เดียวจะทำยังไง?&lt;/p&gt;

&lt;p&gt;ปกติในภาษาอื่นเราก็จะสร้าง interface ขึ้นมา แล้วให้แต่ละ class implement interface นั้นใช่มั้ย? ใน Go ก็มี interface เหมือนกัน แต่สิ่งที่ต่างคือ ใน Go เป็น implicit interface ไม่ต้องมีการเขียนคีย์เวิร์ด implement เลย&lt;/p&gt;

&lt;p&gt;เช่น เรามี &lt;code&gt;Cat&lt;/code&gt; และ &lt;code&gt;Dog&lt;/code&gt; ซึ่งทั้งคู่มี method ที่มี method signature เหมือนกันคือ &lt;code&gt;Speaker()&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Speak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Meow!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Speak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Woof!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เราสามารถสร้าง interface ได้แบบนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Speaker&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Speak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;โดย &lt;code&gt;Cat&lt;/code&gt; และ &lt;code&gt;Dog&lt;/code&gt; ของเราจะยังเหมือนเดิม ไม่มีแก้โค้ดใดๆ แต่ Go จะรู้เองว่ามันคือ &lt;code&gt;Speaker&lt;/code&gt; เพราะว่า "satisfy interface"&lt;/p&gt;

&lt;p&gt;และเราก็สามารถประกาศ slice ของ &lt;code&gt;Speaker&lt;/code&gt; แล้วเก็บค่า &lt;code&gt;Cat&lt;/code&gt; กับ &lt;code&gt;Dog&lt;/code&gt; ไว้ด้วยกัน รวมถึงสามารถเรียก method ของ &lt;code&gt;Speaker&lt;/code&gt; จาก slice ได้เลย&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Kitty"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Bo"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// slice ของ Speaker เก็บได้ทั้ง cat และ dog ทันที&lt;/span&gt;
&lt;span class="n"&gt;animals&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Speaker&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;animals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// เรียก Speak() ของ Speaker ได้เลย&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Speak&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ไอเดียคือใช้การประกาศ interface จากฝั่ง consumer ตรงข้ามกับใน classic OOP ที่เวลาจะใช้ interface ต้องมีการผูกกันตั้งแต่ต้น ซึ่งการทำ interface แบบ Go มีข้อดีหลายอย่าง&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ทำให้เราโฟกัสที่ behavior มากกว่า type&lt;/li&gt;
&lt;li&gt;ยืดหยุ่น สามารถเอา library สองตัวจากคนละที่มาทำงานร่วมกันได้ทันทีถ้า method signature ตรงกัน&lt;/li&gt;
&lt;li&gt;ไม่ผูกติดกับโค้ดต้นทาง ถ้าสนใจ method ไหนก็ประกาศ interface แค่นั้นพอ ซึ่งข้อนี้ทำให้การ mock (เช่น สำหรับ unit test) ง่ายขึ้นมาก&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  โครงสร้าง Interface
&lt;/h1&gt;

&lt;p&gt;ภายใต้ตัวแปร interface จะเก็บค่า 2 อย่างเสมอ คือ type (ชนิดของข้อมูล) และ value (ค่าของข้อมูล) เพราะฉะนั้น interface จะเป็น &lt;code&gt;nil&lt;/code&gt; ก็ต่อเมื่อทั้ง type และ value เป็น &lt;code&gt;nil&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;เช่นจากตัวอย่างเดิม เรามี struct &lt;code&gt;Cat&lt;/code&gt; และ interface &lt;code&gt;Speaker&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;Speaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;

&lt;span class="c"&gt;// ตรวจสอบว่า i เป็น nil รึเปล่า&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จะได้ผลลัพธ์เป็น &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Empty Interface
&lt;/h1&gt;

&lt;p&gt;interface ว่าง &lt;code&gt;interface{}&lt;/code&gt; คือ interface ที่ไม่มีการกำหนด method อะไรไว้ ซึ่งหมายความว่าสามารถเป็น type อะไรก็ได้ (หรือก็คือ &lt;code&gt;any&lt;/code&gt; ในเวอร์ชั่นใหม่ๆ ของ Go)&lt;/p&gt;

&lt;p&gt;เรามักจะใช้ในกรณีที่ต้องการ Dynamic Type เช่น ใช้กับฟังก์ชั่นที่รับพารามิเตอร์อะไรก็ได้ หรือใช้กับโครงสร้างข้อมูลที่ dynamic เช่น &lt;code&gt;map[string]interface{}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;แต่ข้อควรระวังคือ เราจะไม่สามารถใช้ความสามารถของ type เดิมได้ ต้องแปลงค่ากลับมาก่อน เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เราไม่สามารถสั่งแบบนี้ได้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="c"&gt;// จะ error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เนื่องจากตอนนี้ x เป็น &lt;code&gt;interface{}&lt;/code&gt; ไม่ใช่ &lt;code&gt;int&lt;/code&gt; ต้องแปลงกลับเป็น &lt;code&gt;int&lt;/code&gt; ก่อนถึงจะทำ operation ของ &lt;code&gt;int&lt;/code&gt; ได้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ปัจจุบัน Go มี Generics ให้ใช้แล้ว แนะนำให้ใช้ Generics แทน interface{}&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>OOP ใน Go ฉบับเข้าใจง่าย (มั้ง)</title>
      <dc:creator>Perajit</dc:creator>
      <pubDate>Tue, 21 Apr 2026 00:17:37 +0000</pubDate>
      <link>https://forem.com/perajit/oop-ain-go-chbabekhaaaicchngaay-mang-3j2l</link>
      <guid>https://forem.com/perajit/oop-ain-go-chbabekhaaaicchngaay-mang-3j2l</guid>
      <description>&lt;p&gt;ออกตัวก่อนว่าไม่ได้เชี่ยวชาญ Go อะไรมากมาย แค่นึกไม่ออกว่าเขียนเรื่องอะไรดี แล้วเรื่องนี้ก็ผุดขึ้นมา&lt;/p&gt;

&lt;p&gt;ใน Go สามารถทำ OOP ได้ แต่จะค่อนข้างต่างจากภาษาอื่นที่เคยเจอมา คือไม่มีสิ่งที่เรียกว่า class แต่จะใช้ struct ซึ่งเป็นการ define โครงสร้างข้อมูล เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Animal&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;Weight&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เป็นการประกาศโครงสร้างของข้อมูลที่ประกอบด้วยฟิลด์ชื่อ &lt;code&gt;Name&lt;/code&gt; และ &lt;code&gt;Weight&lt;/code&gt; และเนื่องจากใน Go จะใส่ zero value ให้ค่าต่างๆ เสมอ ดังนั้นถ้าประกาศตัวแปรด้วย type ของ struct แต่ละ field ก็จะมีค่าเริ่มต้นเป็น zero value ของแต่ละชนิดข้อมูลโดยอัตโนมัติ ซึ่งก็คือทำหน้าที่เก็บข้อมูลได้เหมือน data class ในภาษาอื่นนั่นเอง&lt;/p&gt;

&lt;p&gt;จากตัวอย่าง &lt;code&gt;Animal&lt;/code&gt; ถ้าประกาศตัวแปรแบบนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เราก็จะได้สิ่งที่เหมือนกับ instance ของ data class ที่มีค่า &lt;code&gt;cat.Name = ""&lt;/code&gt; และ &lt;code&gt;cat.Weight = 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;หรือจะกำหนดค่าเริ่มต้นลงไปตั้งแต่ตอนประกาศค่าก็ได้ เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Kitty"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ก็จะได้ค่าตามที่กำหนดคือ &lt;code&gt;cat.Name = "Kitty"&lt;/code&gt; และ &lt;code&gt;cat.Weight = 2&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Class with methods
&lt;/h1&gt;

&lt;p&gt;ตอนนี้เราสามารถสร้างสิ่งที่เหมือนกับ class ที่มี property แล้ว แต่ว่าในโลกของ OOP เนี่ย class ไม่ได้มีแค่ property แต่ยังมี method ด้วยใช่มั้ย?&lt;/p&gt;

&lt;p&gt;ใน Go เราสามารถสร้าง method ให้กับ struct ได้โดยไม่ได้เขียนลงใน struct เลย แต่ใช้การการผูกฟังก์ชั่นเข้าไปโต้งๆ ทีหลัง ซึ่งคำว่า "ผูกโต้งๆ" อาศัยสิ่งที่เรียกว่า receiver&lt;/p&gt;

&lt;p&gt;ตัวอย่างเช่น เราจะเติม method &lt;code&gt;Eat()&lt;/code&gt; ให้กับ &lt;code&gt;Animal&lt;/code&gt; ได้แบบนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Eat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สังเกตว่ารูปแบบการเขียนฟังก์ชั่นจะมีบางอย่างเพิ่มเข้ามา คือ &lt;code&gt;(a *Animal)&lt;/code&gt; สิ่งนี้แหละที่เรียกว่า receiver โดย &lt;code&gt;a&lt;/code&gt; คือ receiver variable ส่วน &lt;code&gt;*Animal&lt;/code&gt; เป็น receiver type สังเกตว่าจะไม่มีการใช้คีย์เวิร์ด this เหมือนภาษาอื่น แต่จะใช้ receiver อ้างอิงไปเลย&lt;/p&gt;

&lt;p&gt;ลองเขียนโค้ดทดสอบดู&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Kitty"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Weight: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;จะได้ค่า &lt;code&gt;a.Weight = 3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;แล้วทีนี้อยากให้มี method อีกสักกี่อันก็แค่เขียนฟังก์ชั่นโดยผูก receiver เข้าไป&lt;/p&gt;

&lt;p&gt;ข้อดีของการเขียนลักษณะนี้คือทำให้สามารถเติม method เข้าไปได้โดย struct ไม่บวม (อยู่คนละไฟล์ได้) และการใช้ชื่อตัวแปร receiver แทน &lt;code&gt;this&lt;/code&gt; ทำให้ refactor โค้ดจาก function ธรรมดามาเป็น method ได้ง่ายๆ โดยไม่ต้องแก้ชื่อตัวแปรเป็น &lt;code&gt;this&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;เสริมอีกนิดว่า receiver มี 2 แบบคือ value receiver กับ pointer receiver สำหรับในตัวอย่างเราใช้ pointer receiver ซึ่งคือแบบนี้ &lt;code&gt;(a *Animal)&lt;/code&gt; เพราะต้องการแก้ไขข้อมูล เวลาใช้ value receiver ซึ่งคือแบบนี้ &lt;code&gt;(a Animal)&lt;/code&gt; เราจะไม่สามารถแก้ไขข้อมูลได้&lt;/p&gt;

&lt;p&gt;เช่น ถ้าแก้โค้ดของ method &lt;code&gt;Eat()&lt;/code&gt; เป็นแบบนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// การใช้ value receiver จะไม่สามารถแก้ไขข้อมูลได้&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Eat&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ผลที่ได้คือคือค่าของ &lt;code&gt;a.Weight&lt;/code&gt; จะไม่เปลี่ยน&lt;/p&gt;

&lt;h1&gt;
  
  
  Inheritance (หรือจริงๆ คือ Composition)
&lt;/h1&gt;

&lt;p&gt;การ "สืบทอด" ใน Go ก็แตกต่างจากภาษาอื่นที่ใช้คีย์เวิร์ด extends แต่ Go ออกแบบมาให้ "Composition over Inheritance" จึงใช้การ "ฝัง" (embedding) struct ซ้อนเข้าไปข้างใน เช่น&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Animal&lt;/span&gt;
  &lt;span class="n"&gt;SlaveName&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Meow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Meow"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เราจะได้ &lt;code&gt;Cat&lt;/code&gt; ที่มี property และ method ของ &lt;code&gt;Animal&lt;/code&gt; ติดมาด้วยทันที&lt;br&gt;
ทดสอบด้วยการเขียนโค้ดตามด้านล่างนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Name: %v, Weight: %v, SlaveName: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SlaveName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;โค้ดจะไม่พัง และจะได้ผลลัพธ์เป็น &lt;code&gt;Name:, Weight:1, SlaveName:&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Name&lt;/code&gt; เป็นสตริงว่าง จาก zero value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Weight&lt;/code&gt; เป็น 1 เนื่องจากมีการสั่ง &lt;code&gt;cat.Eat()&lt;/code&gt; ทำการเพิ่มค่าจาก zero value ครั้งนึง&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SlaveName&lt;/code&gt; เป็นสตริงว่างจาก zero value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;แล้วถ้าเกิดเราต้องการใส่ค่าเริ่มต้นให้กับ &lt;code&gt;cat&lt;/code&gt; ล่ะ? ในเมื่อเราสามารถเรียก property ที่มาจาก &lt;code&gt;Animal&lt;/code&gt; ได้ตรงๆ งั้นเราลองใส่ &lt;code&gt;Weight&lt;/code&gt; เป็น 2 ให้กับ &lt;code&gt;cat&lt;/code&gt; ดูหน่อย&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SlaveName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Jack"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ปรากฏว่าเขียนแบบนี้จะเจอ syntax error…&lt;/p&gt;

&lt;p&gt;นี่เป็นเรื่องที่เราเจอตอนลองเขียนครั้งแรก แล้วก็งงว่าจะใส่ค่าเริ่มต้นให้มันได้ยังไง แล้วก็ค้นพบว่า วิธีที่ถูกต้องคือ ต้องระบุชื่อ struct ที่ embed มาด้วย!&lt;/p&gt;

&lt;p&gt;เนื่องจากตอนประกาศ struct เราใส่ &lt;code&gt;Animal&lt;/code&gt; เข้าไป ตอนเซ็ตค่าเริ่มต้นเราก็ต้องระบุ &lt;code&gt;Animal&lt;/code&gt; เหมือนกัน แบบนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;SlaveName&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Jack"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ทีนี้ถ้าลองสั่ง&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Name: %v, Weight: %v, SlaveName: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SlaveName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เราจะได้ผลลัพธ์ &lt;code&gt;Name:, Weight:3, SlaveName:Jack&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Name&lt;/code&gt; ยังเป็นสตริงว่างเพราะไม่ได้กำหนดค่า&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Weight&lt;/code&gt; เป็น 3 เนื่องจากค่าเริ่มต้นถูกเซ็ตเป็น 2&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SlaveName&lt;/code&gt; ได้ค่า Jack ที่เซ็ตเข้าไป&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;ตอนที่ดึงค่าออกมาจาก field หรือเรียก method สามารถเรียกได้เลยตรงๆ แต่ตอนประกาศค่าต้องระบุชื่อ struct ที่ embed มาเสมอ&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;สำหรับ OOP ใน Go คร่าวๆ ก็ประมาณนี้ค่ะ&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>oop</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
