<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Waranchit Chaiwong on Medium]]></title>
        <description><![CDATA[Stories by Waranchit Chaiwong on Medium]]></description>
        <link>https://medium.com/@waranchit-ch?source=rss-17ea0fe821f9------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*xIHx5zu2PzUz8HWHqfMt5g.jpeg</url>
            <title>Stories by Waranchit Chaiwong on Medium</title>
            <link>https://medium.com/@waranchit-ch?source=rss-17ea0fe821f9------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 17:50:38 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@waranchit-ch/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[UIKit The Series: EP.1 How to custom the UI Table View Cell]]></title>
            <link>https://waranchit-ch.medium.com/uikit-the-series-ep-1-how-to-custom-the-ui-table-view-cell-1c89a5430302?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/1c89a5430302</guid>
            <category><![CDATA[ios]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Wed, 06 Apr 2022 07:58:07 GMT</pubDate>
            <atom:updated>2022-04-06T07:58:07.027Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/295/1*XB-Hhh556bBSw7XgPRrwUw.png" /></figure><h3>Nibs or Xibs</h3><ul><li>a nib, also called a xib, is very much like a storyboard expect that it only contain the design for a single item.</li><li>NIBs and XIBs are files that <strong>describe user interfaces</strong>, and are built using interface Builder.</li><li>A xib file is compiled into a nib file that is put into your application bundle.</li></ul><h3>Create custom table view cell on nibs</h3><h4>1. Add a nibs inside your project</h4><p>add new file in to your project. Choose <strong>Empty</strong> from <strong>User Interface</strong> category</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NODJzmyjMGBorFDqaDz9xw.png" /></figure><p>Click <strong>Next</strong> and <strong>Create</strong> the new file with the name you want.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GOoNfXfW2Xkzr0P1KsUbUQ.png" /></figure><h4>2. create the view inside nibs</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/565/1*87rLf2jyFIhbIGftJfK67A.png" /><figcaption>table cell prototype by figma design</figcaption></figure><p><strong>Step 1 :</strong> add view object by click the button library(+ button that on the right top) or also you can Press <strong>Command-shift-L</strong> for open object library as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*000Z0yIbkMmDvhqCYNwkGw.png" /></figure><p>and after that, drag a new <strong>Table View Cell</strong> on to the canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T9Wm8OOU4fHeihetYsb6Vw.png" /></figure><p><strong>Step 2 :</strong> Drag an <strong>image view</strong> and <strong>labels</strong> into the cell so that the cell now loogs like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Csxr_6e1OEzryAk7ovkULw.png" /></figure><ul><li>Position the Image View at <strong>X</strong>: 20, <strong>Y</strong>: 16, <strong>Width</strong>: 60, <strong>Height</strong>: 60</li><li>Set The Label Text of the <strong>first label</strong> to <strong>Name</strong>, <strong>Font</strong> to <strong>System 18</strong>, <strong>X</strong>: 88, <strong>Y</strong>: 15, <strong>Width</strong>: 48, <strong>Height</strong>: 22</li><li>Set The Label Text of the <strong>second label</strong> to <strong>Category name</strong>, <strong>Font</strong> to <strong>System 14</strong>, <strong>X</strong>: 88, <strong>Y</strong>: 45, <strong>Width</strong>: 99, <strong>Height</strong>: 17</li><li>The Table View Cell itself <strong>needs</strong> to have a <strong>reuse identifier</strong>. You can set this in the <strong>Attributes inspector</strong> to any text that you want but in this article i’m gonna set to <strong>CustomCell</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KL4sWlNsip1LNVZbcbskMA.png" /></figure><p><strong>Note:</strong> Please make sure you already click on the Table View Cell</p><h3>Use custom table view cell from nib in your code</h3><h4>1. Register nib file</h4><ul><li>In <strong>HomeTableViewController.swift, </strong>add these lines to the end of viewDidLoad<strong>() :</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zdeshyf8TrCVH9XlT8H_6g.png" /></figure><p>The UINib class is used to load nibs. Here, you tell it to load the nib you just created. nibname: is receive nib file name, in this article my our nibs file name is CustomCell . so you can put this name into nibsname: &quot;CustomCell&quot; <strong>Without specify</strong> the xib file extension.</p><h4>2. Create subclass for connect each ui object in nib to this</h4><p><strong>Step 1 :</strong> add new file in to your project. Choose <strong>CoCoa Touch Class</strong> from <strong>Source</strong> category</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3jayikmIIgOKV3p_zdSi5Q.png" /></figure><p>Click <strong>Next. </strong>Name it<strong> </strong>CustomTableViewCell and make it a subclass of <strong>UITableViewCell </strong>and also create XIB file should be <strong>unchecked.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L3HCy-W8PZcYaIdg3qENXg.png" /></figure><p>Click <strong>Next</strong> and <strong>Create.</strong></p><p><strong>Step 2: </strong>add<strong> </strong>outlet properties to <strong>CustomTableViewCell.swift</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b335393b6fc070ff2cfc2681ccd5ec4/href">https://medium.com/media/5b335393b6fc070ff2cfc2681ccd5ec4/href</a></iframe><ul><li>Open <strong>CustomCell.xib</strong> and select the Table View Cell and after that In the <strong>Identity inspector</strong>, change it’s class from UITableViewCell to <strong>CustomTableViewCell</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YrZwS4Tqtn1I_pQUx--pRg.png" /></figure><ul><li>Hook these outlets up to the respective label and image view in the nibs</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cBVITPmtWaJwCdoXy1S5aw.png" /></figure><p>Not that this is all set up, you can tell the HomeTableViewController to use these new <strong>CustomTableViewCell.</strong></p><h4>3. Use it</h4><ul><li>In <strong>HomeTableViewController.swift</strong>, change cellForRowAt to:</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/afe08c40d8a52dd9a01a62632ad1993f/href">https://medium.com/media/afe08c40d8a52dd9a01a62632ad1993f/href</a></iframe><ul><li>Run the app</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/962/1*jh31ZLR9yoM9Xpb2jXtoBQ.png" /></figure><p>everything is fine, <strong>but</strong> if you scroll up to our design. above display is not the same as our design. Why ?</p><h3>Set up Auto Layout Constraints</h3><p>The table view cell will resize to accommodate those larger screens, but ui object inside the cell <strong>won’t</strong> to do this. You should have to add some Auto Layout Constraints to make the ui object’s.</p><p>Open <strong>CustomCell.xib</strong> and add constraints to each ui object inside cell</p><ul><li>Select the <strong>Image View</strong> and open the Add New Constraints Menu.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*W_YetKEDFZxCv8rUn3acbg.png" /></figure><ul><li>Select the <strong>Name label</strong> and open the Add New Constraints Menu.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/536/1*hEqlglXIgcAfdjJm2U-3Fw.png" /></figure><ul><li>Select the <strong>Category name label</strong> and open the Add New Constraints Menu.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/538/1*nBtB_93pTWWpGBoNUqOO9w.png" /></figure><ul><li>Run app again !</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/1*Gul6o-zvRdRV8T6QYhaDcA.png" /></figure><p>Yeahhhhhh. Finally everything is fine. That’s it 😁😊😎. see you on the next episode…</p><h3>References</h3><ul><li><a href="https://www.raywenderlich.com/books/uikit-apprentice">UIKIT Apprentice By Ray Wenderlich</a></li><li><a href="https://www.hackingwithswift.com/example-code/language/what-is-a-nib">What is Nibs ?</a></li><li><a href="https://medium.com/@tjcarney89/whats-a-xib-and-why-would-i-ever-use-one-58d608cd5e9b">What is a XIB and why would i ever use one ?</a></li><li><a href="https://github.com/FunnyDevP/ios_custom_table_view_cell">Custom Table View Cell Github repository</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1c89a5430302" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[มาสร้าง Restful Api ด้วย .Net Core กันเถอะ]]></title>
            <link>https://waranchit-ch.medium.com/%E0%B8%A1%E0%B8%B2%E0%B8%AA%E0%B8%A3%E0%B9%89%E0%B8%B2%E0%B8%87-restful-api-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-net-core-%E0%B8%81%E0%B8%B1%E0%B8%99%E0%B9%80%E0%B8%96%E0%B8%AD%E0%B8%B0-71d77b298486?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/71d77b298486</guid>
            <category><![CDATA[dotnet-core]]></category>
            <category><![CDATA[entity-framework-core]]></category>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Fri, 19 Nov 2021 03:32:17 GMT</pubDate>
            <atom:updated>2021-11-19T03:32:17.540Z</atom:updated>
            <content:encoded><![CDATA[<h3>มาสร้าง Restful Api ด้วย .Net Core กันเถอะ</h3><h3>Introduction</h3><p>สวัสดีทุกคนที่เข้ามาด้วยนะครับ (หรืออาจจะหลงเข้ามาก็เป็นได้…). ช่วงนี้เป็นช่วงที่ผมกำลังศึกษาเกี่ยวกับ การสร้าง Simple API ของฝั่ง Backend โดยใช้ <em>.Net Core,</em> <em>Entity framework</em>, และ <em>Postgres</em>. วันนี้เลยอยากจะมาแชร์เกี่ยวกับขั้นตอนการทำ รวมทั้ง แหล่งเรียนรู้เพิ่มเติมหากใครสนใจ.</p><h3>Web API</h3><h4>Initial Project</h4><p>ก่อนอื่นเราจะมาสร้าง <strong>Initial Project</strong> ประเภท <em>Web API</em> ของเราก่อนนะฮะ ในบทความนี้ผมจะใช้ IDE ที่ชื่อว่า <em>Rider </em>ในการ<em> development</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*98RoZgQcRHVVqNTSc2U6gg.png" /></figure><ol><li>เริ่มต้นให้เรา New Project ขึ้นมาก่อน</li><li>Tab ด้านซ้าย ให้เลือก <em>ASP.NET core Web Application</em></li><li>ในส่วนของ <em>Solution name</em> และ <em>Project name</em> สามารถใส่ได้ตามต้องการเลย</li><li>หากเราต้องการ <em>initial git</em> ด้วย ก็ติ๊กถูกที่ช่อง <em>Create Git repository </em>ได้เลย มันจะ init ให้เราตั้งแต่เริ่ม project เลย</li><li><em>SDK</em> ก็เลือกตามที่จะใช้เลย ในครั้งนี้ผมใช้ <em>.Net 5</em> (หากใครสงสัยว่า .<em>Net 5</em> คืออะไร เดี๋ยวผมจะทิ้งลิ้งไว้ท้ายบทความให้ไปอ่านเพิ่มละกันครับ)</li><li><em>Type</em> ส่วนนี้สำคัญครับ มันเป็นเหมือนการเลือกเราจะสร้างโปรเจคในลักษณะงานแบบไหน ในบทความนี้ให้เราเลือก <em>Web API</em></li><li>หากไม่มีการ set อะไรเพิ่มเติม ก็กดปุ่ม <em>Create</em> ได้เลย</li></ol><h4>Create Controller</h4><p>ในส่วนนี้เราจะมาสร้าง controller กันนะครับ โดยส่วนนี้ผมมองว่าจะเป็นเหมือนด่านหน้า เมื่อมี Request จาก Client(ในที่นี้อาจจะเป็น Frontend หรือ Mobile application or etc.) เข้ามาที่ API service เรา ก็จะเจอ Controller ก่อน. โดยเราจะเลือกสร้างจาก dotnet command, สร้าง Class เองแล้วใส่รายละเอียดที่ต้องใช้ หรือ ในบทความนี้เราจะใช้ Rider เราก็สามารถ สร้าง Template ของ Web API ขึ้นมาได้ง่ายๆเลย.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SHaRI2Sbx3oWmSInLfxS2Q.png" /></figure><ol><li>ให้คลิกขวาที่โฟรเดอร์ Controllers จากนั้นคลิกที่ New Scaffolded Item…</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JIJPaTuvfawBxbsIwwS_fQ.png" /></figure><p>2. ใส่ชื่อ Controller และ เลือก Template ที่ต้องการ ในบทความนี้เราจะเลือกใช้ API Controller — Empty</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/900/1*amJMXZmslxymgl0iopLfYg.png" /></figure><p><strong>ข้อ 1:</strong> เราจะเรียกสิ่งที่เป็น […] ว่า Attribute.</p><p>ในภาพ <em>[Route(“api/[controller]”)]</em> หมายความว่าเรากำหนดให้ <em>Controller</em> จะจัดการกับ <em>request</em> ที่เข้ามาด้วย <em>endpoint /api/[controller]</em>.</p><p><em>[controller] </em>เป็นการที่ตัว dotnet จะหยิบเอาชื่อของ <em>class Controller</em> มาใส่โดยจะตัดคำว่า <em>Controller</em> ออก. ในตัวอย่าง <em>[controller]</em> คือ <em>Todolist</em>. ดังนั้น ถ้ามี <em>request</em> ที่เข้ามาด้วย <em>endpoint api/Todolist</em> ก็จะเข้า Class นี้.</p><p>แต่ในที่นี้เราสามารถกำหนดเองได้ตามต้องการ</p><p>Attribute ที่น่าสนใจนอกจาก Route</p><ul><li>สำหรับ Define HttpMethod</li><li>สำหรับ Binding source ที่มาจาก Request เข้า model หรือ object บางอย่าง เช่น RequestBody, Query string parameter, RequestHeader</li></ul><h4>Controller 101</h4><p>หลังจากก่อนหน้านี้เราสร้าง Class Controller. ในส่วนนี้เราจะมาสร้าง <em>method</em> เพื่อ จัดการ <em>request</em> แต่ละ <em>method</em> ที่เข้ามา.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/631a381e71a5c5d223ef26a8b93a6c1a/href">https://medium.com/media/631a381e71a5c5d223ef26a8b93a6c1a/href</a></iframe><p><strong>Line 30 และ 37:</strong> จะเห็นได้ว่าเรามีการใช้ Attribute <strong>[FromBody] </strong>เพื่อ binding request body กับ Model ที่เรากำหนด ในที่นี้คือ CreateOrUpdatetodoListDto.</p><p>การสร้าง method เพื่อจัดการ request ก็เหมือนการสร้าง method ใน class ทั่วไปเลย โดย <em>Action</em> <em>Return Type</em> ของ <em>Web API method</em> จะแบ่งออกเป็น <strong>3 ประเภท</strong></p><ul><li>Specific type</li><li>IActionResult</li><li>ActionResult&lt;T&gt;</li></ul><p>Specific type</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/66c7e9a311979a1d0a81a723b2c8f2bd/href">https://medium.com/media/66c7e9a311979a1d0a81a723b2c8f2bd/href</a></iframe><p>หากต้องการ <strong>Return ของแค่ Type เดียว</strong> เราสามารถใช้ <em>Action Return Type </em>ประเภทนี้ได้ โดย <em>Return type</em> ก็จะเหมือนการประกาศ method ใน class ทั่วไปเลย. โดย <em>Return Type</em> จะเป็น Primitive type หรือ Complex type ก็ได้.</p><p>IActionResult</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2aed17412390e775fdb9bbe16556bc47/href">https://medium.com/media/2aed17412390e775fdb9bbe16556bc47/href</a></iframe><p>ใช้ในกรณีที่ต้องการ<strong> Return ของ หลาย ๆ Type</strong>(Type ในที่นี้หมายถึง Object Result จะมีอะไรบ้างนั้น เดี๋ยวผมแปะลิงค์ไว้ใต้โพส).</p><p>ActionResult&lt;T&gt;</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/51ab6f0653e913da04591484eafcf37f/href">https://medium.com/media/51ab6f0653e913da04591484eafcf37f/href</a></iframe><p><em>Action return type</em> ประเภทนี้จะมีความหลายกับ IActionResult แต่ต่างตรงที่ <em>ActionResult&lt;T&gt;</em> <strong>สามารถ Return ได้ระหว่าง Object Result และ Specific type.</strong></p><h3>EF Core x Postgres</h3><p>หลังจากที่ก่อนหน้านี้เรา implement ในส่วน Controller กันไปแล้ว. ต่อมาเราจะมา implement ส่วนของ Repository. โดยในบทความนี้เราจะใช้ EF หรือชื่อเต็มๆคือ Entity Framework ซึ่งเป็น ORM ของฝั่ง .NET ที่นิยมมาก</p><p>โดยในส่วนนี้ผมจะมาเล่าว่า ต้องติดตั้ง Lib ตัวไหนบ้าง โดยที่เราต้องติดตั้งจะประกอบไปด้วย</p><ul><li>Microsoft.EntityFrameworkCore 5.0.12</li><li>Npgsql.EntityFrameworkCore.PostgreSQL 5.0.10</li><li>Microsoft.EntityFrameworkCore.Design 5.0.12</li></ul><p>อย่าลืมลง Postgres กันด้วยนะฮะ จะลงในเรื่องเลยหรือจะลงใน container ก็ตามที่สะดวกเลยฮะ.</p><h4>Data Model</h4><p>ในส่วนนี้เราจะมาสร้าง data model กันก่อน โดย data model ก็คือ class นึงที่จะมี properties หลายๆอัน ให้นึกภาพว่า class คือ Table และ properties ก็คือ column แต่ละอัน.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e3e3699f31e0b62f23edd1c10faeffbe/href">https://medium.com/media/e3e3699f31e0b62f23edd1c10faeffbe/href</a></iframe><ul><li><strong>Line 3:</strong> ปกติแล้วหากเราไม่กำหนด <em>Attribute</em> ให้กับ <em>Data class model</em> ในตอน <em>migration</em> ชื่อ <em>table</em> ของเราคือชื่อ <em>Class</em> ที่ไม่มีคำว่า <em>Model</em>. แต่หาก<strong>ต้องการกำหนดชื่อ table เอง</strong>ก็สามารถกำหนด Attribute ตาม line ที่ 3 ได้เลย</li></ul><blockquote><strong>ตัวอย่างหากไม่กำหนด Attribute:</strong> TodolistModel =&gt; Todolist(ชื่อ Table)</blockquote><ul><li><strong>Line 5:</strong> property ตัวนี้เปรียบเสมือน Primary key โดย</li><li><strong>[Column(…)]</strong> เป็น Attribute ตัวหนึ่ง ใช้เพื่อกำหนดคุณสมบัติของ column นั้นๆ เช่น กำหนด ชื่อ, data type ซึ่งหากเราไม่กำหนดชื่อให้มัน มันจะหยิบเอาชื่อ Property ไปเป็นชื่อ Column.</li></ul><h4>DbContext</h4><p>ในส่วนนี้เราจะมาประกาศ สิ่งที่เรียกว่า <em>DbContext</em>. มันคือ class ที่เราจะเอาไว้ mapping ระหว่าง <em>Data Model</em> กับ Table ใน <em>Database</em>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ec1659aa327b32d39d140b0338694e4d/href">https://medium.com/media/ec1659aa327b32d39d140b0338694e4d/href</a></iframe><h4>Connection String</h4><p>ในส่วนนี้เราจะมากำหนด ConnectionString ที่ใช้เชื่อมต่อกับ Database ที่เราจะใช้ โดยในบทความนี้เราจะใช้ Postgres นะฮะ ถ้าใครใช้ตัวอื่นแล้วอยากดูตัวอย่างการกำหนดรูปแบบของ ConnectionString เดี๋ยวผมจะแปะลิงค์ไว้ใต้บทความ.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a870e2950ced4deb47c478db9a3b43ec/href">https://medium.com/media/a870e2950ced4deb47c478db9a3b43ec/href</a></iframe><h4>Register DbContext</h4><p>ในส่วนนี้เราจะ register ตัว DbContext เข้ากับ App Startup เพื่อที่ว่า หากมี Class ไหนก็ตามที่ Require dependency DbContext มันก็จะ Inject เข้า Class นั้นๆให้อัตโนมัติ ถ้าผมจำไม่ผิด มันจะเรียกกระบวนการนี้ว่า IoC(inversion of control)</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7e6f62716d1e35c677aaf20ea85c254c/href">https://medium.com/media/7e6f62716d1e35c677aaf20ea85c254c/href</a></iframe><p><strong>Line 8:</strong> คือการ get connection string จาก config</p><h4>Migration</h4><ul><li>Initial Migration With dotnet</li></ul><blockquote>dotnet ef migrations add InitialCreate</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*syOgdF4_U_A6hw4-B1f0hA.png" /></figure><p>หากขึ้นข้อความแบบนี้ แสดงว่า initial migration เสร็จแล้ว.</p><ul><li>Create Table schema from migration(ที่เราทำไปขั้นตอนก่อนหน้า)</li></ul><blockquote>dotnet ef datebase update</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fSX8h6nPPeqxNGMe09clsQ.png" /></figure><p>หากขึ้นแบบนี้ แสดงว่า เรา migrate table ลงใน Database เรียบร้อยละ ทีนี้เราก็พร้อมจะใช้งานจริงๆละ ขั้นต่อไปเราจะเริ่มimplement ในส่วนของ repository กัน</p><h3>EF Core x Postgres In Action</h3><p>ในส่วนนี้เราจะเริ่ม implement repository กันนะครับ โดยในบทความนี้เราจะใช้ Repository pattern เข้ามาช่วย. Repository pattern คือการที่เราสร้าง Abstraction Layer ขึ้นมาระหว่าง ส่วนของ Business logic และ ส่วนของ Data Access layer ในมุมมองของผมที่ได้ลองกับตัวเอง ผมมองว่าวิธีนี้ทำให้เรา เขียน unit test ง่ายขึ้น</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VdeHRnrn3us9WguuvneLDQ.png" /></figure><p>จากรูปคือการนำเอา repository pattern มาใช้. หากเราต้องการเขียน unit test เราก็แค่ mocking ตัว repository ก็คือจบละ ไม่ต้องไปยุ่งกับ Data Access layer (ในที่นี้คือ DbContext) หากใครสนใจรายละเอียดเพิ่มเติมเกี่ยวกับ Repository pattern เดี๋ยวผมแปะลิงค์ไว้ใต้บทความนะครับ</p><h4>Implementing Repository</h4><ul><li>Define abstraction layer</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/59c6d2d1d16177475ca6dadbc7fef424/href">https://medium.com/media/59c6d2d1d16177475ca6dadbc7fef424/href</a></iframe><ul><li>Implementing</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6d46d02d4892f8ff0d368a67001eb9cd/href">https://medium.com/media/6d46d02d4892f8ff0d368a67001eb9cd/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e872aabb9686133f99e77a9bd3b2b1d9/href">https://medium.com/media/e872aabb9686133f99e77a9bd3b2b1d9/href</a></iframe><h3>References</h3><ul><li><a href="https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2">https://docs.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2</a></li><li><a href="https://thecodeblogger.com/2021/06/02/which-type-should-be-returned-from-net-core-web-api-actions/">https://thecodeblogger.com/2021/06/02/which-type-should-be-returned-from-net-core-web-api-actions/</a></li><li><a href="https://stackoverflow.com/questions/54336578/cant-decide-between-taskiactionresult-iactionresult-and-actionresultthing">https://stackoverflow.com/questions/54336578/cant-decide-between-taskiactionresult-iactionresult-and-actionresultthing</a></li><li><a href="https://exceptionnotfound.net/asp-net-core-demystified-action-results/">https://exceptionnotfound.net/asp-net-core-demystified-action-results/</a></li><li><a href="https://www.connectionstrings.com/">https://www.connectionstrings.com</a></li><li><a href="https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application">https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application</a></li><li><a href="https://docs.microsoft.com/en-us/ef/core/modeling/entity-properties?tabs=data-annotations%2Cwithout-nrt">https://docs.microsoft.com/en-us/ef/core/modeling/entity-properties?tabs=data-annotations%2Cwithout-nrt</a></li></ul><h3>Example Project</h3><ul><li><a href="https://github.com/FunnyDevP/dotnet-core-todolist">https://github.com/FunnyDevP/dotnet-core-todolist</a></li><li><a href="https://github.com/FunnyDevP/csharp_book_store">https://github.com/FunnyDevP/csharp_book_store</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=71d77b298486" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Swift101: Collection Types]]></title>
            <link>https://waranchit-ch.medium.com/swift101-collection-types-f2c94eb34dff?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/f2c94eb34dff</guid>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Sat, 10 Apr 2021 16:54:01 GMT</pubDate>
            <atom:updated>2021-04-10T16:54:01.901Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/966/1*8sSfv8HfncCdNTqvcozYdw.png" /></figure><p>Hi. Today, I would like to talk about Collection Types. The collection type is the data type for storing multiple elements in a single variable. There are several collection types in swift, but three important ones are array, dictionaries and sets.</p><h4>Array</h4><p><strong>What is an array?</strong></p><ul><li>It’s an ordered collection</li><li>It’s store multiple elements of the <strong>same type</strong></li><li>The element in the array are <strong>zero-indexed</strong>(the index of the first element is 0)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NJsTSiGLBajUyqqcBvTNZw.jpeg" /></figure><p><strong>Creating arrays</strong></p><ul><li>You can create an array with array literal.</li></ul><p><strong>Access elements</strong></p><ul><li>You can access an element in an array with subscript syntax</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5617fa3f531e4a523db4ca385e816750/href">https://medium.com/media/5617fa3f531e4a523db4ca385e816750/href</a></iframe><p><strong>Slicing array with <em>countable ranges</em></strong></p><ul><li>You can use the subscript syntax with countable ranges to fetch <em>more than a single value</em> from an array.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/93d57f29fcc7c1ac47c7b59a9ed57b02/href">https://medium.com/media/93d57f29fcc7c1ac47c7b59a9ed57b02/href</a></iframe><p><strong>Appending elements</strong></p><p>If you want to add an element to <em>the end of the array. Swift language provides 2 way for performing that, </em><strong><em>append(_:)</em></strong><em> and </em><strong><em>+=</em></strong><em> operator</em></p><ul><li><em>append(_:)</em></li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/70e3be337ab59d8d24afbdf40638f5b0/href">https://medium.com/media/70e3be337ab59d8d24afbdf40638f5b0/href</a></iframe><ul><li>+= operator</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/96e8c1dc96a274a1d8db1014c84d96ec/href">https://medium.com/media/96e8c1dc96a274a1d8db1014c84d96ec/href</a></iframe><p>as the example above, if you try to append anything other than string. The compiler will show an error…</p><blockquote>error: cannot convert value of type ‘Int’ to expected argument type ‘String’</blockquote><p><strong>Inserting elements</strong></p><p>If you want to add an element into an array with a specific position, you can use the method insert(_:at:) for performing that.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d81949f48577234fb176665391d9c6d/href">https://medium.com/media/9d81949f48577234fb176665391d9c6d/href</a></iframe><p>The at argument defines where you want to add the element. <em>Remember that the array is zero-indexed</em></p><p><strong>Iterating element on array with </strong><strong>for..in</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c7c39d46c6a0eaabb79b374e53f46839/href">https://medium.com/media/c7c39d46c6a0eaabb79b374e53f46839/href</a></iframe><p>as the example above, this is an iterate value from an array. if you need the index of each element, you can iterate over the return. value of the array’s enumerated() method.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f5fa563b224afa0d9cef3fa4ea255f8f/href">https://medium.com/media/f5fa563b224afa0d9cef3fa4ea255f8f/href</a></iframe><h4>Dictionaries</h4><p><strong>What is dictionaries ?</strong></p><ul><li>It’s an unordered collection of pairs</li><li>Each pair comprises a key and a value</li><li>Keys on dictionary is unique<strong> (The same key can’t appear twice in a dictionary)</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cS05kF634aAJf2jHKQ206A.png" /></figure><p><strong>Creating dictionaries</strong></p><ul><li>Using a dictionary literal</li><li>Dictionary literal is a list of key-value pairs separated by commas and enclosed in square brackets.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7726fade9cc83a44e65eb26d37615614/href">https://medium.com/media/7726fade9cc83a44e65eb26d37615614/href</a></iframe><p>When you print the dictionary, there’s no particular order to the pairs because the dictionary is <em>unordered</em>.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/baeff6c9416d8d5354ae1972f805f0d8/href">https://medium.com/media/baeff6c9416d8d5354ae1972f805f0d8/href</a></iframe><p>If you would like to create an empty dictionary, you can define the dictionary with [:]. Remember that, you must explicit data type, otherwise, its compiler can’t inter the type.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f8e4a66049fca6549d26e0e661181bb7/href">https://medium.com/media/f8e4a66049fca6549d26e0e661181bb7/href</a></iframe><p><strong>Accessing values</strong></p><ul><li>Using subscripting syntax for access value from the dictionary.</li><li>If the dictionary <strong>does</strong> find the key, it will return Optional type Optional(value) .</li><li>If the dictionary <strong>doesn’t</strong> find the key, it will return nil.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9e6572bfa55d74f3aab58171184778b6/href">https://medium.com/media/9e6572bfa55d74f3aab58171184778b6/href</a></iframe><p><strong>Modify Dictionary</strong></p><ul><li>You can using subscripting syntax for adding a new pair, update a value, and remove a pair</li></ul><p><em>Adding a value</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*nDTevAcVw7J9xhCszyaWHw.jpeg" /></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b808d1d70fc315042d1aaea31c0e5b2f/href">https://medium.com/media/b808d1d70fc315042d1aaea31c0e5b2f/href</a></iframe><p><em>Updating values</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/334b9d3ebfcdefa2422088b4da88734f/href">https://medium.com/media/334b9d3ebfcdefa2422088b4da88734f/href</a></iframe><blockquote>Subscripting syntax like a upsert . upsert mean’s if does find a key on dictionary, it’s update value but if does’t find a key on dictionary, it’s adding a new pair.</blockquote><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9246e01a03fe990035b5930288eed649/href">https://medium.com/media/9246e01a03fe990035b5930288eed649/href</a></iframe><p><em>Remove a pair</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1af1bfaf9d183e8078ae32c31ebedef8/href">https://medium.com/media/1af1bfaf9d183e8078ae32c31ebedef8/href</a></iframe><p><strong>Iterating Pairs</strong></p><ul><li>You can using for-in for iterating over a dictionary.</li><li>The items in a dictionary are pairs, you need to use a tuple</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/22c13bb99f7f899000c56d93cc13748a/href">https://medium.com/media/22c13bb99f7f899000c56d93cc13748a/href</a></iframe><p>If you would like to iterate over just the values, you can using values property and If you would like to iterate over just the keys, you can using keys property.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d654da3ce65b56e582c987a5ef74de4b/href">https://medium.com/media/d654da3ce65b56e582c987a5ef74de4b/href</a></iframe><h4>Sets</h4><p><strong>What is Sets ?</strong></p><ul><li>It’s an <em>unordered collection</em> of <em>unique value</em> of the <em>same type</em></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/690/1*JzT-9x7e6Fd9L_DAhR-IRg.png" /></figure><p><strong>Creating set</strong></p><ul><li>You can declare a set explicitly by writing struct Set followed by the type inside angle brackets</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6f5342c1e89c9cfb565b8d5c352ab98c/href">https://medium.com/media/6f5342c1e89c9cfb565b8d5c352ab98c/href</a></iframe><p>or you can using Set([element]) without explicit type</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/996049764459a554ed34d8a2354fba65/href">https://medium.com/media/996049764459a554ed34d8a2354fba65/href</a></iframe><h4>Conclusion</h4><p><strong>Array</strong></p><ul><li>Are <strong>ordered</strong> collections of values of the <strong>same type</strong></li><li>Use subscripting syntax =&gt; arr[index] to access and update element</li><li>Be wary of accessing an <strong>index that’s out of bounds</strong></li></ul><p><strong>Dictionaries</strong></p><ul><li>Are <strong>unordered</strong> collections of<em> </em><strong>key-value</strong> pairs.</li><li>The<em> </em><strong>keys</strong><em> </em>and <strong>values</strong> are all of the <strong>same type</strong></li><li>Use subscripting syntax =&gt; arr[key] to get values, added a new pair, update value by key, and remove pair.</li><li>The <strong>keys</strong> on dictionary is <strong>unique</strong></li></ul><p><strong>Sets</strong></p><ul><li>Are <strong>unordered</strong> collections of unique values of the <strong>same type</strong></li></ul><h4>References</h4><ol><li><a href="https://www.raywenderlich.com/books/swift-apprentice/v6.0">Swift Apprentice by raywenderlich Tutorial team</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f2c94eb34dff" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Swift101: Optional]]></title>
            <link>https://waranchit-ch.medium.com/swift101-optional-e9eb8c0fc24c?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/e9eb8c0fc24c</guid>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Sat, 20 Mar 2021 19:38:27 GMT</pubDate>
            <atom:updated>2021-03-20T19:38:27.475Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jWH-PAnDomdZpfE749ubCg.jpeg" /><figcaption>Photo by <a href="https://learnappmaking.com/swift-optionals-how-to/">learnappmaking</a></figcaption></figure><p>Optionals are Swift’s solution to the problem of representing both a value and the absence of a value nil.</p><p>Think of an optional as a box: it either contains exactly one value, or is empty. When it doesn’t contain a value, it’s said to contain nil</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*On0w-mNzX8b3gdzWoKCedg.png" /><figcaption>Photo by <a href="https://stackoverflow.com/questions/29054096/difference-between-optional-values-in-swift">stackoverflow</a></figcaption></figure><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ccebbb89105dbe4c80e469b2695d716a/href">https://medium.com/media/ccebbb89105dbe4c80e469b2695d716a/href</a></iframe><p>As the example above, You can describe that variable’s contain integer or nil</p><p><strong>When</strong> you define a variable as an optional type, that means the value is not a real type. Like the example above, errorCode isn’t an <em>Integer</em> type but it’s <em>optional of Integer. </em>If you would like to modify that value the result is Value of optional type &#39;Int?&#39; must be unwrapped to a value of type Int. So, when you would like to use a real value, you should be unwrapping that variable. the solution of unwrapping has a 4 way:</p><blockquote>Force Unwrapping</blockquote><blockquote>Optional Binding</blockquote><blockquote>Guard</blockquote><blockquote>Nil coalescing</blockquote><h4><strong>Force Unwrapping</strong></h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9dc7b790486aed3a95a1442a0de6743c/href">https://medium.com/media/9dc7b790486aed3a95a1442a0de6743c/href</a></iframe><p>The exclamation mark after the variable name tells the compiler that you would like to look inside the box and take out the value.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/688a80bb8d5e31ce2599b2a70ef20afb/href">https://medium.com/media/688a80bb8d5e31ce2599b2a70ef20afb/href</a></iframe><p>when you try to unwrap an optional variable with force unwrapping but that doesn’t contain a value, the error occurs:</p><blockquote>Fatal error: Unexpectedly found nil while unwrapping an Optional value</blockquote><p>How can you play it safe? You can use the if statement to check if the optional contains nil?. if it doesn’t, that means it contains a value and you can unwrap it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e9020ef7ab0604a7ae6510e2c7a2bb53/href">https://medium.com/media/e9020ef7ab0604a7ae6510e2c7a2bb53/href</a></iframe><h4><strong>Optional Binding</strong></h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d3584a81ce2a7b3eb8d86a0f09061a89/href">https://medium.com/media/d3584a81ce2a7b3eb8d86a0f09061a89/href</a></iframe><p>For this way, you don’t use<em> exclamation marks</em> for unwrapping value from the box.</p><p>You can define a constant variable on if statement.</p><ul><li>If the optional <strong>contains</strong> a value, this value is unwrapped and stored in, or bound to, the constant, and then the if statement <em>executes the if block.</em></li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/99f82eeb697ebe4de1b0b96082cc0dc0/href">https://medium.com/media/99f82eeb697ebe4de1b0b96082cc0dc0/href</a></iframe><ul><li>If the optional <strong>doesn’t contain</strong> a value, then the if statement <em>executes the else block.</em></li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c3ff0c321a64661d2f1d417ede0ac19a/href">https://medium.com/media/c3ff0c321a64661d2f1d417ede0ac19a/href</a></iframe><blockquote>Tips</blockquote><blockquote>it’s common practice to give the unwrapped constant the same name as the optional (<em>shadowing</em> that optional)</blockquote><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a575115fae4b253d72214840ffd3fb76/href">https://medium.com/media/a575115fae4b253d72214840ffd3fb76/href</a></iframe><p>You can unwrap <em>multiple values</em> at the same time:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e37ddeb389f81dfff624caa2eeb0df8a/href">https://medium.com/media/e37ddeb389f81dfff624caa2eeb0df8a/href</a></iframe><p>If you unwrap multiple values, It will <strong>only execute</strong> the if part of the statement <strong>when both optional contain a value.</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fa1d988bd5085a58353662a6ced01ebe/href">https://medium.com/media/fa1d988bd5085a58353662a6ced01ebe/href</a></iframe><h4>Guard</h4><p><strong>guard statement</strong> is<em> to check a condition and only continue executing a function if the condition is true.</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/53c1ea36ef0f15b696b08a608eab13b7/href">https://medium.com/media/53c1ea36ef0f15b696b08a608eab13b7/href</a></iframe><p>The guard statement comprises guard followed by a condition that can include both <em>Boolean expressions and optional binding, </em>followed<em> </em>by<em> </em>else<em>, </em>followed by<em> </em>a block of code covered by the else will execute if the condition is <em>false</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cXmoov_pxR6LIyYBnGoaDQ.png" /></figure><h4>Nil coalescing</h4><p>You can use it when you want to get a value out of the optional no matter what and in the case of nil, you’ll use a default value.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1022/1*Cmo57T78TeOlj3Zc4Atj5w.png" /></figure><h4>Conclusion</h4><ol><li>nil represents the absence of a value</li><li>Non-optional variables and constants are <strong>never</strong> nil</li><li>Optional are <strong>like boxes</strong> that can contain a value or be empty(nil)</li><li>To work with the value inside an optional, you <strong>must</strong> first unwrap it from the optional.</li><li>The safest ways to unwrap an optional’s value is by using <strong>optional binding </strong>or <strong>nil coalescing</strong>. Use <strong>forced unwrapping</strong> only when appropriate, as it could produce a runtime error</li><li>You can guard let to bind an optional. If the binding fails. the compiler forces you to exist the current function</li></ol><h4>References</h4><ol><li><a href="https://www.raywenderlich.com/books/swift-apprentice/v6.0">Swift Apprentice by raywenderlich Tutorial team</a></li><li><a href="https://learnappmaking.com/swift-optionals-how-to/">Optional in Swift: The ultimate guide</a></li><li><a href="https://stackoverflow.com/questions/29054096/difference-between-optional-values-in-swift">Difference between optional values in swift?</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e9eb8c0fc24c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SwiftUI The series: Layout 101]]></title>
            <link>https://waranchit-ch.medium.com/swiftui-the-series-layout-101-cd9f147113da?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/cd9f147113da</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Tue, 16 Mar 2021 17:25:39 GMT</pubDate>
            <atom:updated>2021-03-16T17:25:39.713Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MmrMR0nuyHy7ax31l3-98Q.jpeg" /></figure><h4>View Protocol</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b324a6ae3226583a87a7ed5e42b8c5be/href">https://medium.com/media/b324a6ae3226583a87a7ed5e42b8c5be/href</a></iframe><ul><li>It’s responsible for <em>display user interface.</em></li><li>It’s must implement <em>compute property</em> body, that’s responsible for display view on the user interface</li></ul><h4>Layout</h4><p>The body property(View protocol) must return one view . If you would like to display multiple view on user interface, you can use Stack for group multiple views in one single view.</p><p><strong>Stack</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/724/1*Uw0y-D2u61miMH6SESYSMg.jpeg" /><figcaption>Photo by <a href="https://ichi.pro/">https://ichi.pro</a></figcaption></figure><blockquote>VStack</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/185/1*PnwibuBIu_jR3zOU_LG83A.png" /><figcaption>photo by google.com</figcaption></figure><ul><li>It’s Display multiple views by <em>vertical alignment</em></li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/18d21a7e4633d7c303ef06b144a031b9/href">https://medium.com/media/18d21a7e4633d7c303ef06b144a031b9/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/338/1*J05F2lQ_Tk0hXCj4i9yUXg.png" /></figure><ul><li>By default, the views inside a Vstack are <em>aligned to the center</em></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AmOfw6-e0xXz2vg4FzkC0g.png" /><figcaption>example VStack alignment attribute</figcaption></figure><blockquote>HStack</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/348/1*t0BoDKoyxn8QDuyILU5kQg.png" /><figcaption>photo by google.com</figcaption></figure><ul><li>It’s Display multiple views by <em>Horizontal alignment</em></li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c59d0e36c6741c311ba4222f514dd998/href">https://medium.com/media/c59d0e36c6741c311ba4222f514dd998/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/570/1*r6nJzGuK5saFm2zADT0Z1g.png" /></figure><p>By default, the view in a horizontal stack are<em> aligned to the center</em> and positioned with standard space in between (usually 8 points)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SuV6ztdbFTnYoB95l36ptA.png" /><figcaption>example HStack alignment attribute</figcaption></figure><p><strong>Spacer</strong></p><p>The alignment options available for <em>VStack and HStack</em><strong> </strong>views align the view in the opposite axis</p><ul><li>Vertical stack(VStack) can align the views horizontally</li><li>Horizontal stack(HStack) can align the views vertically</li></ul><ol><li>Vertical stack(VStack)</li></ol><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/639bd92833b4efe5bdcf73a38b51f966/href">https://medium.com/media/639bd92833b4efe5bdcf73a38b51f966/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hA1ReuYD3WRA9xEsEj1Vew.png" /></figure><p>2. Horizontal stack(HStack)</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff5d96797e19e9495122421b3d46cb92/href">https://medium.com/media/ff5d96797e19e9495122421b3d46cb92/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8a5RskH0GUgSa5G-FcGWkQ.png" /></figure><p><strong>Group</strong></p><p>The purpose of the Group is to group multiple views that applying the same modifier</p><p>below, this is an example for creating views that using the same modifier.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3a997a7b0fb46fc87c0e747e75daaef1/href">https://medium.com/media/3a997a7b0fb46fc87c0e747e75daaef1/href</a></iframe><p>As the example above, you can see that multiple views are using the same modifier that Causing redundant modifiers.</p><p>You can be using Group to reduce redundant modifier</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ff2167b66a90b7e68e94b3c6794f96f3/href">https://medium.com/media/ff2167b66a90b7e68e94b3c6794f96f3/href</a></iframe><h4>References</h4><ul><li><a href="https://www.amazon.com/SwiftUI-Masterminds-advantage-insanely-iPhones-ebook/dp/B084R76T4D">SwiftUI for Masterminds by J.D Gauchat</a></li></ul><blockquote>As the content above, that’s layout fundamental. The next episode, I’m telling about State on SwiftUI. Please to be continued.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cd9f147113da" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Golang: integration test with testcontainer]]></title>
            <link>https://waranchit-ch.medium.com/golang-integration-test-with-testcontainer-77ac5ef6dfed?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/77ac5ef6dfed</guid>
            <category><![CDATA[testcontainer]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[integration-testing]]></category>
            <category><![CDATA[mongodb]]></category>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Sat, 27 Feb 2021 13:30:00 GMT</pubDate>
            <atom:updated>2021-02-27T13:30:00.488Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NjXzaw15-2QPs5dHRW9fmg.png" /><figcaption>photo by : <a href="https://www.testcontainers.org/">https://www.testcontainers.org</a></figcaption></figure><h3>Introduction</h3><p>สวัสดีครับ วันนี้จะมาแชร์ตัวอย่างการทำ integration test กับ mongodb โดยใช้ ภาษา golangและใช้ library ที่ชื่อ testcontainer-goโดยจะเป็นตัวช่วยสร้าง container เพื่อใช้สำหรับ test และเมื่อ test เสร็จ มันก็จะจัดการ remove container ให้เองเลย ทำให้ง่ายและสะดวกสบายต่อการทำ integration test</p><p>แล้วทำไมเราถึงต้องทำ integration test ด้วยละ ทำแค่ unit test อย่างเดียวพอไหม ? ส่วนตัวผมมองว่า unit test ยังไงก็ต้องมีอยู่แล้ว แต่การทำ integration test จะเป็นเหมือนการ test ของ flow นั้น ๆ ทั้งเส้น เช่น การ test http handler หรือแม้แต่การ test กับ process ที่เราต้องไปติดต่อกับ external server เช่น การ request ไปหา third-party หรือ การ query ตัว database เป็นต้น ส่วนใครที่อยากรู้เพิ่มเติมเกี่ยวกับการ testing สามารถเข้าไปอ่านได้ที่ <a href="https://iamgique.medium.com/%E0%B8%88%E0%B8%B3%E0%B9%81%E0%B8%99%E0%B8%81-user-interface-tests-integration-tests-%E0%B9%81%E0%B8%A5%E0%B8%B0-unit-tests-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-test-pyramid-1afb6e34c70d">Test Pyramid</a></p><h3>Coding</h3><ol><li>initial project ด้วย go mod init {github repo}</li><li>install library</li></ol><ul><li>mongodb : go get go.mongodb.org/mongo-driver/mongo</li><li>testcontainer-go : go get github.com/testcontainers/testcontainers-go</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2c04f10149094fa1e858afe2de1803dd/href">https://medium.com/media/2c04f10149094fa1e858afe2de1803dd/href</a></iframe><p>ในส่วนด้านล่างนี้จะเป็น ส่วนของการเตรียมสภาพแวดล้อมสำหรับการ test</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7a544e0edad17142991727b4aa15e71e/href">https://medium.com/media/7a544e0edad17142991727b4aa15e71e/href</a></iframe><p><strong>หมายเลข 1:</strong> กำหนดว่าเราจะใช้ image อะไรในการสร้าง container นั้นๆ เพื่อใช้ในการ testing</p><p><strong>หมายเลข 2:</strong> สร้าง container จาก image ที่เรากำหนดจาก <em>หมายเลข 1</em></p><p><strong>หมายเลข 3:</strong> get host และ port เพื่อใช้ในการเชื่อมต่อกับ mongodb</p><p><strong>หมายเลข 4:</strong> การเตรียม process clean up container</p><p><strong>หมายเลข 5:</strong> สร้าง mongo client โดย connect ไปที่ host ของ container ที่เราสร้างไว้ก่อนหน้านี้</p><p>code แบบ เต็มๆ</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0c7920a47327f6d2c7c37af961b715a3/href">https://medium.com/media/0c7920a47327f6d2c7c37af961b715a3/href</a></iframe><pre><em>// </em><strong><em>+build</em></strong><em> integration</em></pre><pre>เปรียบเสมือการ แปะว่า test ของ file นี้จะเป็น integration test นะ  จุดประสงค์คือเราต้องการจะแบ่งแยกระหว่าง unit test และ integration test</pre><pre>โดย คำสั่ง run test สำหรับ integration test คือ </pre><pre>go test -tags=integration ./...</pre><pre>--------------------------------------------------------------------</pre><pre>// <strong><em>+build</em></strong><em> !integration</em></pre><pre>เปรียบเสมือการ แปะว่า test ของ file นี้จะเป็น unit test นะ</pre><pre>โดยคำสั่ง run test สำหรับ unit test คือ</pre><pre>go test ./...</pre><pre>*** tag build เราต้องใส่ไว้ที่ บรรทัดแรกของ file</pre><h3>References</h3><ol><li><a href="https://golang.testcontainers.org/">https://golang.testcontainers.org</a></li><li><a href="https://github.com/mongodb/mongo-go-driver">https://github.com/mongodb/mongo-go-driver</a></li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=77ac5ef6dfed" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[System design The series: EP1. What is Reliability ?]]></title>
            <link>https://waranchit-ch.medium.com/system-design-the-series-ep1-what-is-reliability-aa7d5eae0f40?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/aa7d5eae0f40</guid>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Sun, 31 Jan 2021 07:22:46 GMT</pubDate>
            <atom:updated>2021-01-31T16:38:35.424Z</atom:updated>
            <content:encoded><![CDATA[<h3>System design The series: Reliability</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/991/1*xvrm3mQlIylLIT5U69xjJw.jpeg" /></figure><h3>Introduction</h3><p>ช่วงนี้เริ่มศึกษาเกี่ยวกับ system design โดยส่วนตัวอยากรู้ว่า หากเราจะ design ระบบสักอันนึงเนี่ย นอกจากตัว programming language แล้ว มันต้องรู้อะไรบ้างนะ เพื่อที่จะตัดสินในการเลือก tool ให้เหมาะสม กับ แอพลิเคชัน หรือ จะออกแบบระบบยังไงให้มีความทนทานในกรณีที่เกิดความเสียหาย จึงได้เริ่มต้นศึกษาจากหนังสือที่ชื่อว่า <strong>Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems ของ </strong><a href="https://www.amazon.com/Martin-Kleppmann/e/B00Q43XKD6/ref=dp_byline_cont_book_1">Martin Kleppmann</a> ซึ่งเป็นหนังสือที่หลาย ๆ เว็บไซต์แนะนำสำหรับผู้เริ่มต้นจะศึกษาเกี่ยวกับ system design</p><h3>Reliability</h3><p><em>Reliability ก็คือ </em>การที่ตัวระบบของเรานั้น <strong>ควร</strong> ที่จะสามารถทำงานได้อย่างถูกต้อง แม้ว่าตัวระบบของเราเจอกับความผิดพลาดบางอย่าง โดยความผิดพลาดในที่นี้ อาจจะมาจากตัว software หรือ hardware หรือจากตัวคนเราเองก็เป็นได้. โดยคุณสมบัติทั่วไปของระบบที่มีความ Reliability นั้น</p><ul><li>ตัวระบบสามารถทำงานได้ถูกต้องตามที่ user คาดหวังให้มันเป็น</li><li>ตัวระบบสามารถ<em>ทนทานต่อความเสียหาย (fault-tolerant) </em>ที่อาจจะเกิดขึ้น ไม่ว่าจะจากตัว user เอง หรือเกิดจากการที่ตัว software ของเราทำงานผิดพลาด เช่น หากเกิดความผิดพลาดบางอย่างขึ้น ตัวระบบ จะยังคงทำงานต่อไปได้ ไม่ใช่. เกิดปุ๊ป ตัวระบบก็ล้มหายตายจากปั๊ป มันก็จะเร็วป๊ายยยยย</li><li>ตัวระบบต้องสามารถป้องกันทุกการเข้าถึงโดยที่ไม่ได้รับอนุญาติ(Unauthorization) เช่น ตัวระบบไม่ควรให้ผู้ใช้เข้าถึงข้อมูลได้ หากผู้ใช้ไม่ทำการ login เข้าสู่ระบบซะก่อน</li></ul><p>จากที่อ่านไปข้างต้น ความเสียหายมักจะมาจาก คน ไม่ก็ Hardware</p><p><strong>Hardware Faults</strong></p><p>ความผิดพลาดในด้าน hardware มักจะมีสาเหตุ เช่น hard disk crash. RAM เกิดความเสียหาย หรือแม้แต่ มีการหลุดของสาย network.</p><p><strong>Human faults</strong></p><p>หรือง่าย ๆ ก็คือเป็นความผิดพลาดที่มักจะมีสาเหตุมาจากตัวคนนั่นเอง โดยตัวอย่างเช่น จากการศึกษา ตัว internet service ที่มีขนาดใหญ่ พบว่า การ configuration ตัวระบบผิด เกิดขึ้นบ่อยมากเมื่อเทียบ <em>ความผิดพลาดด้าน Hardware (Hardware faults) ซึ่งท่าที่พอจะมาสารถหลีกเลี่ยงความผิดก็จะมี …</em></p><ul><li><em>Decoupling:</em> ในการ design ตัวระบบนั้น เราควรจะ design ให้ไม่ขึ้นตรงกับใคร หรือก็คือไม่ depend กับตัวอื่น ๆ เช่น เรามี class A และ class A Depends on Class B สิ่งที่เกิดขึ้นคือ หาก class A มีการแก้ไข class B ก็จะโดนไปด้วย ทางที่ดีเราควรออกแบบให้แต่ละตัวแยกออกจากกันไปเลย หาก แก้ไข class A ก็โดนแค่ A ส่วน class B ก็ยังคงทำงานได้เป็นปกติ</li><li><em>Testing:</em> อีกท่าที่ใช้ป้องกันความผิดพลาดที่เกิดจากคนเรา ก็คือ ต้องมีการ testing ในทุกๆ level ไม่ว่าจะเป็น unit test, integration test, หรือแม้แต่ automate test</li><li><em>Monitoring:</em> ควรมีการทำ monitoring เพื่อใช้เช็คว่า ปัญจุบันตัวระบบของเรานั้น ยังสุขภาพดี ทำงานดีเหมือนเดิมอยู่หรือเปล่า ซึ่งหากเกิดความผิดพลาดขึ้น เราจะได้รู้ตัวได้เร็ว และแก้ไขปัญหาได้อย่างรวดเร็ว</li></ul><h3>Conclusion</h3><ul><li>Reliability ส่วนตัวผมมองว่ามันเป็นแนวคิดนึงในการออกแบบระบบ ที่ช่วยให้ตัวเราตอนออกแบบนั้น คำนึงถึงหลาย ๆ ปัจจัย ไม่ว่าจะเป็นการออกแบบให้ตัวระบบนั้นทำงานได้ถูกต้องตามที่ผู้ใช้คาดหวังให้มันเป็น หรือแม้แต่ ความสามารถในการทนทานต่อความผิดพลาดที่เกิดขึ้น(fault-tolerance) ทั้งจาก Hardware, Software หรือ Human Error แต่อย่าเข้าใจผิดคิดว่าหากเราออกแบบให้ตัวระบบของเรานั้น มีความ reliability แล้วมันจะสามารถทนทานต่อทุกความเสียหายที่เกิดขึ้น ซึ่งพูดตามความเป็นจริงคือ …. <strong><em>มันเป็นไปไม่ด้ายยยยย</em></strong></li></ul><h3>References</h3><ol><li><a href="https://www.amazon.com/Designing-Data-Intensive-Applications-Reliable-Maintainable/dp/1449373321">Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems By Martin Kleppmann</a></li><li><a href="https://softwareengineering.stackexchange.com/questions/244476/what-is-decoupling-and-what-development-areas-can-it-apply-to">What is Decoupling ?</a></li></ol><h3>Next…</h3><p>ในส่วนตัวไปจะเป็นเรื่อง เกี่ยวกับ <em>Scalability </em>โปรดติดตามตอนต่อไป…</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aa7d5eae0f40" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Golang X GRPC: Protobuf nullable type]]></title>
            <link>https://waranchit-ch.medium.com/golang-x-grpc-protobuf-nullable-type-a6958804702?source=rss-17ea0fe821f9------2</link>
            <guid isPermaLink="false">https://medium.com/p/a6958804702</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[grpc-gateway]]></category>
            <category><![CDATA[protobuf]]></category>
            <category><![CDATA[grpc]]></category>
            <dc:creator><![CDATA[Waranchit Chaiwong]]></dc:creator>
            <pubDate>Thu, 01 Oct 2020 15:42:35 GMT</pubDate>
            <atom:updated>2020-10-01T15:42:35.129Z</atom:updated>
            <content:encoded><![CDATA[<p>ณ ปัจจุบันเราได้มีการเล่นกับ grpc-gateway อยู่พอสมควร ตอนแรก ๆ มันก็ดีมากนะ แปลกใหม่ดี จนมาเจอข้อกำหนดบางอย่างที่ว่า ในตอน response ออกไปหา client ถ้า field ไหนไม่มีค่า ให้แสดงค่า null แทน…. อ๊าววว จะเอาไงดีละทีเนี่ย เพราะโดยปกติตัว scalar type ของ protobuf message มันกำหนดเป็น null ไม่ได้ (ใน Go ก็คือของที่เป็น pointer type นั่นเอง).</p><h4>Message field type with Message</h4><p>โดยปกติแล้ว ถ้าอยากให้ <em>message field</em> สามารถป้อนค่า <em>nil</em> ได้ เราก็แค่กำหนด type ของ <em>message field </em>นั้น ๆ ให้เป็น <em>message</em> ซะก็จบ เช่น</p><pre>message M1 {<br>    M2 data = 1;<br>}<br><br>message M2 {<br>    string value = 1;<br>}</pre><p>จากตัวอย่างการประกาศ message ด้านบน หมายความว่า field data ใน message M1 สามารถ <em>มีค่าหรือไม่มีค่าก็ได้</em> เพราะเมื่อเราสั่ง generate protobuf แล้ว มันจะได้ struct ตามด้านล่าง</p><pre><em>type </em>M1 <em>struct </em>{<br>   state         protoimpl.MessageState<br>   sizeCache     protoimpl.SizeCache<br>   unknownFields protoimpl.UnknownFields<br><br>   Data *M2 `protobuf:&quot;bytes,1,opt,name=data,proto3&quot; json:&quot;data,omitempty&quot;`<br>}</pre><p>จากที่เห็นตาม code ด้านบน field data จะมี type เป็น *M2(Pointer of M2).</p><pre>msg := M1{Data: <em>nil</em>}<br>marshaller := runtime.JSONPb{EmitDefaults: true}<br>b, _ := marshaller.Marshal(&amp;msg)</pre><pre><strong>Result<br></strong>{&quot;data&quot;:null}</pre><p>จาก code ด้านบน ในที่สุดเราก็ได้ท่าที่ตอบโจทย์สักที เย้ๆๆๆๆๆ. แต่เดี๋ยวก่อน ในทางกลับกัน ถ้า field Data มีค่าละ json ที่ออกมามันก็ควรจะเป็น …</p><p><strong><em>{“data”: “test”}</em></strong></p><p>แต่ ดั๊นนนนมีเซอร์ไพรส์ซะงั้น. เพราะหลังจากที่เรากำหนดค่าให้ Data มันกลับได้ออกมาเป็น…</p><p><strong><em>{“data”: {“value”: “test”}}</em></strong></p><p>เอ๊…ทำไมมันถึงเป็นแบบนี้ละน๊อออออ ติ๊กต็อกๆๆ. ก็ไม่แปลกหรอก เพราะถ้าเราประกาศ <em>message field type</em>ให้เป็น <em>message</em> มันก็เหมือนเราทำ <em>nested struct</em> นั่นเอง. ถ้างั้นมันจะมีวิธีอื่นไหมละ ที่จะตอบโจทย์ทั้งแบบ<em>มีค่าและไม่มีค่า</em></p><h4>Wrapper type (Well-Known Types)</h4><p>จริงๆแล้ว protobuf จะมีสิ่งที่เรียกว่า Wrapper type ซึ่งจริงๆแล้วมันก็เหมือนการเอา scalar type มาห่อให้เป็น message นั่นเอง เช่น</p><pre>string =&gt; google.protobuf.StringValue<br>int32 =&gt; google.protobuf.Int32Value<br>int64 =&gt; google.protobuf.Int64Value</pre><blockquote>จริงๆมีเยอะกว่านี้ อยากดูเพิ่มก็กดเข้าไปเลยยย <a href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf">https://developers.google.com/protocol-buffers/docs/reference/google.protobuf</a></blockquote><p>จากนั้น เราก็ไปแก้ message field type data ให้เป็น wrapper type</p><pre>message M1 {<br>    google.protobuf.String data = 1;<br>}<br>// อย่าลืม import &quot;google/protobuf/wrappers.proto&quot;; ด้วยยย</pre><p>หลังจากที่ generate proto แล้ว ทีนี่เราจะได้ struct ที่มีหน้าตา</p><pre><em>type </em>M1 <em>struct </em>{<br>   state         protoimpl.MessageState<br>   sizeCache     protoimpl.SizeCache<br>   unknownFields protoimpl.UnknownFields<br><br>   Data *wrappers.StringValue `protobuf:&quot;bytes,1,opt,name=data,proto3&quot; json:&quot;data,omitempty&quot;`<br>}</pre><p>ไหน ๆ เราก็ได้ struct โฉมใหม่ละ ไหนลองซิ มันจะได้ตามที่เราต้องการหรือเปล่า</p><pre><em>// 1. แบบไม่มีค่า</em><br>msg := M1{Data: <em>nil</em>}<br>marshaller := runtime.JSONPb{EmitDefaults: true}<br>b ,_ := marshaller.Marshal(&amp;msg)</pre><pre><strong>Result<br></strong><em>{&quot;data&quot;:null}</em></pre><pre><em>// 2. แบบมีค่า</em><br>msg := M1{Data: &amp;wrapper.StringValue{Value: &quot;test&quot;}}<br>marshaller := runtime.JSONPb{EmitDefaults: true}<br>b ,_ := marshaller.Marshal(&amp;msg)</pre><pre><strong>Result<br></strong><em>{&quot;data&quot;:&quot;test&quot;}</em></pre><p>ในที่สุดดดด เราก็ได้วิธีที่ตอบโจทย์ที่สุดละ นั่นคือการประกาศตัว message field type ให้เป็นแบบ Wrapper type…..</p><h4><strong>References</strong></h4><p><a href="https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#int32value">https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#int32value</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a6958804702" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>