<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-26659265</id><updated>2024-09-08T23:21:11.432+07:00</updated><category term="Golang"/><category term="Javascript"/><category term="erlang"/><category term="TDD"/><category term="java"/><category term="linux"/><category term="ruby"/><category term="Angularjs"/><category term="python"/><category term="haskell"/><category term="java 8"/><category term="jquery"/><category term="Clojure"/><category term="functional programming"/><category term="Django"/><category term="Jasmine"/><category term="Map"/><category term="command line"/><category term="git"/><category term="php"/><category term="Coldfusion"/><category term="Spy"/><category term="android"/><category term="html5"/><category term="ubuntu"/><category term="Go"/><category term="Grails"/><category term="HTTP"/><category term="Lambda"/><category term="Railo"/><category term="Template"/><category term="Unix"/><category term="Websocket"/><category term="Xojo"/><category term="mongodb"/><category term="nginx"/><category term="node.js"/><category term="otp"/><category term="time"/><category term="vim"/><category term="Agile"/><category term="CFML"/><category term="Clean Code"/><category term="Data Type"/><category term="Dependency Injection"/><category term="event"/><category term="html"/><category term="install"/><category term="oop"/><category term="phonegap"/><category term="reduce"/><category term="shell"/><category term="short ruby"/><category term="Actionscript 3"/><category term="Annotation"/><category term="Data Mining"/><category term="Directive"/><category term="Gradle"/><category term="Kata"/><category term="Knockout"/><category term="Liferay"/><category term="Mock"/><category term="MySQL"/><category term="Pair Programming"/><category term="Philosophy"/><category term="Quote"/><category term="Rust"/><category term="Tip"/><category term="ajax"/><category term="book"/><category term="brew"/><category term="c"/><category term="canvas"/><category term="cofeescript"/><category term="concurrency"/><category term="config"/><category term="copy"/><category term="craftsmanship"/><category term="date"/><category term="filter"/><category term="functional"/><category term="groovy"/><category term="init"/><category term="mocha"/><category term="new habit"/><category term="npm"/><category term="on"/><category term="scrum"/><category term="spring"/><category term="sprint3r"/><category term="team"/><category term="Array"/><category term="Assembly"/><category term="BDD"/><category term="BTS"/><category term="Block"/><category term="CSS"/><category term="Channel"/><category term="Concept"/><category term="Context"/><category term="Data Binding"/><category term="Design Pattern"/><category term="Dojo"/><category term="Dos"/><category term="Elixir"/><category term="Field"/><category term="GNU Assembler"/><category term="GoF"/><category term="HTTPS"/><category term="Hibernate"/><category term="IO"/><category term="JS"/><category term="Liverpool"/><category term="Mail"/><category term="OS X"/><category term="Object"/><category term="Opensource"/><category term="Postfix"/><category term="Practice"/><category term="Product"/><category term="RPC"/><category term="RealBasic"/><category term="Request"/><category term="Robotframework"/><category term="SMTP"/><category term="Server"/><category term="Software"/><category term="Starling"/><category term="Statement"/><category term="Static"/><category term="TestBox"/><category term="Training"/><category term="Trick"/><category term="Turbo C"/><category term="Uncle Bob"/><category term="Windows"/><category term="architecture"/><category term="binding"/><category term="business"/><category term="company"/><category term="container"/><category term="docker"/><category term="ember.js"/><category term="facebook"/><category term="fizzbuzz"/><category term="function"/><category term="generate"/><category term="gettext"/><category term="grep"/><category term="infoq"/><category term="interface"/><category term="java platform"/><category term="keyword"/><category term="language"/><category term="library"/><category term="list"/><category term="mac osx"/><category term="machine learning"/><category term="method"/><category term="mvc"/><category term="osx"/><category term="package"/><category term="padrino"/><category term="private"/><category term="process"/><category term="programmer"/><category term="programming"/><category term="programming language"/><category term="reading"/><category term="rebar"/><category term="regular expression"/><category term="rest"/><category term="scope"/><category term="selector"/><category term="set"/><category term="sinatra"/><category term="split"/><category term="ssh"/><category term="t2decode"/><category term="tax"/><category term="thin"/><category term="tmux"/><category term="upload"/><category term="user interface"/><category term="utf8"/><category term="web server"/><category term="webview"/><category term="zip"/><category term="ทะเล"/><category term="ทักษะ"/><category term="บุรีรัมย์"/><category term="ภาษี"/><category term="หนังสือ"/><category term="อาชีพ"/><category term="$broadcast"/><category term="$interval"/><category term="$on"/><category term="$rootScope"/><category term="$scope"/><category term="$watch"/><category term="13H"/><category term="2013"/><category term="2014"/><category term="365 day"/><category term="3D scanning"/><category term="5P"/><category term="API"/><category term="AST"/><category term="ATDD"/><category term="AWS"/><category term="Abstract Syntax Tree"/><category term="Access"/><category term="Actor Model"/><category term="AdaBoost"/><category term="Adapters"/><category term="AddHandler"/><category term="Ag"/><category term="Algorithms"/><category term="Amazon Elastic Beanstalk"/><category term="Amazon S3"/><category term="Apriori"/><category term="Arsenal"/><category term="Assembler"/><category term="Atom"/><category term="Auth"/><category term="BCBK4"/><category term="Bangkok"/><category term="Barcamp Bangkhen 4"/><category term="Bas Vodde"/><category term="Bash"/><category term="BigData"/><category term="Boy Scout Rule"/><category term="Build"/><category term="Built-in web server"/><category term="C Link"/><category term="C++"/><category term="C4.5"/><category term="CART"/><category term="CF"/><category term="Card"/><category term="Category Theory"/><category term="Chanwit Kaewkasi"/><category term="Classification and Regression Trees"/><category term="Code as Data"/><category term="CodeIgniter"/><category term="Confirmation"/><category term="Conversation"/><category term="Course"/><category term="Course Online"/><category term="Cowboy"/><category term="Cross Origin"/><category term="Culture"/><category term="Cursor"/><category term="D3.js"/><category term="DB25"/><category term="DCI"/><category term="Datasource"/><category term="Decision Tree"/><category term="Decorator"/><category term="Django-Storages"/><category term="Do"/><category term="Donald"/><category term="Doug McIlroy"/><category term="Drag"/><category term="Dropbox"/><category term="Dropwizard"/><category term="EM"/><category term="Elastic Beanstalk"/><category term="Election"/><category term="Email"/><category term="Embed"/><category term="End Credit"/><category term="English"/><category term="Erlang 17"/><category term="Erlang built-in term storage"/><category term="Error"/><category term="FAT Radio"/><category term="Fail Tolerance"/><category term="FileField"/><category term="Fill"/><category term="Flash"/><category term="Flex"/><category term="Form"/><category term="Framwork"/><category term="Functor"/><category term="Future"/><category term="GAS"/><category term="GOPATH"/><category term="GOROOT"/><category term="GVM"/><category term="Geeky Academy Batch 2"/><category term="Gist"/><category term="Google"/><category term="Goroutine"/><category term="Graphics"/><category term="Group"/><category term="H2"/><category term="HSQL"/><category term="HUnit"/><category term="Hexagonal"/><category term="Higher Order Function"/><category term="Hook"/><category term="IDEO"/><category term="IP"/><category term="Immutable"/><category term="Injection"/><category term="Innovation"/><category term="Input"/><category term="IntelliJ"/><category term="Iron"/><category term="Isolate"/><category term="JSON"/><category term="Jenkins"/><category term="Jersey"/><category term="Just Do It"/><category term="Just For Fun"/><category term="K-Means"/><category term="KDD"/><category term="Ken Thompson"/><category term="Keough"/><category term="Knockoutjs"/><category term="Lazy Evaluation"/><category term="Lean Startup"/><category term="Learning Test"/><category term="Len Cylinder"/><category term="License"/><category term="Light"/><category term="Linus"/><category term="List Comprehension"/><category term="Love"/><category term="MIME"/><category term="MVVM"/><category term="Make"/><category term="Mark Zuckerberg"/><category term="MarkSpec"/><category term="Martin"/><category term="Maslow&#39;s"/><category term="Math"/><category term="Maven"/><category term="Measure It"/><category term="Message Passing"/><category term="Micro computer"/><category term="Microservice"/><category term="Migration"/><category term="Mike Cohn"/><category term="MinGW"/><category term="MockBox"/><category term="Mode"/><category term="Model"/><category term="Monad"/><category term="Monadic"/><category term="MondayPuzzle"/><category term="Mouse"/><category term="Movie"/><category term="Mutable"/><category term="My.Droppages"/><category term="NVD3.js"/><category term="Naive Bayes"/><category term="NanoHTTPD"/><category term="No if"/><category term="OCR"/><category term="ORMs"/><category term="OS"/><category term="OpenBD"/><category term="Oplog"/><category term="Oriented"/><category term="Output"/><category term="PDF"/><category term="PageRank"/><category term="Parallel"/><category term="Partnerships"/><category term="Passion"/><category term="Pattern"/><category term="Pattern Matching"/><category term="People"/><category term="Philosopy"/><category term="Planning Poker"/><category term="Portal"/><category term="Portlet"/><category term="Ports"/><category term="Power"/><category term="Preprocessor"/><category term="Purpose"/><category term="Push stream module"/><category term="RDS"/><category term="RESTful"/><category term="Reactive Programming"/><category term="Referential transparency"/><category term="Regex"/><category term="Release"/><category term="Replace"/><category term="Respect my Vote"/><category term="Review"/><category term="Rob Pike"/><category term="Robert"/><category term="Routine"/><category term="Rustlang"/><category term="Rx"/><category term="SBE"/><category term="SQL"/><category term="STAMP"/><category term="SUT"/><category term="SVM"/><category term="Scatter Plot"/><category term="Scenario"/><category term="Science"/><category term="Scientific Method"/><category term="Simple is the best"/><category term="Skoode Skill"/><category term="Slot Machine"/><category term="Small"/><category term="Socket"/><category term="Spock"/><category term="Spring MVC"/><category term="StartupSurvival"/><category term="Stereotype"/><category term="Structure"/><category term="Sudoku"/><category term="Support Vector Machines"/><category term="TCP"/><category term="Tense"/><category term="Tesseract"/><category term="Test First"/><category term="Thailand"/><category term="The Avengers"/><category term="Think like Zuck"/><category term="Thread"/><category term="Top Ten"/><category term="Torvalds"/><category term="Tour"/><category term="Translate"/><category term="True Incube"/><category term="Trust"/><category term="UX"/><category term="Uncle Bob Martin"/><category term="User Stories"/><category term="User Story"/><category term="VCS"/><category term="Vagrant"/><category term="View"/><category term="ViewModel"/><category term="Web Component"/><category term="Web Content"/><category term="Win"/><category term="Without Frramework"/><category term="YWNA"/><category term="abstraction"/><category term="accounting"/><category term="adapt"/><category term="addEventListener"/><category term="adobe air"/><category term="alias"/><category term="amdahl&#39;s law"/><category term="animate"/><category term="ant"/><category term="apply"/><category term="archive"/><category term="arguments"/><category term="assignment"/><category term="audio"/><category term="automate"/><category term="awk"/><category term="bag"/><category term="basic"/><category term="behavior"/><category term="binary"/><category term="bookmark"/><category term="bootloader"/><category term="broadcast"/><category term="buffer"/><category term="bundle"/><category term="byte"/><category term="call"/><category term="callback function"/><category term="caps lock"/><category term="career"/><category term="cat"/><category term="center"/><category term="change"/><category term="charset"/><category term="checkbox"/><category term="chicken"/><category term="class"/><category term="clone"/><category term="cloud"/><category term="cmd"/><category term="coach"/><category term="code.org"/><category term="coding"/><category term="collate"/><category term="collect"/><category term="come back to blogger"/><category term="compile"/><category term="computed"/><category term="concurrent"/><category term="condition"/><category term="condition loop"/><category term="constant"/><category term="contains"/><category term="content type"/><category term="contenteditable"/><category term="controller"/><category term="craftsman"/><category term="create database"/><category term="credit"/><category term="cross"/><category term="cross functional"/><category term="crypto"/><category term="csv"/><category term="data"/><category term="data structure"/><category term="debit"/><category term="declaration binding"/><category term="declarative"/><category term="declarative bindings"/><category term="delay"/><category term="delegate"/><category term="device-width"/><category term="dict"/><category term="dictionary"/><category term="distributed"/><category term="down"/><category term="drawstring"/><category term="duplicate_bag"/><category term="duration"/><category term="easymotion"/><category term="edit"/><category term="effect"/><category term="element"/><category term="embedded"/><category term="esc"/><category term="esys"/><category term="esys-particle"/><category term="ets"/><category term="experience"/><category term="expression"/><category term="extend"/><category term="extension name"/><category term="fail wall"/><category term="falsy"/><category term="feed"/><category term="file name"/><category term="fileutils"/><category term="find"/><category term="firewire"/><category term="flag"/><category term="flatMap"/><category term="flush"/><category term="for"/><category term="forEach"/><category term="form wizard"/><category term="format"/><category term="framework"/><category term="free host"/><category term="ftp"/><category term="game"/><category term="game of life"/><category term="gcfg"/><category term="geeky base"/><category term="gen_event"/><category term="gen_fsm"/><category term="gen_server"/><category term="genymotion"/><category term="gf"/><category term="git+ssh"/><category term="global code retreat"/><category term="go to file"/><category term="gopenvpn"/><category term="groupingBy"/><category term="grunt"/><category term="hard"/><category term="hash"/><category term="head"/><category term="home office"/><category term="i18n"/><category term="i686"/><category term="iMac"/><category term="iOS"/><category term="iText"/><category term="id"/><category term="iframe"/><category term="ignore"/><category term="image"/><category term="impact mapping"/><category term="import"/><category term="indirect solution"/><category term="ini"/><category term="inspect"/><category term="invoice"/><category term="jetty"/><category term="k-NN"/><category term="k-Nearest Neighbors"/><category term="kNN"/><category term="learning"/><category term="lein"/><category term="leiningen"/><category term="let"/><category term="letfn"/><category term="life"/><category term="linux sis"/><category term="lisp"/><category term="live"/><category term="load balancer"/><category term="local ignore"/><category term="localization"/><category term="logic"/><category term="login"/><category term="loop"/><category term="loopback"/><category term="magazine"/><category term="mapToInt"/><category term="martini"/><category term="media"/><category term="mercurial"/><category term="mesh wall"/><category term="mgo"/><category term="mind set"/><category term="mobiscroll"/><category term="module"/><category term="mostRecentCall"/><category term="mymemory translated"/><category term="mysql_real_escape_string"/><category term="name binding"/><category term="native implemented functions"/><category term="ng-repeat"/><category term="nif"/><category term="nikic"/><category term="node"/><category term="oauth2"/><category term="observable"/><category term="ordered_set"/><category term="orientationchange"/><category term="pain"/><category term="paper"/><category term="parallel processing"/><category term="params"/><category term="parse"/><category term="parser"/><category term="particle"/><category term="passwd"/><category term="paste"/><category term="pckeyboardhack"/><category term="pen"/><category term="personal branding"/><category term="phpfog"/><category term="phpfog.com"/><category term="physical"/><category term="pip"/><category term="pipe"/><category term="plugin"/><category term="port"/><category term="postit"/><category term="prefix"/><category term="processing"/><category term="processing.js"/><category term="professional"/><category term="project"/><category term="pronto"/><category term="protocol"/><category term="public"/><category term="public key"/><category term="quotation"/><category term="radio"/><category term="rake"/><category term="rebase"/><category term="reboot"/><category term="recovery"/><category term="reflection"/><category term="refresh"/><category term="relaod"/><category term="reltool"/><category term="remove"/><category term="reset"/><category term="rm_rf"/><category term="rune"/><category term="rvm"/><category term="save image"/><category term="script"/><category term="search"/><category term="sed"/><category term="sense"/><category term="session"/><category term="setTimeout"/><category term="sftp"/><category term="sha256"/><category term="shadow dom"/><category term="shelf"/><category term="shutdown"/><category term="sick"/><category term="signal"/><category term="signed apk"/><category term="sleep"/><category term="slice"/><category term="slide"/><category term="sme"/><category term="socity"/><category term="soft"/><category term="sort"/><category term="sound"/><category term="special form"/><category term="speedup"/><category term="spring for android"/><category term="spring social"/><category term="static library"/><category term="static page"/><category term="stream"/><category term="string"/><category term="struct"/><category term="students"/><category term="sum"/><category term="swap"/><category term="swot"/><category term="system call"/><category term="system write"/><category term="tagline"/><category term="tail"/><category term="tar.bz2"/><category term="tar.gz"/><category term="team work"/><category term="technique"/><category term="temparament"/><category term="test"/><category term="testing"/><category term="titanium"/><category term="tomcat7"/><category term="translator api"/><category term="trimesh"/><category term="truthy"/><category term="tuple"/><category term="type"/><category term="unit"/><category term="unit test"/><category term="unity"/><category term="unless"/><category term="up"/><category term="upload file"/><category term="url"/><category term="value"/><category term="vector"/><category term="version"/><category term="video"/><category term="viewport"/><category term="vimrc"/><category term="virtualbox"/><category term="virtualenv"/><category term="visitor pattern"/><category term="web"/><category term="wheel"/><category term="wingrep"/><category term="words"/><category term="workflow"/><category term="x86_64"/><category term="xUnit"/><category term="xargs"/><category term="yii"/><category term="yii framework"/><category term="กรุงเทพฯ"/><category term="กล่อง"/><category term="การค้า"/><category term="การศึกษา"/><category term="กำลังใจ"/><category term="ขับรถ"/><category term="คณิตศาสตร์"/><category term="คน"/><category term="ครอบครัว"/><category term="ครั้งแรก"/><category term="ความสมบูรณ์"/><category term="คุยงาน"/><category term="งาน"/><category term="จักรยาน"/><category term="จังหวะ"/><category term="ทักทาย"/><category term="ทีม"/><category term="ธุรกิจ"/><category term="นักทดลอง"/><category term="บริษัท"/><category term="บัญชี"/><category term="บางขุนเทียน"/><category term="ปฏิสัมพันธ์"/><category term="ป่าชายเลน"/><category term="พิมพ์สัมผัส"/><category term="พิสูจน์"/><category term="พื้นฐาน"/><category term="ฟุตบอล"/><category term="ภาษีมูลค่าเพิ่ม"/><category term="มันๆ"/><category term="มูลค่าเพิ่ม"/><category term="รถสองแถว"/><category term="รถสาธารณะ"/><category term="ระบบเงินสดย่อย"/><category term="รักษาความลับ"/><category term="รักแฟน"/><category term="ราชบุรี"/><category term="รายเดือน"/><category term="ลืม"/><category term="วันเด็ก"/><category term="สติ"/><category term="สมองตัน"/><category term="สมุทรสาคร"/><category term="สยาม"/><category term="สรรพกร"/><category term="สองหมื่น"/><category term="สามก๊ก"/><category term="สุขภาพ"/><category term="สูตร"/><category term="หนังสือสัญญา"/><category term="หัก ณ ที่จ่าย"/><category term="อุบัติเหตุ"/><category term="อ่าน"/><category term="เขียน"/><category term="เดินทาง"/><category term="เต้น"/><category term="เที่ยว"/><category term="เปตอง"/><category term="เพลงเก่า"/><category term="แซงคิว"/><category term="แฟนเก่ง"/><category term="แมว"/><category term="โค้ช"/><category term="โตๆ"/><category term="ไทย"/><category term="ไม่ดู"/><category term="ไม่ประมาท"/><category term="่javascript"/><title type='text'>( λ ) IPorsut</title><subtitle type='html'>I&#39;m a Programmer.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>451</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-26659265.post-1686069773649077690</id><published>2017-02-04T17:42:00.001+07:00</published><updated>2017-02-04T17:42:35.852+07:00</updated><title type='text'>ของใน Go package time ที่ใช้บ่อยๆ ตอนที่ 3</title><content type='html'>จากตอนที่แล้ว เราแปลงจาก &lt;a href=&quot;https://iporsut.blogspot.com/2017/01/go-package-time-2.html&quot;&gt;time.Time ไปเป็น string&lt;/a&gt;&amp;nbsp;กันได้แล้ว วันนี้เราจะมาดูการแปลงจาก string มาเป็น time.Time กันต่อครับ&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
แปลงจาก string มาเป็น Time ด้วย function time.Parse และ time.ParseInLocation&lt;/h3&gt;
&lt;div&gt;
function time.Parse นั้นจะรับค่า layout คือรูปแบบการจัดเรียกของ string จริงๆจะเรียกตามที่ชินปากก็คือ format ที่มันอยู่นั่นเอง ซึ่งค่านี้ก็เหมือนกับตอนที่เราต้องการแปลงจาก time.Time ไปเป็น string ในตอนที่แล้วนั่นเอง ไม่ว่าจะแปลงจากอะไรไปเป็นอะไรก็ต้องบอก format กันก่อน และอีกค่าที่ต้องส่งให้ time.Parse ก็คือ string ที่ต้องการแปลงนั่นเอง ไปดูตัวอย่างกันดีกว่าครับ&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
timeString := &quot;04/02/2017 07:55:00&quot;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
tm, err := time.Parse(&quot;02/01/2006 15:04:05&quot;, &amp;nbsp;timeString)&lt;/div&gt;
&lt;div&gt;
if err != nil {&lt;/div&gt;
&lt;div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; log.Fatal(err)&lt;/div&gt;
&lt;div&gt;
}&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
fmt.Println(tm) // Output:&amp;nbsp;2017-02-04 07:55:00 +0000 UTC&lt;/div&gt;
&lt;br /&gt;
จะเห็นว่า เรายังใช้การกำหนดรูปแบบเป็นวันที่เจาะจงวันหนึ่งเช่นเดิมจาก &lt;a href=&quot;https://iporsut.blogspot.com/2017/01/go-package-time-2.html&quot;&gt;ตอนที่แล้ว&lt;/a&gt;&amp;nbsp;และการแปลงจาก string มาเป็น time.Time มีโอกาสที่จะมี error กลับมา เราจึงต้องเอามีการกำหนดค่าผลลัพธ์จาก time.Parse สองตำแหน่งคือตำแหน่งแรกเป็น time.Time ผลลัพธ์ที่ได้จากการแปลง และ อีกค่ากรณีแปลงไม่ได้จะมี error กลับออกมา&lt;br /&gt;
&lt;br /&gt;
ข้อสังเกตุ เนื่องจาก string ที่เป็น input ของเราไม่มีข้อมูลเกี่ยวกับ timezone ดังนั้นพอเรา fmt.Println ค่าออกมาดูจะเห็น&amp;nbsp;+0000 UTC นั่นคือใช้ UTC timezone นั่นเอง แต่ถ้า format string ของเราอยู่ในรูปแบบที่กำหนด timezone ได้เช่น format แบบ&amp;nbsp;&lt;span id=&quot;RFC3339&quot; style=&quot;color: #222222; font-family: &amp;quot;menlo&amp;quot; , monospace; font-size: 14px; text-align: justify;&quot;&gt;RFC3339&lt;/span&gt;&lt;span style=&quot;background-color: #efefef; color: #222222; font-family: &amp;quot;menlo&amp;quot; , monospace; font-size: 14px; text-align: justify;&quot;&gt;     = &quot;2006-01-02T15:04:05Z07:00&quot;&lt;/span&gt; เวลาเรา time.Parse ออกมาแล้วจะได้ค่าตาม timezone ที่อยู่ใน string input เช่น&lt;br /&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;timeString := &quot;2017-02-04T07:55:00+07:00&quot;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
tm, err := time.Parse(time.RFC3339, &amp;nbsp;timeString)&lt;/div&gt;
&lt;div&gt;
if err != nil {&lt;/div&gt;
&lt;div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; log.Fatal(err)&lt;/div&gt;
&lt;div&gt;
}&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
fmt.Println(tm) // Output:&amp;nbsp;2017-02-04 07:55:00 +0700 ICT&lt;br /&gt;
&lt;br /&gt;
ทีนี้ถ้าเกิด string ที่เป็น input ของเรานั้น ไม่มีข้อมูล timezone แต่เราอยากบังคับให้ parse string นั้นเป็น timezone ที่เราต้องการ เราจะใช้ function time.ParseInLocation แทน ทำได้ดังนี้เช่น&lt;br /&gt;
&lt;br /&gt;
timeString := &quot;04/02/2017 07:55:00&quot;&lt;br /&gt;
tm, err := time.ParseInLocation(&quot;02/01/2006 15:04:05&quot;, timeString, time.Local)&lt;br /&gt;
if err != nil {&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;log.Fatal(err)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
fmt.Println(tm) // Output:&amp;nbsp;2017-02-04 07:55:00 +0700 ICT&lt;br /&gt;
&lt;br /&gt;
จะเห็นว่า time.ParseInLocation รับเพิ่มอีกค่าคือ *time.Location แต่ว่าที่ผมใช้ time.Local เพราะเป็นค่าที่อยู่ใน package time กำหนดไว้ให้เป็น timezone เดียวกันกับเครื่องที่รันโปรแกรมนั่นเอง&lt;br /&gt;
&lt;br /&gt;
ถ้าเกิดเราอยากได้ timezone อื่นให้เราใช้ฟังก์ชัน time.LoadLocation เช่น&lt;br /&gt;
&lt;br /&gt;
timeString := &quot;04/02/2017 07:55:00&quot;&lt;br /&gt;
loc, err := time.LoadLocation(&quot;Asia/Bangkok&quot;)&lt;br /&gt;
if err != nil {&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;log.Fatal(err)&lt;br /&gt;
}&lt;br /&gt;
tm, err := time.ParseInLocation(&quot;02/01/2006 15:04:05&quot;, timeString, loc)&lt;br /&gt;
if err != nil {&lt;br /&gt;
&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;log.Fatal(err)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
fmt.Println(tm)&lt;br /&gt;
&lt;br /&gt;
ซึ่งทำการโหลด &quot;Asia/Bangkok&quot; เข้ามาก่อนส่งไปให้ ParseInLocation นั่นเองครับ&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/1686069773649077690/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/1686069773649077690' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/1686069773649077690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/1686069773649077690'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2017/02/go-package-time-3.html' title='ของใน Go package time ที่ใช้บ่อยๆ ตอนที่ 3'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-7595984170290506805</id><published>2017-01-30T00:57:00.001+07:00</published><updated>2017-02-04T07:47:34.203+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Go"/><category scheme="http://www.blogger.com/atom/ns#" term="Golang"/><category scheme="http://www.blogger.com/atom/ns#" term="time"/><title type='text'>ของใน Go package time ที่ใช้บ่อยๆ ตอนที่ 2</title><content type='html'>ตัวแปรเวลาที่เรามี สุดท้ายโปรแกรมเราก็ต้องการเอาไปแสดงผล ซึ่งก็แสดงเป็นสตริงที่บอกเวลานั่นเองครับ เช่น 29/01/2017 คือวันที่ 29 เดือนมกราคม ปี 2017 หรือในทางกลับกันเช่นกัน เราอาจจะส่งข้อมูลเวลาในรูปแบบสตริง แล้วต้องการแปลงกลับมาเป็นตัวแปรเวลา เพื่อคำนวณค่าบางอย่างแบบที่ให้ดูในบล็อกโพสอันที่แล้ว (&lt;a href=&quot;https://iporsut.blogspot.com/2017/01/go-package-time-1.html&quot;&gt;ของใน Go package time ที่ใช้บ่อยๆ ตอนที่ 1&lt;/a&gt;)&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
วันนี้มาดูวิธีการแปลงจาก time.Time มาเป็น string กันก่อน&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
แปลงจาก time.Time ไปเป็น string ด้วย method Format&lt;/h3&gt;
&lt;div&gt;
method Format รับค่า pattern ที่ต้องการแปลง ว่าตำแหน่งของ วัน เดือน ปี ชั่วโมง นาที วินาที อยู่ตรงไหน และการแสดงชั่วโมงเป็นแบบ 24 ชั่วโมงหรือเป็นแบบ 12 ชั่วโมงแล้วมี AM PM แต่วิธีกำหนดรูปแบบการของ Go จะต่างกับภาษาอื่น ดูตัวอย่างเลยจะเข้าใจมากกว่า เช่น&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
tm := time.Date(2017, 1, 30, 13, 30, 25, 0, time.Local)&lt;/div&gt;
&lt;div&gt;
format := tm.Format(&quot;02/01/2006 15:04:05&quot;)&lt;/div&gt;
&lt;div&gt;
fmt.Println(format) // Output: 30/01/2017 13:30:25&lt;br /&gt;
&lt;br /&gt;
อีกตัวอย่างแสดงเป็นแบบ AM/PM&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
format := tm.Format(&quot;02/01/2006 03:04:05 PM&quot;)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
fmt.Println(format) // Output: 30/01/2017 01:30:25 PM&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
ใครที่เคยใช้ภาษาอื่นอาจจะงง เพราะจะชินกับการ format date time โดยใช้ตัวอักษรอย่าง dd/mm/yyyy แต่สำหรับ Go เลือกที่จะใช้ วันที่ 2 มกราคม ปี 2006 เวลา 15 นาฬิกา 4 นาที 5 วินาที หรือถ้าคิดเป็นแบบ AM/PM คือ วันที่ 2 มกราคม ปี 2006 เวลา 3 นาฬิกา 4 นาที 5 วินาที ตอนบ่าย&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
ลองเรียงใหม่ โดยเอาเดือนขึ้นก่อน&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
เดือน &amp;nbsp; &amp;nbsp; =&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&lt;/div&gt;
&lt;div&gt;
วันที่ &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;2&lt;/div&gt;
&lt;div&gt;
ชั่วโมง &amp;nbsp; =&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;3&lt;/div&gt;
&lt;div&gt;
นาที &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;4&lt;/div&gt;
&lt;div&gt;
วินาที &amp;nbsp; &amp;nbsp; =&amp;gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;5&lt;/div&gt;
&lt;div&gt;
ปี &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; (200) 6&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
นั่นละครับที่มาที่ไปตลกดี เพิ่งเคยเห็นภาษาที่ใช้วิธีนี้เหมือนกัน แต่พอเราจำวันเดือนปีได้ แล้วเขียน format ก็ดูง่ายดี เพราะเราเห็น pattern ที่เป็นตัวเลขออกไปเลย&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
แต่จริงๆแล้ว มันมี format เวลาที่เป็นมาตรฐานที่ใช้กันบ่อยๆอยู่ package time เลยจะทำค่าคงที่ไว้ให้แล้ว ทำให้เรียกใช้และจำง่ายๆเช่น time.RFC3339 เป็นเวลามาตรฐานที่เราใช้สำหรับ JSON สำหรับเก็บค่าเวลาในรูปแบบ string ตัวอย่างการใช้งานง่ายๆเช่น&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
tm := time.Date(2017, 1, 30, 13, 30, 25, 0, time.Local)&lt;/div&gt;
&lt;div&gt;
format := tm.Format(time.RFC3339)&lt;/div&gt;
&lt;div&gt;
fmt.Println(format) // Output: 2017-01-30T13:30:25Z&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
ยังมีอีกหลายรูปแบบที่ถูกกำหนดเป็นค่าคงที่ไว้ให้แล้วดังนี้&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre style=&quot;background: rgb(239, 239, 239); border-radius: 5px; color: #222222; font-family: Menlo, monospace; font-size: 14px; line-height: 1.4em; margin: 20px; overflow-x: auto; padding: 10px;&quot;&gt;const (
        &lt;span id=&quot;ANSIC&quot;&gt;ANSIC&lt;/span&gt;       = &quot;Mon Jan _2 15:04:05 2006&quot;
        &lt;span id=&quot;UnixDate&quot;&gt;UnixDate&lt;/span&gt;    = &quot;Mon Jan _2 15:04:05 MST 2006&quot;
        &lt;span id=&quot;RubyDate&quot;&gt;RubyDate&lt;/span&gt;    = &quot;Mon Jan 02 15:04:05 -0700 2006&quot;
        &lt;span id=&quot;RFC822&quot;&gt;RFC822&lt;/span&gt;      = &quot;02 Jan 06 15:04 MST&quot;
        &lt;span id=&quot;RFC822Z&quot;&gt;RFC822Z&lt;/span&gt;     = &quot;02 Jan 06 15:04 -0700&quot; &lt;span class=&quot;comment&quot; style=&quot;color: #006600;&quot;&gt;// RFC822 with numeric zone&lt;/span&gt;
        &lt;span id=&quot;RFC850&quot;&gt;RFC850&lt;/span&gt;      = &quot;Monday, 02-Jan-06 15:04:05 MST&quot;
        &lt;span id=&quot;RFC1123&quot;&gt;RFC1123&lt;/span&gt;     = &quot;Mon, 02 Jan 2006 15:04:05 MST&quot;
        &lt;span id=&quot;RFC1123Z&quot;&gt;RFC1123Z&lt;/span&gt;    = &quot;Mon, 02 Jan 2006 15:04:05 -0700&quot; &lt;span class=&quot;comment&quot; style=&quot;color: #006600;&quot;&gt;// RFC1123 with numeric zone&lt;/span&gt;
        &lt;span id=&quot;RFC3339&quot;&gt;RFC3339&lt;/span&gt;     = &quot;2006-01-02T15:04:05Z07:00&quot;
        &lt;span id=&quot;RFC3339Nano&quot;&gt;RFC3339Nano&lt;/span&gt; = &quot;2006-01-02T15:04:05.999999999Z07:00&quot;
        &lt;span id=&quot;Kitchen&quot;&gt;Kitchen&lt;/span&gt;     = &quot;3:04PM&quot;
        &lt;span class=&quot;comment&quot; style=&quot;color: #006600;&quot;&gt;// Handy time stamps.&lt;/span&gt;
        &lt;span id=&quot;Stamp&quot;&gt;Stamp&lt;/span&gt;      = &quot;Jan _2 15:04:05&quot;
        &lt;span id=&quot;StampMilli&quot;&gt;StampMilli&lt;/span&gt; = &quot;Jan _2 15:04:05.000&quot;
        &lt;span id=&quot;StampMicro&quot;&gt;StampMicro&lt;/span&gt; = &quot;Jan _2 15:04:05.000000&quot;
        &lt;span id=&quot;StampNano&quot;&gt;StampNano&lt;/span&gt;  = &quot;Jan _2 15:04:05.000000000&quot;
)&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
วันนี้เท่านี้ก่อนครับ เดี๋ยวตอนต่อไปว่ากันด้วยการแปลงจาก string มาเป็น time.Time ด้วย function time.Parse และ time.ParseInLocation กันครับ</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/7595984170290506805/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/7595984170290506805' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7595984170290506805'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7595984170290506805'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2017/01/go-package-time-2.html' title='ของใน Go package time ที่ใช้บ่อยๆ ตอนที่ 2'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-2615367613579687549</id><published>2017-01-27T00:22:00.001+07:00</published><updated>2017-01-27T00:22:25.713+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Go"/><category scheme="http://www.blogger.com/atom/ns#" term="Golang"/><category scheme="http://www.blogger.com/atom/ns#" term="time"/><title type='text'>ของใน Go  package time ที่ใช้บ่อยๆ ตอนที่ 1</title><content type='html'>&amp;nbsp;สำหรับเรื่อง วันที่ และ เวลา เวลาที่เราเขียน Go นั้นหลักๆเราจะเอา &lt;a href=&quot;https://golang.org/pkg/time/&quot;&gt;package time&lt;/a&gt; มาใช้งานครับ ซึ่งผมจะลิสต์ที่ผมได้ใช้บ่อยๆมาสรุปไว้ในโพสต์นี้ครับ&lt;br /&gt;
&lt;br /&gt;
สิ่งแรกที่ต้องรู้คือ package time นั้นเก็บข้อมูลเวลาอยู่ในรูปแบบของประเภทข้อมูลที่ชื่อว่า time.Time ครับ ซึ่งตัวมันเองถ้าไปเปิดดูโค้ด ก็คือ struct แบบนึงนั่นเองครับ และ ประเภทข้อมูล time.Time ก็มี methods หลายๆตัวไว้ให้เราจัดการข้อมูลของวันที่และเวลานั่นเองครับ ต่อไปเราไปดู function ใน package time และ method ของ time.Time ที่เราใช้บ่อยๆกันต่อดีกว่าครับ&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
อยากได้ค่าของเวลาปัจจุบัน&lt;/h3&gt;
&lt;div&gt;
แน่นอนว่าเป็นค่าเวลาที่เราต้องใช้กันบ่อยๆอยู่แล้วเวลาเขียนโปรแกรม เพราะเราอยากได้เวลาปัจจุบันมาเก็บเป็นข้อมูลเช่น ข้อมูลเมื่อตอนบันทึกข้อมูลลงฐานข้อมูล ข้อมูลเอาไว้เก็บล็อกการทำงาน ซึ่งเราจะเรียก function ชื่อว่า time.Now() ครับในการเอาค่าเวลาปัจจุบันออกมา เช่น&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
now := time.Now()&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
อยากได้จำนวน วัน, เดือน และ ปี ที่อยู่ในค่าของเวลา&lt;/h3&gt;
&lt;div&gt;
ต่อไปเมื่อเรามีตัวแปรเก็บค่าของเวลาแล้ว เราอยากได้ค่า วัน, เดือน และ ปี ของวันที่และเวลาที่เก็บในตัวแปรนั้นออกมา เราก็จะเรียกใช้ method ต่างๆที่เตรียมไว้สำหรับข้อมูล time.Time ดังนี้ครับ สมมติว่าเรามีตัวแปร now เก็บค่าเวลาปัจจุบันไว้&lt;/div&gt;
&lt;h4&gt;
อยากรู้วันที่เรียก&lt;/h4&gt;
&lt;div&gt;
day := now.Day()&lt;/div&gt;
&lt;h4&gt;
อยากรู้เดือนเรียก&lt;/h4&gt;
&lt;div&gt;
month := now.Month()&lt;/div&gt;
&lt;h4&gt;
อยากรู้ปีเรียก&lt;/h4&gt;
&lt;div&gt;
year := now.Year()&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h3&gt;
อยากได้จำนวน ชั่วโมง, นาที และ วินาที ที่อยู่ในค่าของเวลา&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
ถ้าเราอยากรู้จำนวน ชั่วโมง, นาที และ วินาที ที่อยู่ในตัวแปรของเวลา เราจะเรียกใช้ methods ต่างๆดังต่อไปนี้ครับ&lt;/div&gt;
&lt;h4&gt;
อยากรู้จำนวนชั่วโมง&lt;/h4&gt;
&lt;div&gt;
hour := now.Hour()&lt;/div&gt;
&lt;h4&gt;
อยากรู้จำนวนนาที&lt;/h4&gt;
&lt;div&gt;
minute := now.Minute()&lt;/div&gt;
&lt;h4&gt;
อยากรู้จำนวนวินาที&lt;/h4&gt;
&lt;div&gt;
second := now.Second()&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
สร้างค่าเวลาด้วย function time.Date&lt;/h3&gt;
&lt;div&gt;
เรารู้วิธีได้ค่าเวลาปัจจุบันไปแล้ว ต่อไปถ้าเราจะสร้างตัวแปรของเวลา โดยระบุลงไปชัดๆ ว่า วัน และ เวลาไหน เราจะใช้ fuction time.Date เข้ามาใช้ครับ ซึ่งเราต้องระบุค่าเยอะหน่อย ตัวอย่างเช่น&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
tm := time.Date(2017, 1, 27, 8, 30, 20, 0, time.Local)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
จะเห็นว่ากำหนด arguments ไปให้ตั้ง 8 ค่า แต่ละค่าคือค่าต่อไปนี้ตามลำดับครับ&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
2017 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; ปี 2017&lt;/div&gt;
&lt;div&gt;
1 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; เดือนที่ 1 (มกราคม)&lt;/div&gt;
&lt;div&gt;
27 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; วันที่ 27&lt;/div&gt;
&lt;div&gt;
8 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; เวลา 8 นาฬิกา&lt;/div&gt;
&lt;div&gt;
30 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; 30 นาที&lt;/div&gt;
&lt;div&gt;
20 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; 20 วินาที&lt;/div&gt;
&lt;div&gt;
0 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; =&amp;gt; 0 นาโนวินาที&lt;/div&gt;
&lt;div&gt;
time.Local &amp;nbsp;=&amp;gt; ค่าสุดท้ายเป็นค่าที่ระบุ time zone ครับ การที่เราใช้ตัวแปร time.Local คือให้เอาตาม time zone ที่ระบุไว้ในเครื่องที่เรารันโปรแกรมครับ&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
เปรียบเทียบเวลา เวลาไหนเกิดขึ้นก่อน เวลาไหนเกิดทีหลัง หรือ เป็นเวลาเดียวกัน&lt;/h3&gt;
&lt;div&gt;
ต่อไปถ้าเรามีค่าของเวลาเก็บในตัวแปรสองตัว ถ้าเราอยากเปรียบเทียบค่าเวลาว่าอะไรมาก่อน อะไรมาหลัง หรือเป็นเวลาเดียวกัน เราใช้ method ที่ชื่อว่า Before, After และ Equal ช่วยครับ ตัวอย่างเช่น ผมสร้างค่าเวลาขึ้นมา 3 ค่าไว้ยกตัวอย่างดังนี้&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
t1 := time.Date(2017, 1, 27, 8, 30, 20, 0, time.Local)&lt;/div&gt;
&lt;div&gt;
t2 := time.Date(2017, 1, 28, 8, 30, 20, 0, time.Local)&lt;/div&gt;
&lt;div&gt;
t3 := time.Date(2017, 1, 28, 8, 30, 20, 0, time.Local)&lt;/div&gt;
&lt;h4&gt;
อยากรู้ว่าเวลา t1 เป็นเวลาที่เกิดก่อน t2 หรือไม่&lt;/h4&gt;
&lt;div&gt;
if t1.Before(t2) {&lt;/div&gt;
&lt;div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; fmt.Println(t1, &quot;is time before&quot;, &amp;nbsp;t2)&lt;/div&gt;
&lt;div&gt;
}&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h4&gt;
อยากรู้ว่าเวลา t2 เป็นเวลาที่เกิดทีหลัง t1 หรือไม่&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
if t2.After(t1) {&lt;/div&gt;
&lt;div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; fmt.Println(t2, &quot;is time after&quot;, t1)&lt;/div&gt;
&lt;div&gt;
}&lt;/div&gt;
&lt;div&gt;
&lt;h4&gt;
อยากรู้ว่าเวลา t2 เป็นเวลาเดียวกันกับ t3 หรือไม่&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
if t2.Equal(t3) {&lt;/div&gt;
&lt;div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; fmt.Println(t2, &quot;is the same time&quot;, t3)&lt;/div&gt;
&lt;div&gt;
}&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
ตอนที่ 1 เอาไว้แค่นี้ก่อน ตอนต่อไปเดี๋ยวดูเรื่องการแปลงค่าจาก string มาเป็นเวลา และ แปลงค่าจากเวลา เป็น string ในรูปแบบที่ต้องการครับ&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/2615367613579687549/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/2615367613579687549' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/2615367613579687549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/2615367613579687549'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2017/01/go-package-time-1.html' title='ของใน Go  package time ที่ใช้บ่อยๆ ตอนที่ 1'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-6304566768395282840</id><published>2016-11-15T21:34:00.000+07:00</published><updated>2016-11-15T21:35:20.230+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Atom"/><category scheme="http://www.blogger.com/atom/ns#" term="Elixir"/><title type='text'>Atom Package for Elixir</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRyo410STPYpu91Sd_0T4t83DBF2710q-M_dJH3p4kuTeRa5fnJHBNt-zUM09Rh3HbzjP_zzPkf6Z7BHsaptX2vXU8p62PUcjN1WtHJqkVwX-T8QvhZOhN34dgv8kfY0nLtlLu/s1600/elixir.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRyo410STPYpu91Sd_0T4t83DBF2710q-M_dJH3p4kuTeRa5fnJHBNt-zUM09Rh3HbzjP_zzPkf6Z7BHsaptX2vXU8p62PUcjN1WtHJqkVwX-T8QvhZOhN34dgv8kfY0nLtlLu/s200/elixir.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGRVHjDv6rywuIjQ_T0WF9pPWn-A4CCD_xVvFP1BQwLVmUSUDVpRRlrZEM4MU4-7n0lSSXerAYIYrJXLQhsqEwfbTQxEr2cHxB1H3cjzhzSXeJ5kAe0kW9m34Qx6oojJERvequ/s1600/Screen+Shot+2016-11-15+at+21.31.34.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;178&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGRVHjDv6rywuIjQ_T0WF9pPWn-A4CCD_xVvFP1BQwLVmUSUDVpRRlrZEM4MU4-7n0lSSXerAYIYrJXLQhsqEwfbTQxEr2cHxB1H3cjzhzSXeJ5kAe0kW9m34Qx6oojJERvequ/s200/Screen+Shot+2016-11-15+at+21.31.34.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
ช่วงนี้เปลี่ยนมาใช้ Atom เป็น Editor หลักในการทำงาน ซึ่งงานหลักตอนนี้ก็เขียนอยู่ 2 ภาษาคือ Ruby และ Elixir โน้ตไว้หน่อยว่าลง Package เสริมอะไรบ้างสำหรับใช้เขียน Elixir&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;language-elixir&lt;/li&gt;
&lt;li&gt;language-erlang&lt;/li&gt;
&lt;li&gt;atom-elixir&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
ลงทั้ง elixir และ erlang เพราะยังไงก็ยังรันบน erlang vm บาง library ต้องดูโค้ด erlang บ้าง ส่วน atom-elixir ช่วยทั้ง go to definition ของ function ช่วยทั้ง ดู document ซึ่ง key ในการกดดู document ตอนแรกถูกตั้งไว้เป็น F2 ซึ่งกดบน MacOS ไม่สะดวกเลยต้อง Key mapping ให้เป็น cmd-k cmd-k คือกด cmd ค้างไว้แล้วกด k สองครั้งติด เราตั้งค่าได้ที่ไฟล์ Key map ดังนี้&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
&#39;atom-text-editor:not(mini)[data-grammar^=&quot;source elixir&quot;]&#39;:&lt;/div&gt;
&lt;div&gt;
&amp;nbsp; &#39;cmd-k cmd-k&#39;: &#39;atom-elixir:show-elixir-docs&#39;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/6304566768395282840/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/6304566768395282840' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/6304566768395282840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/6304566768395282840'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/11/atom-package-for-elixir.html' title='Atom Package for Elixir'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRyo410STPYpu91Sd_0T4t83DBF2710q-M_dJH3p4kuTeRa5fnJHBNt-zUM09Rh3HbzjP_zzPkf6Z7BHsaptX2vXU8p62PUcjN1WtHJqkVwX-T8QvhZOhN34dgv8kfY0nLtlLu/s72-c/elixir.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-2593307077895978672</id><published>2016-11-06T17:17:00.002+07:00</published><updated>2016-11-06T17:17:45.807+07:00</updated><title type='text'>Elixir Default Arguments</title><content type='html'>Function ของ Elixir สามารถกำหนดค่า Default ให้กับ Argument ได้ โดยที่เมื่อเรียกใช้ Function แล้วไม่ได้กำหนดค่าให้กับ Argument นั้น ค่าจะเป็นค่าตามที่กำหนดไว้ตอนสร้าง Function&lt;br /&gt;
&lt;br /&gt;
ตัวอย่างเช่น&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
defmodule Say do
  def hello(to \\ &quot;World&quot;) do
    &quot;Hello, #{to}!&quot;
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
เมื่อเรียกใช้งาน ถ้าไม่ส่งค่าอะไรไป Argument to ก็จะมีค่าเป็น &quot;World&quot;&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
iex&amp;gt; Say.hello
&quot;Hello, World!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
ถ้าส่งค่าไป Argument to ก็มีค่าตามที่ส่งไป&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
iex&amp;gt; Say.hello(&quot;iPorsut&quot;)
&quot;Hello, iPorsut!&quot;
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
Elixir สามารถกำหนด Default Arguments ที่ Arguments ตำแหน่งอื่น ที่ไม่ใช่ตำแหน่งสุดท้ายของ Function ก็ได้เช่นกัน ตัวอย่างเช่น Function &lt;a href=&quot;http://elixir-lang.org/docs/stable/elixir/Enum.html#find/3&quot;&gt;find&lt;/a&gt; จาก module Enum ถูกประกาศไว้แบบนี้&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
find(enumerable, default \\ nil, fun)
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
จะเห็นว่า find เป็น Function ที่มี 3 Arity (3 Arguments) แต่ในตำแหน่งที่ 2 นั้นมีค่า Default เป็น nil ดังนั้นการเรียกใช้ Function find จะสามารถทำได้ 2 แบบหลักๆคือ ส่ง 2 Arguments และส่ง 3 Arguments&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;ถ้าส่ง 2 Arguments Elixir จะมองว่าเราส่ง enumerable และ fun แล้ว default จะมีค่าเป็น nil&lt;/li&gt;
&lt;li&gt;ถ้าส่ง 3 Arguments Elixir จะมองว่าเราส่งทั้ง enumerable, default และ fun ตามลำดับ&lt;/li&gt;
&lt;/ul&gt;
ตัวอย่างอีก Function คือ IO.puts ที่เราให้แสดงผลข้อมูลออกทาง Standard Output ซึ่งปกติเวลาใช้เราก็ส่งแค่ 1 Argument เพื่อเอาค่านั้นไปแสดงเช่น&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
IO.puts &quot;Hello, World&quot;
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
ซึ่งก็จะแสดง &quot;Hello, World&quot; ที่ console ซึ่งถ้าเราดูการประกาศ IO.puts เราจะเห็นว่ากำหนดไว้แบบนี้&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
puts(device \\ group_leader(), item)
&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
เมื่อเราส่งค่าเดียวเข้าไป item เลยมีค่าเท่ากับค่าที่เราส่งไป แล้ว device มีค่าเป็น group_leader() ตามที่กำหนด default เอาไว้นั่นเอง

นี่ก็เป็นพฤติกรรมการเรียกใช้ Function ที่มีการกำหนด Default ให้กับ Arguments เมื่อเราเห็นการเรียกใช้จะได้เข้าใจนั่นเองว่าแต่ละค่า Arguments เป็นอะไร</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/2593307077895978672/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/2593307077895978672' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/2593307077895978672'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/2593307077895978672'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/11/elixir-default-arguments.html' title='Elixir Default Arguments'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-3306531772430764621</id><published>2016-09-27T15:12:00.001+07:00</published><updated>2016-09-27T15:12:42.871+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Block"/><category scheme="http://www.blogger.com/atom/ns#" term="Golang"/><category scheme="http://www.blogger.com/atom/ns#" term="Statement"/><title type='text'>Golang Block is a Statement (version. Thai)</title><content type='html'>ปกติแล้ว Block ใน Go คือลำดับของ Statement ที่อยู่ภายในปีกกา { และ } เช่น&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;package main

import &quot;fmt&quot;

func main() {
 name := &quot;iPorsut&quot;
 fmt.Printf(&quot;Hello %s\n&quot;, name)
}

&lt;/pre&gt;
&lt;br /&gt;
ซึ่งเมื่อผมได้ไปอ่านโค้ดตัวอย่างของ &lt;a href=&quot;https://github.com/go-kit/kit&quot;&gt;go-kit&lt;/a&gt;&amp;nbsp;แล้วเจอการใช้งาน Block ซ้อน Block โดยที่ไม่ใช้ Block ของ function หรือ Block ของ for, if, switch แบบนี้&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;package main

func main() {
 // Endpoint domain.
 var sumEndpoint endpoint.Endpoint
 {
  sumDuration := duration.With(&quot;method&quot;, &quot;Sum&quot;)
  sumLogger := log.NewContext(logger).With(&quot;method&quot;, &quot;Sum&quot;)

  sumEndpoint = addsvc.MakeSumEndpoint(service)
  sumEndpoint = opentracing.TraceServer(tracer, &quot;Sum&quot;)(sumEndpoint)
  sumEndpoint = addsvc.EndpointInstrumentingMiddleware(sumDuration)(sumEndpoint)
  sumEndpoint = addsvc.EndpointLoggingMiddleware(sumLogger)(sumEndpoint)
 } 
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
การที่เราสร้าง Block ใหม่ขึ้นมา  scope ของตัวแปรจะอยู่ภายใน Block นั้นเท่านั้น เช่นตัวแปร sumDuration และ sumLogger สร้างภายใน Block เมื่อออกนอก Block นี้ก็ไม่สามารถอ้างอิงได้อีก&lt;br /&gt;
&lt;br /&gt;
นอกจากนั้นตัวแปรชื่อเดียวกัน ที่สร้างใหม่ภายใน Block ที่ซ้อนอยู่ จะบังชื่อตัวแปรภายนอก เมื่อออกจาก scope ก็จะเป็น scope ของตัวแปรเดิม เช่น&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;package main

import &quot;fmt&quot;

func main() {
 name := &quot;World&quot;
 {
  name := &quot;iPorsut&quot;
  fmt.Printf(&quot;Hello %s\n&quot;, name)
 }
 fmt.Printf(&quot;Hello %s\n&quot;, name)
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
จะได้ผลลัพธ์เป็น
&lt;br /&gt;
&lt;pre&gt;Hello iPorsut
Hello World
&lt;/pre&gt;
&lt;br /&gt;
ผมลองไปดูที่ &lt;a href=&quot;https://golang.org/ref/spec&quot;&gt;Golang Spec&lt;/a&gt; แล้วเจอจุดที่นิยามโครงสร้างแบบนี้อยู่คือในส่วนของ &lt;a href=&quot;https://golang.org/ref/spec#Block&quot;&gt;Block&lt;/a&gt; นั้นกำหนดไว้แบบนี้
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Block = &quot;{&quot; StatementList &quot;}&quot; .
StatementList = { Statement &quot;;&quot; } .
&lt;/pre&gt;
&lt;br /&gt;
ซึ่ง Block คือ StatementList ที่อยู่ภายใน { } และ StatementList คือ Statement ตั้งแต่ 0 ตัวขึ้นไป ต่อไปไปดูในส่วนของนิยาม &lt;a href=&quot;https://golang.org/ref/spec#Statements&quot;&gt;Statement&lt;/a&gt; นั้นกำหนดไว้แบบนี้
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Statement =
 Declaration | LabeledStmt | SimpleStmt |
 GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
 FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
 DeferStmt .

SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
&lt;/pre&gt;
&lt;br /&gt;
จุดน่าสนใจคือ Block ก็คือ Statement แบบหนึ่งนั่นเอง ด้วยนิยามแบบนี้จะเห็นว่าเราสามารถเขียน Block ซ้อนๆกันได้ เพราะ Block ก็คือ Statement แบบหนึ่งนั่นเอง</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/3306531772430764621/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/3306531772430764621' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/3306531772430764621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/3306531772430764621'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/09/golang-block-is-statement-ver-thai.html' title='Golang Block is a Statement (version. Thai)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-4390052300714090603</id><published>2016-09-27T15:12:00.000+07:00</published><updated>2016-09-27T15:12:18.017+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Block"/><category scheme="http://www.blogger.com/atom/ns#" term="Golang"/><category scheme="http://www.blogger.com/atom/ns#" term="Statement"/><title type='text'>Golang Block is a Statement (version. English)</title><content type='html'>Usually, Block in Golang is a sequence of statements in bracket { and }. Example 
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;package main

import &quot;fmt&quot;

func main() {
 name := &quot;iPorsut&quot;
 fmt.Printf(&quot;Hello %s\n&quot;, name)
}

&lt;/pre&gt;
&lt;br /&gt;
When I had read &lt;a href=&quot;https://github.com/go-kit/kit&quot;&gt;go-kit&lt;/a&gt; Example, I found it uses nested Block like this.
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;package main

func main() {
 // Endpoint domain.
 var sumEndpoint endpoint.Endpoint
 {
  sumDuration := duration.With(&quot;method&quot;, &quot;Sum&quot;)
  sumLogger := log.NewContext(logger).With(&quot;method&quot;, &quot;Sum&quot;)

  sumEndpoint = addsvc.MakeSumEndpoint(service)
  sumEndpoint = opentracing.TraceServer(tracer, &quot;Sum&quot;)(sumEndpoint)
  sumEndpoint = addsvc.EndpointInstrumentingMiddleware(sumDuration)(sumEndpoint)
  sumEndpoint = addsvc.EndpointLoggingMiddleware(sumLogger)(sumEndpoint)
 } 
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
When we create nested Block. A declaration inside a Block have scope only inside Block. So &amp;nbsp;&#39;sumDuration&#39; and &#39;sumLogger&#39; variables cannot use after outside Block.&lt;br /&gt;
&lt;br /&gt;
Variable inner Block shadow a variable outer Block if it has a same name. Example.
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;package main

import &quot;fmt&quot;

func main() {
 name := &quot;World&quot;
 {
  name := &quot;iPorsut&quot;
  fmt.Printf(&quot;Hello %s\n&quot;, name)
 }
 fmt.Printf(&quot;Hello %s\n&quot;, name)
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
Output:
&lt;br /&gt;
&lt;pre&gt;Hello iPorsut
Hello World
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
I had seen in the &lt;a href=&quot;https://golang.org/ref/spec&quot;&gt;Golang Spec&lt;/a&gt;. I found definition of structure of &lt;a href=&quot;https://golang.org/ref/spec#Block&quot;&gt;Block&lt;/a&gt; like this.
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Block = &quot;{&quot; StatementList &quot;}&quot; .
StatementList = { Statement &quot;;&quot; } .
&lt;/pre&gt;
&lt;br /&gt;
It means Block is composed by StatementList inside bracket { } and StatementList is Statement zero or more.
The definition of &lt;a href=&quot;https://golang.org/ref/spec#Statements&quot;&gt;Statement&lt;/a&gt; is
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;Statement =
 Declaration | LabeledStmt | SimpleStmt |
 GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
 FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
 DeferStmt .

SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
&lt;/pre&gt;
&lt;br /&gt;
We found Block, it is also a Statement too. From those definitions, we can write nested Block.</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/4390052300714090603/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/4390052300714090603' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4390052300714090603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4390052300714090603'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/09/golang-block-is-statement-ver-english.html' title='Golang Block is a Statement (version. English)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-4004475198878262946</id><published>2016-09-21T11:43:00.003+07:00</published><updated>2016-09-21T13:20:15.152+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="English"/><category scheme="http://www.blogger.com/atom/ns#" term="haskell"/><category scheme="http://www.blogger.com/atom/ns#" term="Tense"/><title type='text'>Type of Tense in Haskell</title><content type='html'>I am reading the book about English Tense. It tells 12 tenses.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Past Simple&lt;/li&gt;
&lt;li&gt;Present Simple&lt;/li&gt;
&lt;li&gt;Future Simple&lt;/li&gt;
&lt;li&gt;Past Continuous&lt;/li&gt;
&lt;li&gt;Present Continuous&lt;/li&gt;
&lt;li&gt;Future Continuous&lt;/li&gt;
&lt;li&gt;Past Perfect&lt;/li&gt;
&lt;li&gt;Present Perfect&lt;/li&gt;
&lt;li&gt;Future Perfect&lt;/li&gt;
&lt;li&gt;Past Perfect Continuous&lt;/li&gt;
&lt;li&gt;Present Perfect Continuous&lt;/li&gt;
&lt;li&gt;Future Perfect Continuous&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
It have a patterns that base Simple, Continuous, Perfect, Perfect Continuous compose with time Past, Present, Future.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I try to write it as a Haskell algebraic datatype.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;pre&gt;data BaseTense = Simple
               | Continuous
               | Perfect
               | PerfectContinuous deriving (Show, Eq)

data TimeTense = Past
               | Present
               | Future deriving (Show, Eq)

data Tense = Tense TimeTense BaseTense deriving (Show, Eq)
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
We create two sum type BaseTense and TimeTense and product type Tense that compose TimeTense and BaseTense</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/4004475198878262946/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/4004475198878262946' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4004475198878262946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4004475198878262946'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/09/type-of-tense-in-haskell.html' title='Type of Tense in Haskell'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-4827685335924348641</id><published>2016-09-20T09:34:00.001+07:00</published><updated>2016-09-20T15:17:31.441+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Iron"/><category scheme="http://www.blogger.com/atom/ns#" term="Rust"/><category scheme="http://www.blogger.com/atom/ns#" term="Rustlang"/><category scheme="http://www.blogger.com/atom/ns#" term="time"/><title type='text'>Rust make and compare time</title><content type='html'>My wife, she is learning Golang and make the exercise try to write English greetings service, that response greeting string depending period of time.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
if time now between &amp;gt;= 00.00 and &amp;lt; 12.00 response &quot;Good Morning&quot;.&lt;br /&gt;
if time now between &amp;gt;= 12.00 and &amp;lt; 18.00 response &quot;Good Afternoon&quot;.&lt;br /&gt;
if time now between &amp;gt;= 18.00 and &amp;lt; 24.00 response &quot;Good Evening&quot;&lt;br /&gt;
&lt;br /&gt;
You can see her repository at this link&amp;nbsp;&lt;a href=&quot;https://github.com/Kanokorn/english-greetings&quot;&gt;https://github.com/Kanokorn/english-greetings&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I want try to learn Rust language with her exercise too. So I write it with &lt;a href=&quot;https://github.com/iron/iron&quot;&gt;Iron&lt;/a&gt; web framework.&lt;br /&gt;
&lt;br /&gt;
You can see my repository at this link&amp;nbsp;&lt;a href=&quot;https://github.com/iporsut/rust-iron-english-greeting&quot;&gt;https://github.com/iporsut/rust-iron-english-greeting&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
I learnt many thing about Rust when I do this exercise. Such as how to create time value and compare it.&lt;br /&gt;
&lt;br /&gt;
Rust use time library&amp;nbsp;&lt;a href=&quot;https://crates.io/crates/time&quot;&gt;https://crates.io/crates/time&lt;/a&gt;&amp;nbsp;for manage about time.&lt;br /&gt;
&lt;br /&gt;
You can get time now by call time::now() that return time::Tm struct value.&lt;br /&gt;
&lt;br /&gt;
time::Tm struct have fields.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
pub struct Tm {
    pub tm_sec: i32,
    pub tm_min: i32,
    pub tm_hour: i32,
    pub tm_mday: i32,
    pub tm_mon: i32,
    pub tm_year: i32,
    pub tm_wday: i32,
    pub tm_yday: i32,
    pub tm_isdst: i32,
    pub tm_utcoff: i32,
    pub tm_nsec: i32,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
I want to get 00:00, 12:00, 18:00 and 24:00 &amp;nbsp;time of same day of now. I must copy and clear tm_hour, tm_min, tm_sec, tm_nsec fields value.&lt;br /&gt;
&lt;br /&gt;
I decide to create new function receive now value and create new mut value copy value from arguments and hour value for clear.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
fn set_hour(t: time::Tm, hour: i32) -&amp;gt; time::Tm {
    let mut t = t;
    t.tm_hour = hour;
    t.tm_min = 0;
    t.tm_sec = 0;
    t.tm_nsec = 0;
    t
}
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
I can make function like this because time::Tm implement Copy, Clone trait.&lt;br /&gt;
&lt;br /&gt;
I can compare time like a number because time::Tm implement Eq and PartialEq, Ord, PartialOrd trait.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;    fn handler(_: &amp;amp;mut Request) -&amp;gt; IronResult&amp;lt;response&amp;gt; {
        let now = time::now();

        let midnight = set_hour(now, 0);
        let midday = set_hour(now, 12);
        let sunset = set_hour(now, 18);
        let midnightnextday = set_hour(now, 24);

        let greeting = if now &amp;gt;= midnight &amp;amp;&amp;amp; now &amp;lt; midday {
            &quot;Good Morning&quot;.to_string()
        } else if now &amp;gt;= midday &amp;amp;&amp;amp; now &amp;lt; sunset {
            &quot;Good Afternoon&quot;.to_string()
        } else if now &amp;gt;= sunset &amp;amp;&amp;amp; now &amp;lt; midnightnextday {
            &quot;Good Evening&quot;.to_string()
        } else {
            &quot;Hello&quot;.to_string()
        };

        Ok(Response::with((status::Ok, greeting)))
    }
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a powerful of Rust Generic and Trait.</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/4827685335924348641/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/4827685335924348641' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4827685335924348641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4827685335924348641'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/09/rust-make-and-compare-time.html' title='Rust make and compare time'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-4399008196498534294</id><published>2016-09-16T22:17:00.002+07:00</published><updated>2016-09-16T22:21:27.072+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Rust"/><category scheme="http://www.blogger.com/atom/ns#" term="utf8"/><title type='text'>Rust lang count characters in UTF-8 text file.</title><content type='html'>Today I&#39;m try to learn Rust language by write a small program. I choose to write character counting in text file that UTF-8 encoding.&lt;br /&gt;
&lt;br /&gt;
This is a example when I run the program.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpa_9jr310h8AUOV1oPZVyRnSWkl8V2uraniMd2dEdnZxODQIGSbuXFKz4HxT5Yi_u7-8HCpCol4COeDejPGT3US1yeuD9WaNjU6yx6ocqw6zCrvA2pGfUiT2atIegRMFZIr28/s1600/Screen+Shot+2559-09-16+at+10.14.17+PM.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;145&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpa_9jr310h8AUOV1oPZVyRnSWkl8V2uraniMd2dEdnZxODQIGSbuXFKz4HxT5Yi_u7-8HCpCol4COeDejPGT3US1yeuD9WaNjU6yx6ocqw6zCrvA2pGfUiT2atIegRMFZIr28/s200/Screen+Shot+2559-09-16+at+10.14.17+PM.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
This is a soucecode.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1HqRY8el1RiWLs0ND1DzuO9qnGs17vif1AmnGM8H3whu7AQn7IdL89J0gWkAx9HrE3R_z3lyNLuQFf0KmaRaUmcj47dV9kJcw8ZxzlbKxO2DqQOupRnThObldsoklKU-y-uxm/s1600/Screen+Shot+2559-09-16+at+10.15.57+PM.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;215&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1HqRY8el1RiWLs0ND1DzuO9qnGs17vif1AmnGM8H3whu7AQn7IdL89J0gWkAx9HrE3R_z3lyNLuQFf0KmaRaUmcj47dV9kJcw8ZxzlbKxO2DqQOupRnThObldsoklKU-y-uxm/s400/Screen+Shot+2559-09-16+at+10.15.57+PM.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;
use std::io::prelude::*;
use std::env;
use std::fs::File;

fn main() {
    let filename = env::args().nth(1).unwrap();
    let mut f = File::open(filename).unwrap();
    let mut s = String::new();
    f.read_to_string(&amp;amp;mut s).unwrap();
    println!(&quot;{}&quot;, s.trim_right().chars().count());
}&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
First line in main function, I use env::args().nth(1) for get the filename from command line arguments. You can see that I must call .unwrap() because return type of nth(1) is a type&amp;nbsp;Option&amp;lt;Self::Item&amp;gt;. It maybe a value String or None. So when we call unwrap() if value is None it will panic and if value is not None it will return that value.&lt;br /&gt;
&lt;br /&gt;
Next line, I use File::open for open file and use unwrap again because return type of open() is&amp;nbsp;Result&amp;lt;File&amp;gt;. It maybe a File or Err. So when we call unwrap() if value is Err it will panic and if value is File it will return File value to f.&lt;br /&gt;
&lt;br /&gt;
Next line, I make a new String.&lt;br /&gt;
&lt;br /&gt;
Next line, I use method read_to_string for read a content in file to string s and unwrap() again because return type of read_to_string is&amp;nbsp;Result&amp;lt;usize&amp;gt;. It maybe a usize or Err. So when we call unwrap() if value is Err it will panic and if value is usize it will return usize value.&lt;br /&gt;
&lt;br /&gt;
Next line, I use println for print a value of s.trim_right().chars().count() that cut the right space and call chars() that return Chars type. It is a iterator for unicode char in String. Then we can use count() in Chars type for counting character in format Unicode.&lt;br /&gt;
&lt;br /&gt;
This is a repository for this program&amp;nbsp;&lt;a href=&quot;https://github.com/iporsut/rust-utf8count&quot;&gt;https://github.com/iporsut/rust-utf8count&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/4399008196498534294/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/4399008196498534294' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4399008196498534294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4399008196498534294'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/09/rust-lang-count-characters-in-utf-8.html' title='Rust lang count characters in UTF-8 text file.'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpa_9jr310h8AUOV1oPZVyRnSWkl8V2uraniMd2dEdnZxODQIGSbuXFKz4HxT5Yi_u7-8HCpCol4COeDejPGT3US1yeuD9WaNjU6yx6ocqw6zCrvA2pGfUiT2atIegRMFZIr28/s72-c/Screen+Shot+2559-09-16+at+10.14.17+PM.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-895874865908560687</id><published>2016-09-15T16:25:00.001+07:00</published><updated>2016-09-15T16:25:23.713+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="container"/><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><title type='text'>สร้าง Docker Image from scratch</title><content type='html'>ปกติการสร้าง Docker Image เราจะใช้การสร้าง Dockerfile โดยที่บรรทัดแรกจะระบุว่าเอา Image ไหนเป็น base โดยใช้คำสั่ง FROM เช่น เอาจาก ubuntu เป็น base ก็เขียนแบบนี้&lt;br /&gt;&lt;br /&gt;FROM ubuntu&lt;br /&gt;&lt;br /&gt;
ทีนี้ถ้าเราอยากสร้างแค่ Image ที่มีโปรแกรม binary ของเราทำงานทันที เราสร้างได้โดยใช้ base จาก scratch ซึ่งเป็น base image พิเศษ ไม่ต้อง pull เพราะเมื่อ Docker เห็น scratch จะรู้ว่าเราต้องการสร้าง Image โดยไม่ต้องใช้อะไรเป็น base เลย ตัวอย่างเช่นผมสร้างโปรแกรมง่ายๆให้ปริ้น Hello, World! ที่หน้าจอ แล้วต้องการเอาไปรันภายใต้ Docker container ผมสามารถสร้าง Image ได้แบบนี้&lt;br /&gt;
&lt;br /&gt;
FROM scratch&lt;br /&gt;
COPY ./hello /hello&lt;br /&gt;ENTRYPOINT [&quot;/hello&quot;]&lt;br /&gt;&lt;br /&gt;เมื่อรัน sudo docker build -t hello .&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3VPasbWcx7VSodINxMF0lXvQgVCRYTG_5X6IyelnUirvFOdrCkITAb1EgOkTwSFWCUgxl9Fr4sInyu2ZQVN4sJKsmbAr7h74xvyE1t09_lAYN6nC2XcxkwmnNlCqhn-54V7Ne/s1600/Screen+Shot+2559-09-15+at+4.17.20+PM.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;196&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3VPasbWcx7VSodINxMF0lXvQgVCRYTG_5X6IyelnUirvFOdrCkITAb1EgOkTwSFWCUgxl9Fr4sInyu2ZQVN4sJKsmbAr7h74xvyE1t09_lAYN6nC2XcxkwmnNlCqhn-54V7Ne/s400/Screen+Shot+2559-09-15+at+4.17.20+PM.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
เราก็จะได้ image ใหม่ชื่อ hello&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKMbUDE-GprROTa_QCFTCFbLHHirxmzPsgRWjbdYI_ixddhqDgM6MBpBD0ADtSYejW8jkci_9dpGtEDkMLBWGRmRSLfSVmMwYK3hG9nNGODZnHdgju4FR8NmnyEc9Ktzt9L5l9/s1600/Screen+Shot+2559-09-15+at+4.19.49+PM.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;118&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKMbUDE-GprROTa_QCFTCFbLHHirxmzPsgRWjbdYI_ixddhqDgM6MBpBD0ADtSYejW8jkci_9dpGtEDkMLBWGRmRSLfSVmMwYK3hG9nNGODZnHdgju4FR8NmnyEc9Ktzt9L5l9/s640/Screen+Shot+2559-09-15+at+4.19.49+PM.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
ทดลองรัน image ขึ้นมาดูโดยสั่ง sudo docker run hello เราก็จะเห็นผลลัพธ์แบบนี้ครับ&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmy-p1xld_Ze4JBhU78GSatlAXwzlGZhwfiqypcmgQGFVdVfSfC9myjWXykbsqNLwTbIdVW98NB4inXPsIld16kHsVIhyFu5FL-z9_aZ4CE4xguVQ5GupeKUjqOiaHjWQSBui-/s1600/Screen+Shot+2559-09-15+at+4.21.04+PM.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;60&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmy-p1xld_Ze4JBhU78GSatlAXwzlGZhwfiqypcmgQGFVdVfSfC9myjWXykbsqNLwTbIdVW98NB4inXPsIld16kHsVIhyFu5FL-z9_aZ4CE4xguVQ5GupeKUjqOiaHjWQSBui-/s400/Screen+Shot+2559-09-15+at+4.21.04+PM.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/895874865908560687/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/895874865908560687' title='1 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/895874865908560687'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/895874865908560687'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2016/09/docker-image-from-scratch.html' title='สร้าง Docker Image from scratch'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3VPasbWcx7VSodINxMF0lXvQgVCRYTG_5X6IyelnUirvFOdrCkITAb1EgOkTwSFWCUgxl9Fr4sInyu2ZQVN4sJKsmbAr7h74xvyE1t09_lAYN6nC2XcxkwmnNlCqhn-54V7Ne/s72-c/Screen+Shot+2559-09-15+at+4.17.20+PM.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-4189707278277563778</id><published>2015-07-30T21:38:00.001+07:00</published><updated>2015-07-30T21:38:06.697+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Actor Model"/><category scheme="http://www.blogger.com/atom/ns#" term="erlang"/><title type='text'>อธิบาย Actor Model ด้วย Erlang</title><content type='html'>บอกพี่ &lt;a class=&quot;g-profile&quot; href=&quot;https://plus.google.com/115475644044373253491&quot; target=&quot;_blank&quot;&gt;+Adisorn Chockaumnuai&lt;/a&gt; &amp;nbsp;เดี๋ยวเขียน blog อธิบายเรื่อง Actor Model ให้ แต่ขออธิบายโดยโค้ด Erlang นะ เพราะผมยังไม่เคยใช้ Actor Model ของภาษาอื่น เริ่มเลยแล้วกัน&lt;br /&gt;
&lt;br /&gt;
Actor Model คือวิธีการออกแบบที่เราให้สิ่งต่างๆเป็น Actor และสื่อสารกันโดยการส่ง message ไปมาระหว่าง Actor ถ้ามองแบบเทียบกับการออกแบบ แบบ Object ก็คล้ายๆกัน แต่ต่างกันตรง การส่ง message ของ OOP มักจะอยู่ในรูปของ method ที่ทำงานเป็นแบบ sequential แต่สำหรับ Actor Model การส่ง message ไปหา Actor จะเป็นแบบ concurrent คือเราส่งไปได้เลย ไม่ต้องรอ (non-blocking/async) เหมือนกับการส่งจดหมาย ที่จะส่งเข้ากล่องรับจดหมายไปก่อนเลย ไม่ต้องรอว่าคนรับจะอ่านจดหมายเราตอนไหน การส่งจดหมายแต่ละครั้งก็ต้องส่งโดยระบุชื่อ ที่อยู่ผู้รับให้ชัดเจน ถ้าเราต้องการให้เขาตอบกลับ ก็ต้องระบุชื่อที่อยู่ผู้ส่งให้ชัดเจนเช่นกัน&lt;br /&gt;&lt;br /&gt;ตัวอย่างเช่น&lt;br /&gt;&lt;br /&gt;Actor1&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; —— Hello —&amp;gt; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Actor2&lt;br /&gt;Actor1&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;— Hi — &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; Actor2&lt;br /&gt;&lt;br /&gt;ดูตัวอย่างโค้ดของ Erlang เลยแล้วกัน&lt;br /&gt;&lt;br /&gt;สำหรับ Erlang Actor ก็คือ process แต่ละ process ที่ถูกสร้างขึ้นมานั่นเอง สำหรับ erlang สร้าง process ใหม่ได้ด้วยฟังก์ชัน spawn เพื่อบอกให้ทำงานฟังก์ชันโดยแยกเป็น process ใหม่ แล้วจะได้ process id เป็นหมายเลขอ้างอิงของ process นั้นๆเช่น&amp;nbsp; ซึ่งการจะส่ง message เราต้องใช้ process id เนี่ยแหละ แทนชื่อที่อยู่ผู้รับ แบบการส่งจดหมาย&amp;nbsp; ถ้ามีฟังก์ชันดังนี้&lt;br /&gt;&lt;br /&gt;-module(account).&lt;br /&gt;&lt;br /&gt;-export([add/2]).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;add(A, B) -&amp;gt;&lt;br /&gt;&lt;br /&gt;A+B.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;แล้วใน erlang shell ผมลองสั่งแบบนี้&lt;br /&gt;&lt;br /&gt;&amp;gt; account:add(10,20).&lt;br /&gt;&lt;br /&gt;30&lt;br /&gt;&lt;br /&gt;จะได้ผลลัพธ์ออกมาเป็น 30 เลย แบบนี้คือการเรียกฟังก์ชันให้ทำงานธรรมดา ไม่ได้สร้างออกไปเป็น process ใหม่ แต่ถ้าผมเรียกแบบนี้&lt;br /&gt;&lt;br /&gt;&amp;gt; spawn(account, add, [10,20]).&lt;br /&gt;&amp;lt;0.38.0&amp;gt;&lt;br /&gt;&lt;br /&gt;จะเห็นหมายเลข process id เป็น &amp;lt;0.38.0&amp;gt; ออกมาแทน นั่นคือ PID ของ&amp;nbsp; process ใหม่ และเราไม่เห็นผลลัพธ์การทำงานที่ shell เพราะว่ามันทำงานที่อีก process&lt;br /&gt;&lt;br /&gt;ทีนี้มาดูโค้ดอีกแบบกัน&lt;br /&gt;&lt;br /&gt;-module(account).&lt;br /&gt;&lt;br /&gt;-export([account/1]).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;account(Balance) -&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; receive&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {deposit, Amount} -&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; account(Balance + Amount);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {witdraw, Amount} -&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; account(Balance - Amount);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {balance, Sender} -&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Sender ! {balance, Balance},&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; account(Balance);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _otherwise -&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; account(Balance)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;receive end เป็น block ที่บอกให้ process ที่กำลังรัน account อยู่ให้หยุดรอรับ message ที่เข้ามาที่ process โดยที่ภายใน receive end จะเป็น pattern matching ว่าถ้ามี message เข้ามาใน pattern ทางด้านซ้ายของ -&amp;gt; จะทำงานทางด้านขวา&lt;br /&gt;&lt;br /&gt;จากโค้ด ผมออกแบบให้รองรับ message 4 pattern ด้วยกันคือ&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;{deposit, Amount} -&amp;gt; โดยที่ตรง Amount เป็นค่าที่ต้องการเอามาเพิ่มเข้าไปที่ balance โดยเราจะเรียก account อีกรอบพร้อมกำหนด balance ใหม่เข้าไปเพื่อรอรับ message ต่อไป&lt;br /&gt;&lt;br /&gt;{witdraw, Amount} -&amp;gt; เหมือนกับ deposit แต่เราทำการลบค่า balance ออกแทน&lt;br /&gt;&lt;br /&gt;{balance, Sender} -&amp;gt; โดยที่ Sender ต้องเป็น process id ที่ต้องการรู้ค่า balance เราจะส่ง ค่า balance ตอบกลับไปให้ process นั้น&lt;br /&gt;&lt;br /&gt;_otherwise -&amp;gt; โดยที่การใช้ _ บอกว่าเป็นค่าอะไรก็ได้ เราจะไม่ทำอะไร เราจะแค่กลับไปรอรับ message อื่นต่อไป&lt;br /&gt;&lt;br /&gt;นี่คือตัวอย่างการส่ง message ไปมากับ process account โดยที่ Erlang ใช้สัญลักษณ์ ! ในการส่ง message โดยให้ PID อยู่ด้านซ้าย และ message อยู่ด้านขวา&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1&amp;gt; c(account).&lt;br /&gt;{ok,account}&lt;br /&gt;2&amp;gt; Acc = spawn(account, account, [100]).&lt;br /&gt;&amp;lt;0.39.0&amp;gt;&lt;br /&gt;3&amp;gt; Acc ! {balance, self()}.&lt;br /&gt;{balance,&amp;lt;0.32.0&amp;gt;}&lt;br /&gt;4&amp;gt; flush().&lt;br /&gt;Shell got {balance,100}&lt;br /&gt;ok&lt;br /&gt;5&amp;gt; Acc ! {deposit, 500}.&lt;br /&gt;{deposit,500}&lt;br /&gt;6&amp;gt; Acc ! {balance, self()}.&lt;br /&gt;{balance,&amp;lt;0.32.0&amp;gt;}&lt;br /&gt;7&amp;gt; flush().&lt;br /&gt;Shell got {balance,600}&lt;br /&gt;ok&lt;br /&gt;8&amp;gt; Acc ! {witdraw, 200}.&lt;br /&gt;{witdraw,200}&lt;br /&gt;9&amp;gt; Acc ! {balance, self()}.&lt;br /&gt;{balance,&amp;lt;0.32.0&amp;gt;}&lt;br /&gt;10&amp;gt; flush().&lt;br /&gt;Shell got {balance,400}&lt;br /&gt;ok&lt;br /&gt;11&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;ที่เห็นเป็นการติดต่อกันระหว่าง 2 process คือ process ของ Shell และ process ของ account นั่นเอง ใน shell ถ้าเราจะดู message ที่ส่งมาแล้วค้างอยู่จะใช้คำสั่ง flush() ออกมานั่นเอง&lt;br /&gt;
&lt;br /&gt;
เท่านี้น่าจะพอเข้าใจ Actor Model ซึ่งในภาษาอื่นที่รองรับการเขียนแบบ Model นี้ก็มีอะไรคล้ายๆกันแบบนี้เช่นกัน แค่เขียนด้วย syntax ที่ต่างกันนั่นเอง&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/4189707278277563778/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/4189707278277563778' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4189707278277563778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4189707278277563778'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/07/actor-model-erlang.html' title='อธิบาย Actor Model ด้วย Erlang'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-4426346688283511057</id><published>2015-06-15T06:53:00.002+07:00</published><updated>2015-06-15T06:53:29.646+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="coding"/><title type='text'>vim การเลื่อน indent เวลาอยู่ใน mode insert, normal หรือ visual </title><content type='html'>เวลาใช้งาน vim ถ้าเราต้องค่าให้มัน auto indent ให้ เช่นแบบนี้&lt;br /&gt;
&lt;br /&gt;
au BufEnter *.scss set tabstop=4 shiftwidth=4 expandtab&lt;br /&gt;
&lt;br /&gt;
เวลาเรากด enter ขึ้นบรรทัดใหม่ มันก็จะขยับ indent ให้เองเช่น&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAZyw5Wi5eJNe7-Mye_YfWQq2aeCXzW-XsF_KuipdF52Y6RG0hdgeUg0OnVrWYUEfqX9wCOuDSVYes-3QRFCKiP_GlbRX2fg75QAlym9g5kvh4THXqWxsPObXZmpo-OldF75L6/s1600/Screen+Shot+2558-06-15+at+6.46.37+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;136&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAZyw5Wi5eJNe7-Mye_YfWQq2aeCXzW-XsF_KuipdF52Y6RG0hdgeUg0OnVrWYUEfqX9wCOuDSVYes-3QRFCKiP_GlbRX2fg75QAlym9g5kvh4THXqWxsPObXZmpo-OldF75L6/s320/Screen+Shot+2558-06-15+at+6.46.37+AM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
เห็นตำแหน่ง cursor ตรงบรรทัดที่ 7 นะว่ามันเลื่อน indent ให้เอง&lt;br /&gt;
&lt;br /&gt;
แต่เมื่อเราอยากขยับ cursor ตรงบรรทัดที่ 7 ไปซ้ายสุดล่ะ เพื่อเขียน selector ของ css อันใหม่ ก่อนหน้านี้ผมต้องกดลบเอาเอง แล้วที่นี้ผมตั้ง tab เป็น space เอาไว้ ต้องลบที่ละ 1 space เสียเวลามาก หรือไม่ก็ต้องกด esc กลับไป normal command mode ก่อนอีก ก็เสียเวลาเช่นกัน&lt;br /&gt;
&lt;br /&gt;
วันนี้เลยลองไปค้นดูเจอที่นี่ &lt;a href=&quot;http://stackoverflow.com/questions/4559896/vim-how-to-tab-backward&quot;&gt;http://stackoverflow.com/questions/4559896/vim-how-to-tab-backward&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
เลยรู้วิธีที่จะเลื่อนตำแหน่ง cursor หรือจัด indent ของทั้งบรรทัด แม้จะอยู่คนละ mode ก็ตาม ดังนี้&lt;br /&gt;
&lt;br /&gt;
ถ้าอยู่ใน insert mode ให้กด:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C-d - เลื่อน indent ไปทางซ้าย&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; C-t - เลื่อน indent ไปทางขวา&lt;br /&gt;&lt;br /&gt;ถ้าอยู่ใน normal (command) mode:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&amp;lt; - เลื่อน indent ไปทางซ้าย&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;gt;&amp;gt; - เลื่อน indent ไปทางขวา&lt;br /&gt;&lt;br /&gt;ถ้าอยู่ใน visual mode และทำการเลือก text หลายๆบรรทัดเอาไว้:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt; - เลื่อน indent ไปทางซ้าย&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;gt; - เลื่อน indent ไปทางขวา&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;เพียงเท่านี้ ก็ทำให้ใช้งานได้เร็วขึ้นอีก เพราะไม่เสียเวลาเคาะลบเองแล้ว</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/4426346688283511057/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/4426346688283511057' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4426346688283511057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4426346688283511057'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/vim-indent-mode-insert-normal-visual.html' title='vim การเลื่อน indent เวลาอยู่ใน mode insert, normal หรือ visual '/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAZyw5Wi5eJNe7-Mye_YfWQq2aeCXzW-XsF_KuipdF52Y6RG0hdgeUg0OnVrWYUEfqX9wCOuDSVYes-3QRFCKiP_GlbRX2fg75QAlym9g5kvh4THXqWxsPObXZmpo-OldF75L6/s72-c/Screen+Shot+2558-06-15+at+6.46.37+AM.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-7449881820918663893</id><published>2015-06-12T00:04:00.002+07:00</published><updated>2015-06-12T00:04:37.720+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="craftsmanship"/><title type='text'>ลูกค้า ไม่เท่ากับ ผู้ใช้งาน</title><content type='html'>สำหรับอาชีพ Developer ไม่ว่าจะรับงานรูปแบบไหน ทำงานประจำบริษัท หรือ รับงาน Freelance บางทีเราก็สับสนระหว่าง ลูกค้า และ ผู้ใช้งาน&lt;br /&gt;
&lt;br /&gt;
ลูกค้าคือใครได้บ้างล่ะ เอาง่ายๆในก็คนที่ยอมจ่ายเงินให้กับสิ่งที่เราทำให้ได้&lt;br /&gt;
&lt;br /&gt;
ส่วนผู้ใช้งาน อาจจะเป็นทั้งลูกค้าเราเอง และ หรือไม่ได้เป็นก็ได้&lt;br /&gt;
&lt;br /&gt;
ถ้ามีคนจ้างเราพัฒนา App ตัวนึง ลูกค้าคือคนจ้างเราทำนั่นล่ะ ส่วนผู้ใช้งานคือใครบ้างก็ได้ที่โหลด App นี้ไปใช้ ส่วนผู้ใช้คือลูกค้าของคนที่จ้างเราอีกที&lt;br /&gt;
&lt;br /&gt;
ในมุมของคนพัฒนา App เราอาจจะคิดถึงผู้ใช้งานเป็นหลัก จนลืมปัจจัยอื่นๆในมุมมองของลูกค้าผู้จ้างเราก็ได้ เขาอาจจะมีปัจจัยภายในองค์กรต่างๆที่เราไม่รู้ก็ได้เช่นกัน&lt;br /&gt;
&lt;br /&gt;
เราควรจะต้องคุยกับลูกค้า เสนอสิ่งที่เราคิดว่าดีกับลูกค้า แต่ถ้าลูกค้าบอกปฎิเสธ ไม่ใช่เรื่องที่เราจะต้องเอามาโกรธลูกค้าแต่อย่างใด เราต้องขอให้ลูกค้าเล่าให้ฟัง ว่ามีปัจจัยอะไรหรือไม่ ทำไมถึงตัดสินใจแบบนั้น เพื่อที่เราจะได้เข้าใจ และ ช่วยปรับให้ดีที่สุดเราที่เราจะคิดออกได้ต่อไป&lt;br /&gt;
&lt;br /&gt;
สุดท้ายยังไงก็แล้วแต่ ลูกค้าต้องอยู่กับสิ่งที่เราทำให้ต่อไป เพราะมันเป็นธุรกิจที่เขาทำ เราต้องให้เขาตัดสินใจ และเราก็เคารพการกันสินใจของลูกค้า และหาทางช่วยเหลือกันไปเท่าที่จะทำได้ &lt;br /&gt;
&lt;br /&gt;
และท้ายสุด ถ้าลูกค้าเลือกทางที่เราก็ไม่สามารถจะทำธุรกิจร่วมกันได้ต่อไป ก็ต้องบอกกันตรงๆ และแยกทางกันไป</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/7449881820918663893/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/7449881820918663893' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7449881820918663893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7449881820918663893'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/customer-or-user.html' title='ลูกค้า ไม่เท่ากับ ผู้ใช้งาน'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-3601170706276797522</id><published>2015-06-11T06:33:00.002+07:00</published><updated>2015-06-11T06:33:30.284+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="craftsmanship"/><title type='text'>Code ที่ดี จะทำงานกันเป็น Team</title><content type='html'>&amp;nbsp;เมื่อวานผมลอง Refactor งานที่ทำในส่วนของ Javascript ที่ใช้ Angular.js เป็น framework ช่วยเขียน ซึ่งตอนแรก ส่วนที่ทำ โค้ดจะแบบเป็น tempalte html และมี controller ใช้ service เป็นส่วนที่รับหน้าที่เรียก API หลังบ้านเอาข้อมูลกลับมา ส่วน controller จะเรียกใช้ service อีกที เพื่อ binding ข้อมูลกับ tempalte&lt;br /&gt;
&lt;br /&gt;
สิ่งที่เกิดขึ้นก่อนที่จะแก้เมื่อวานคือ controller ใหญ่มาก ไฟล์ขนาด 170 กว่าบรรทัด ส่วน service เล็กนิดเดียว เพราะทำหน้าที่แค่เรียก HTTP API แล้วก็ส่ง promise กลับ&lt;br /&gt;
&lt;br /&gt;
ใน controller เนี่ยทำแทบทุกอย่าง ทั้ง Binding UI template ทั้งมี Logic ในการแสดงผล Logic ในการปรับแต่งข้อมูลที่รับมาแล้วจาก service มีเรื่องการ sorting ด้วย รวมอัดใน controller เต็มไปหมด&lt;br /&gt;
&lt;br /&gt;
ถ้าเราเอาโครงสร้าง Code ที่เราเขียน มาเทียบกับทีมทีมหนึ่ง จะเห็นว่า Controller นี่มันทำตัวเป็นฮีโร่มากเลยนะ รับหน้าที่เกือบทุกอย่าง ซึ่งการมีฮีโร่ในทีมแบบนี้ถือว่าไม่ดี ทีมควรจะแบ่งหน้าทีความรับผิดชอบให้ดีกว่านี้&lt;br /&gt;
&lt;br /&gt;
ผลที่ได้จากการ Refactor เมื่อวานคือ Controller จาก 170 กว่า เหลือ 40 กว่าบรรทัด เพราะลองแบ่งดีๆจะพบว่า Controller ควรทำหน้าที่ binding ข้อมูลกับ UI เท่านั้น ไม่ควรมี Logic อะไรมากมาย ส่วนเรื่องการเตรียมข้อมูล หรือ Logic ผมทำการเพิ่มอีก Service นึงเข้ามาจัดการให้ และ ยังแยก ส่วนที่เป็น model ของ record ที่จะแสดงในตารางตรง UI ออกมาด้วยเพื่อให้เป็น Logic ของแต่ละ record&lt;br /&gt;
&lt;br /&gt;
สุดท้ายก็ได้โค้ดที่เปิดออกมาเข้าใจ Flow การทำงานตรงนั้นว่าทำอะไร ถ้าอยากจะเห็นรายละเอียดของอีกเรื่อง ก็ไปเปิดอีกไฟล์ได้ ซึ่งก็จะเห็น Flow เฉพาะเรื่องนั้นๆไป</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/3601170706276797522/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/3601170706276797522' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/3601170706276797522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/3601170706276797522'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/code-like-team.html' title='Code ที่ดี จะทำงานกันเป็น Team'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-7752175807378891389</id><published>2015-06-09T22:28:00.002+07:00</published><updated>2015-06-09T22:28:30.616+07:00</updated><title type='text'>มนุษย์ เป็นสัตว์ที่ต้องการ ความเข้าใจ</title><content type='html'>ใช้แล้ว เราก็เป็นสัตว์แบบหนึ่งบนโลกใบนี้นั่นแหละ และเราก็พอจะรู้ตัวเรากันเองว่า เราเป็นสัตว์สังคม คือต้องอยู่อาศัยกันเป็นกลุ่ม พึ่งพากันและกันถึงจะอยู่รอด&lt;br /&gt;
&lt;br /&gt;
ไม่ว่าจะเป็นคนเด่นดัง มีตำแหน่งใหญ่โตแค่ไหน มนุษย์ทุกคน ก็ยังเป็นมนุษย์นั่นละ ซึ่งอยากรู้สึกว่า&amp;nbsp; &lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;b&gt;&quot;มีคนเข้าใจ&quot;&lt;/b&gt; &lt;/blockquote&gt;
และเมื่อมนุษย์รู้สึกว่า มีคนเข้าใจ สิ่งที่จะตามมาก็คือ การเปิดใจ รับฟังสิ่งที่คนที่เขารู้สึกว่าเข้าใจเขาพูด ยินดีที่จะพูดคุย ช่วยเหลือ ให้คนที่เข้าใจตัวเองมากกว่าคนที่ทำให้เขารู้สึกว่าไม่เข้าใจเขาเสียเลย&lt;br /&gt;
&lt;br /&gt;
ดังนั้น ถ้าเราจะสื่อสารกับใคร ให้พยายาม สื่อสารให้เข้าไว้ใจเรา ว่าเราเข้าใจสถานการณ์ที่เข้าเจอให้ได้ อยากไปรีบร้อนบอกสิ่งที่เราต้องการ หรือตำหนิ ถ้าเขาไม่ยอมทำอย่างที่เราต้องการ ให้พูดคุยให้เขาเห็นว่าเราเข้าใจ เห็นใจ สิ่งที่เขาเจอ ที่เข้าเป็นให้ได้ แล้วจากนั้น เขาจะยอมรับฟังสิ่งที่เราต้องการบอกเอง&lt;br /&gt;
&lt;br /&gt;
ป.ล. เป็นความรู้ที่ลองสรุปในมุมของตัวเองหลังจากอ่านหนังสือ &quot;เงียบ ให้ถูกจังหวะ คนชนะ ไม่พูดมาก&quot;&amp;nbsp; Just Listen: Discover the Secret to Getting Through to Absolutely Anyone ; Mark Goulston เขียน; นุชนาฎ เนตรประเสริฐศรี แปล (ยังอ่านไม่จบ)</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/7752175807378891389/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/7752175807378891389' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7752175807378891389'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7752175807378891389'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/just-listen.html' title='มนุษย์ เป็นสัตว์ที่ต้องการ ความเข้าใจ'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-1353800661284242520</id><published>2015-06-08T23:35:00.002+07:00</published><updated>2015-06-08T23:35:55.282+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="craftsmanship"/><title type='text'>Listen to your code.</title><content type='html'>&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;http://www.imagesbuddy.com/images/120/2013/12/listen-to-your-heart.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;http://www.imagesbuddy.com/images/120/2013/12/listen-to-your-heart.jpg&quot; height=&quot;150&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&quot;Listen to the technical people. If they are complaining about the difficulty of making changes, then take such complaints seriously and give them time to fix things. &quot; - Martin Fowler (&lt;a href=&quot;http://www.martinfowler.com/articles/designDead.html&quot;&gt;Is Design Dead?&lt;/a&gt;)&lt;/blockquote&gt;
&lt;br /&gt;
เมื่อวานกับวันนี้ เกิดปัญหากับระบบที่กำลังพัฒนาอยู่ ทุกคนต่างช่วยกันหาทางออก หาทางแก้ ไม่ว่าจะดูที่ Log ไม่ว่าจะดูที่ Dashboard ของการ monitor ระบบ ช่วยกันทุกๆทางที่จะเป็นไปได้&lt;br /&gt;
&lt;br /&gt;
สุดท้ายเราทุกคนตัดสินใจมาดูที่ Code เปิดโค้ดออกที่จอใหญ่ แล้วดูด้วยกัน แทบทุกตำแหน่ง ทั้ง Dev ทั้งทีม PO ทั้ง ที่ปรึกษาของระบบรอบข้างที่เราไปติดต่อด้วย ทุกคนช่วยกันดูที่ Code&lt;br /&gt;
&lt;br /&gt;
แม้เราจะไม่ได้เจอจุดพลาดอะไรร้ายแรง แต่เราก็เห็นร่วมกันว่าควรจะปรับปรุงตรงไหน เห็นด้วยกันว่าโค้ดที่เราทำยังอ่านยากยังไง ได้จุดที่เอาไปปรับปรุงเพื่อให้เราพลาดน้อยลง&lt;br /&gt;
&lt;br /&gt;
จะเห็นว่า ถ้าเราดูและฟังสิ่งที่โค้ดสะท้อนออกมา เราก็จะเข้าใจระบบเราจริงๆ และถ้าเราทำให้โค้ดมันสะท้อนสิ่งที่เราต้องการ สะท้อนสิ่งที่เราพูดคุยกัน วันหลังเรากลับมาดูโค้ดกันอีกครั้งก็จะเจอปัญหาที่เราไม่เคยเจอมาก่อนได้เร็วมากๆ&lt;br /&gt;
&lt;br /&gt;
ทางทีดีหมั่นดูและรับฟังโค้ดเรากันบ่อยๆครับ และค่อยๆปรับปรุงไปทุกๆรอบการทำงานจะดีที่สุด</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/1353800661284242520/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/1353800661284242520' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/1353800661284242520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/1353800661284242520'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/listen-to-your-code.html' title='Listen to your code.'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-6685851400574593729</id><published>2015-06-06T23:57:00.001+07:00</published><updated>2015-06-06T23:57:33.982+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Go"/><category scheme="http://www.blogger.com/atom/ns#" term="Golang"/><category scheme="http://www.blogger.com/atom/ns#" term="Training"/><title type='text'>สรุปสอน Introduction Go รอบที่ 3</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglAjcuyYl0k79xO6FDRziZcjSjaYUDSxE6O_SbAClhGbylWQ6j8psvL6GBcy8edvtnvEzJ9-JD3qO-g-xp0HF_sZVCjAr_ZDfyZx69eaqT8MjFuHegtX9UbnI2s0jtYyROVVPs/s1600/go.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglAjcuyYl0k79xO6FDRziZcjSjaYUDSxE6O_SbAClhGbylWQ6j8psvL6GBcy8edvtnvEzJ9-JD3qO-g-xp0HF_sZVCjAr_ZDfyZx69eaqT8MjFuHegtX9UbnI2s0jtYyROVVPs/s200/go.png&quot; width=&quot;141&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
วันนี้เป็นครั้งที่ 3 แล้วที่ช่วยๆกันสอน Go ฟรีๆ 1 วัน เราก็ได้เรียนรู้จากสองครั้งแรกกันพอสมควร กับเวลาในการสอนแค่ไม่กี่ชั่วโมง สองครั้งแรกเราลุยทำ workshop กันเลย ไม่ได้อธิบาย basic syntax อะไรทั้งสิ้น ติดปัญหากันพอสมควร โดยเฉพาะครั้งที่ 2 ที่เราเลือกให้ต่อ Mongodb กันด้วย ไหนจะเรื่องลง git เรื่อง mongodb เบื้องต้น&lt;br /&gt;
&lt;br /&gt;
ทำให้รอบที่ 3 เราตัดสินใจกันว่า เราจะใช้แค่ package ที่มาพร้อมกับตอนติดตั้ง Go สอนเท่านั้น และจะมีสอน basic syntax ก่อนด้วย ในส่วนของ workshop ก็ให้ใช้เก็บใน type map ธรรมดาๆแทนการต่อ db ข้างนอก&lt;br /&gt;
&lt;br /&gt;
วันนี้ผมเริ่มเปิดเรื่องให้ โดยอธิบายหลักการและเป้าหมายที่ใช้ในการออกแบบภาษา Go ของทีมงานพัฒนาภาษา โดยผมเอามาจาก slide ของ Rob Pike มีรูปจากเมียที่ทำสรุปให้ประกอบ คือรูปนี้&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSRI9FirVkGo9CKezEzgV5Z436G0SiKYfYSIS72y8FyV6eka8LYyJhEUE5OhVo6IKnOt5NIyYc3MomxrYdU3_MiyqfAFIf1_S2dGppw2U1bOwi7o9fH7tVFFvHKvDfx7q41Li/s1600/whatgo.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSRI9FirVkGo9CKezEzgV5Z436G0SiKYfYSIS72y8FyV6eka8LYyJhEUE5OhVo6IKnOt5NIyYc3MomxrYdU3_MiyqfAFIf1_S2dGppw2U1bOwi7o9fH7tVFFvHKvDfx7q41Li/s400/whatgo.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6HOAgCwcCCTblVMPBXj5-oT8dU0ackKu_zAhIKnFFfhDZgOJqSpqD-blA8CLrnVLztYG_OjvI6AoSnQsz3TTIb69yPFWsF1LLCzbVEjIHAkb-4t7n0f3UAWZdqLMJ5jbdGPs4/s1600/gosummary.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;300&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6HOAgCwcCCTblVMPBXj5-oT8dU0ackKu_zAhIKnFFfhDZgOJqSpqD-blA8CLrnVLztYG_OjvI6AoSnQsz3TTIb69yPFWsF1LLCzbVEjIHAkb-4t7n0f3UAWZdqLMJ5jbdGPs4/s400/gosummary.jpg&quot; width=&quot;400&quot; /&gt;&amp;nbsp;&lt;/a&gt;&amp;nbsp; &lt;/div&gt;
&lt;br /&gt;
คือ Go นั้นยึดหลัก Clarity is key ซึ่งได้พี่หนุ่มช่วยแปลคำสวยๆให้คือคำว่า &quot;ความชัดเจนถือเป็นหัวใจหลักของ Go&quot; ซึ่งนำมาสู่การทำให้โค้ดสามารถอ่านเข้าใจได้ง่าย มี Concurrency ในตัวทำให้ Scale ได้ จัดการกับ Code Base ขนาดใหญ่ได้ดีเพราะตรวจสอบสิ่งที่ไม่ใช้ตั้งแต่ต้นออก เน้นการสร้าง Tool ขึ้นมาช่วยงานต่างๆ และ ย้ำว่า Go ไม่ได้เหมาะกับทุกงานทุกสถานการณ์เสมอไป&lt;br /&gt;
&lt;br /&gt;
หลังจากนั้นได้ วิน ช่วยสอนต่อเป็นหลัก ผมจะเสริมๆบางเรื่องไปเรื่อยๆ วันนี้ได้จบลงตรงการสร้าง HTTP Service โดยข้อมูลส่งไปมาเป็น JSON สิ่งที่สอนไปจำได้คร่าวๆดังนี้&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Basic Syntax&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;เรื่องการติดตั้ง&lt;/li&gt;
&lt;li&gt;การตั้งค่า environment variable ต่างๆ GOROOT , GOPATH&lt;/li&gt;
&lt;li&gt;การสร้าง package การสร้าง main&lt;/li&gt;
&lt;li&gt;การประกาศตัวแปร&lt;/li&gt;
&lt;li&gt;ประเภทข้อมูลเบื้องต้น int, string, bool&lt;/li&gt;
&lt;li&gt;array, slice, map&lt;/li&gt;
&lt;li&gt;เรื่อง control ต่างๆ if, for , switch&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;ต่อมา workshop ยังทำโจทย์เก็บข้อมูล contact ทำให้ได้เรียนรู้เรื่องต่างๆไปด้วยคือ&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;การสร้ง&amp;nbsp; package ใหม่&lt;/li&gt;
&lt;li&gt;การสร้าง function&amp;nbsp;&lt;/li&gt;
&lt;li&gt;การตั้งชื่อเพื่อกำหนดการเข้าถึงสิ่งต่างๆใน package &lt;/li&gt;
&lt;li&gt;การสร้าง type struct ขึ้นเอง&lt;/li&gt;
&lt;li&gt;การสร้าง HTTP server ด้วย package net/http&lt;/li&gt;
&lt;li&gt;การเขียน unittest ด้วย package testing และใช้ go test ช่วย run test&lt;/li&gt;
&lt;li&gt;การ encode / decode JSON&lt;/li&gt;
&lt;li&gt;การเขียน httptest&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;สุดท้ายมีเวลาอีกนิด ผมสอนเรื่อง method และ interface ไปนิดหน่อย &lt;/li&gt;
&lt;/ul&gt;
จะเห็นว่าผมสอนพื้นฐานกันมาถึงแค่เรื่อง function ใน package แล้วก็เอาไปทำ HTTP Service กันก่อนเลย เพราะเนื่องจากข้อจำกัดของเวลา ทำให้ผมตัดสินใจมาทางนี้ เพราะเท่านี้ก็สามารถนำเอาไปใช้ประโยชน์ได้จริงๆแล้ว&lt;br /&gt;
&lt;br /&gt;
ส่วนเรื่อง Method และ Interface เป็นสิ่งที่จะทำให้เราเขียน Go ได้สำนวน (Idiom) Go มากยิ่งขึ้น ผมคิดว่าคงต้องใช้เวลาเพิ่มอีกถึงจะเข้าใจได้กว่านี้เลยไม่เน้นมากในเวลาวันเดียว&lt;br /&gt;
&lt;br /&gt;
ส่วนเรื่อง Concurrency วันนี้ไม่ได้พูดถึงเลย คิดกันไว้ว่าเราจะเปิดเฉพาะ Concurrency with Go แยกต่างหากเลย แต่ว่าคงขอซ้อมสอนกันเองก่อน&lt;br /&gt;
&lt;br /&gt;
ขอบคุณทุกๆท่านที่มาฟังเราสอนวันนี้ครับ ผิดพลาดประการใด ขอนำไปปรับปรุงในการสอนครั้งต่อๆไป </content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/6685851400574593729/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/6685851400574593729' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/6685851400574593729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/6685851400574593729'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/training-introduction-go-3.html' title='สรุปสอน Introduction Go รอบที่ 3'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglAjcuyYl0k79xO6FDRziZcjSjaYUDSxE6O_SbAClhGbylWQ6j8psvL6GBcy8edvtnvEzJ9-JD3qO-g-xp0HF_sZVCjAr_ZDfyZx69eaqT8MjFuHegtX9UbnI2s0jtYyROVVPs/s72-c/go.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-7711570690888050804</id><published>2015-06-05T02:16:00.001+07:00</published><updated>2015-06-05T02:16:18.914+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Agile"/><category scheme="http://www.blogger.com/atom/ns#" term="BDD"/><category scheme="http://www.blogger.com/atom/ns#" term="SBE"/><category scheme="http://www.blogger.com/atom/ns#" term="Scenario"/><category scheme="http://www.blogger.com/atom/ns#" term="User Stories"/><title type='text'>User Stories and Scenario Template</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk1wp0xfNcRLc67sX5DLEpGae0z1Baf9VnPg3x7n3z7EzkIXV_DADcPOwA9x4ZB77tcfPJJbjf2wScDhSXQ5UwuZrgJck5DdcsvlKotRUUx-3TNMrMhLH6T1E8sitpzlMHoe0M/s1600/Screen+Shot+2558-06-05+at+2.15.38+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;123&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk1wp0xfNcRLc67sX5DLEpGae0z1Baf9VnPg3x7n3z7EzkIXV_DADcPOwA9x4ZB77tcfPJJbjf2wScDhSXQ5UwuZrgJck5DdcsvlKotRUUx-3TNMrMhLH6T1E8sitpzlMHoe0M/s200/Screen+Shot+2558-06-05+at+2.15.38+AM.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
กำลังอ่านหนังสือ &lt;a href=&quot;http://www.infoq.com/minibooks/agile-guts&quot;&gt;Agile with Guts - A pragmatic guide to value-driven development&lt;/a&gt; ได้บอก template ของการเขียน &lt;b&gt;User stories&lt;/b&gt; ได้แบบนี้&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;As a&lt;/b&gt; &amp;lt;&lt;i&gt;who&lt;/i&gt;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;In order to&lt;/b&gt; &amp;lt;&lt;i&gt;how&lt;/i&gt;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;I want to&lt;/b&gt; &amp;lt;&lt;i&gt;what&lt;/i&gt;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
นั่นคืออยู่ในรูปของ ใคร? (who) ต้องการที่จะทำให้เกิดอะไร? (how) และจะใช้วิธีการไหน? (what)&lt;br /&gt;
&lt;br /&gt;
ส่วนถ้าใครเคยอ่านเกี่ยวกับเรื่อง &lt;b&gt;BDD&lt;/b&gt; (Behavior Driven Development) หรือ &lt;b&gt;SBE&lt;/b&gt; (Specification by Example) คงเคยเห็นรูปแบบนี้&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Given&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;When&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Then&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
รูปแบบนี้เอาไว้ยกตัวอย่าง &lt;b&gt;Scenario&lt;/b&gt; ที่เกิดขึ้นของ &lt;b&gt;User stories&lt;/b&gt; นั่นเอง&lt;br /&gt;
&lt;br /&gt;
ตัวอย่างเช่น&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;As a &lt;/b&gt;&lt;i&gt;ลูกค้า เป็นสมาชิก Online Banking&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;In order&lt;/b&gt; &lt;i&gt;ตรวจสอบยอดเงินคงเหลือในบัญชี&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;I want to&lt;/b&gt; &lt;i&gt;สามารถเข้าสู่ระบบแล้วกดดูยอดเงินคงเหลือล่าสุดได้&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
Scenario ที่ 1&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Given&lt;/b&gt; &lt;i&gt;ลูกค้าที่มีเงินในบัญชี 1000 บาท และเป็น สมาชิก Online Banking เข้าสู่ระบบแล้ว&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;When&lt;/b&gt; &lt;i&gt;เลือกเมนู ตรวจสอบยอดเงินคงเหลือ&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Then&lt;/b&gt; &lt;i&gt;ควรจะต้องเห็นยอดเงินในบัญชีแสดง 1,000 บาท&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/7711570690888050804/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/7711570690888050804' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7711570690888050804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7711570690888050804'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/user-stories-and-scenario-template.html' title='User Stories and Scenario Template'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgk1wp0xfNcRLc67sX5DLEpGae0z1Baf9VnPg3x7n3z7EzkIXV_DADcPOwA9x4ZB77tcfPJJbjf2wScDhSXQ5UwuZrgJck5DdcsvlKotRUUx-3TNMrMhLH6T1E8sitpzlMHoe0M/s72-c/Screen+Shot+2558-06-05+at+2.15.38+AM.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-4524253038500285708</id><published>2015-06-04T00:27:00.000+07:00</published><updated>2015-06-04T00:27:21.232+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Concept"/><category scheme="http://www.blogger.com/atom/ns#" term="Context"/><category scheme="http://www.blogger.com/atom/ns#" term="oop"/><title type='text'>Methods have a Context</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPo7ePezlvz6BQM1SMCaAauEFutNfyyFHGmfWXdVS8KF5_S618mTxkvKfWhOtzwY4r13m3HczwDiLog8xqNqOCo7oYXyZfIN2X5s8BshSoU6qQH-c-qDCqBB2dsuoXe4_J_FU0/s1600/Screen+Shot+2558-06-04+at+12.24.00+AM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPo7ePezlvz6BQM1SMCaAauEFutNfyyFHGmfWXdVS8KF5_S618mTxkvKfWhOtzwY4r13m3HczwDiLog8xqNqOCo7oYXyZfIN2X5s8BshSoU6qQH-c-qDCqBB2dsuoXe4_J_FU0/s200/Screen+Shot+2558-06-04+at+12.24.00+AM.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
สมัยเรียน Object Oriented Programming (OOP) แรกๆ นั้นเข้าใจว่า OOP ช่วยให้เราจำลองโลกจริงๆให้เราสามารถเขียนโปรแกรมได้อ่านง่าย และ เข้าใจได้ง่ายมากขึ้น&lt;br /&gt;
&lt;br /&gt;
ซึ่งนั้นก็เป็นประโยชน์ของ OOP ส่วนนึง วันนี้ผมเห็นอีกมุมในการออกแบบ นั่นคือถ้าเรามองในมุมภาษาแบบ Procedural ธรรมดาเช่นภาษา C เราสร้างฟังก์ชัน เพื่อทำงานกับข้อมูลที่เราต้องการ โดยการส่งค่าข้อมูลนั้นไปเป็นพารามิเตอร์ของฟังก์ชัน ถ้าในการทำงานของฟังก์ชัน ต้องไปเรียน ฟังก์ชันอื่นต่อไปอีกที่ต้องการข้อมูลเดียวกัน ก็จะทำให้ส่งข้อมูลต่อไปเรื่อยๆ ตัวอย่างเช่น&lt;br /&gt;
&lt;br /&gt;
มีข้อมูลอยู่ในตัวแปร D&lt;br /&gt;
&lt;br /&gt;
มีฟังก์ชัน A , B , C ดังนี้&lt;br /&gt;
&lt;br /&gt;
function A(D) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; b = B(D)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; c = C(D, b) &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function B(D) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; return D.x&amp;nbsp;+ 10 &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function C(D, n) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; return D.y&amp;nbsp;+ n &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
จะเห็นว่าฟังก์ชัน A , B และ C ต้องส่งค่า D ไปด้วยเสมอ การทำงานของ A, B และ C เกี่ยวข้องกับข้อมูลของ D เสมอ&lt;br /&gt;
&lt;br /&gt;
ในโลกของ OOP เราสามารถสร้าง D เป็น Object แทนที่จะเป็นตัวแปรแยกแล้วส่งเข้าฟังก์ชัน แล้วสร้าง A, B และ C เป็น Method สำหรับ Object D ทั้ง A, B และ C ทำงานภายใต้ context ของ D เสมอนั่นเอง&lt;br /&gt;
&lt;br /&gt;
ทำให้เวลาสร้าง A, B และ C พารามิเตอร์จะเหลือแค่แบบนี้&lt;br /&gt;
&lt;br /&gt;
class D {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; function A() {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; b = B()&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; c = C(b) &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; function B() {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; function C(n) {&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
เวลาเรียกใช้ A ก็แค่ D.A()&lt;br /&gt;
&lt;br /&gt;
จะเห็นว่า method เราจะอ่านง่ายขึ้น ทดสอบได้ง่ายขึ้นด้วยนั่นเองเพราะเราสามารถ เปลี่ยนแปลงค่า context ของ D ได้ง่ายตอนทดสอบนั่นเอง &lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/4524253038500285708/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/4524253038500285708' title='1 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4524253038500285708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/4524253038500285708'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/methods-have-context.html' title='Methods have a Context'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPo7ePezlvz6BQM1SMCaAauEFutNfyyFHGmfWXdVS8KF5_S618mTxkvKfWhOtzwY4r13m3HczwDiLog8xqNqOCo7oYXyZfIN2X5s8BshSoU6qQH-c-qDCqBB2dsuoXe4_J_FU0/s72-c/Screen+Shot+2558-06-04+at+12.24.00+AM.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-7397738540751036910</id><published>2015-06-02T23:49:00.002+07:00</published><updated>2015-06-02T23:49:31.335+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional programming"/><category scheme="http://www.blogger.com/atom/ns#" term="Javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="Map"/><title type='text'>Javascript map function</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRdAidPVdlh_afKnSP89Afm-7gTErp5Fl8ia5ExU5KoHLyE5RkH5SS48JzABmnyGk8UvIAp4s1QiCQnkIhgz7EAHgZXCPsRrnvo6nAUYXHr40RLH4M_k962UtwlMRmlQ6orO-a/s1600/Mmww2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRdAidPVdlh_afKnSP89Afm-7gTErp5Fl8ia5ExU5KoHLyE5RkH5SS48JzABmnyGk8UvIAp4s1QiCQnkIhgz7EAHgZXCPsRrnvo6nAUYXHr40RLH4M_k962UtwlMRmlQ6orO-a/s200/Mmww2.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Array ของ javascript มีฟังก์ชัน map ที่จะรับค่าฟังก์ชันเข้าไปแล้วจะทำการวนซ้ำในข้อมูลแต่ละตัวของ Array เพื่อเรียกฟังก์ชันนั้นให้ทำงานโดยส่งแต่ละค่าใน Array ไปเป็น parameter ของ function เช่น&lt;br /&gt;
&lt;br /&gt;
var list = [1, 2, 3]; &lt;br /&gt;var result = list.map(function(e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return e + 5;&lt;br /&gt;});&lt;br /&gt;console.log(result);&lt;br /&gt;
&lt;br /&gt;
จะแสดง&lt;br /&gt;
&lt;br /&gt;
[6, 7, 8]&lt;br /&gt;
&lt;br /&gt;
จะเห็นว่าเมื่อทำงานเสร็จ จะได้ผลลัพธ์เป็น Array ขนาดเท่าเดิม ที่แต่ละค่าเป็นผลลัพธ์จากการทำงานของ function ที่ส่งเข้าไปนั่นเอง&lt;br /&gt;
&lt;br /&gt;
อีกตัวอย่างเช่น&lt;br /&gt;
&lt;br /&gt;
var names = [&quot;James&quot;, &quot;John&quot;, &quot;Jane&quot;];&lt;br /&gt;
&lt;br /&gt;
var sayHello = names.map(function(name) {&lt;br /&gt;
&amp;nbsp; &amp;nbsp; return &quot;Hello &quot;&amp;nbsp;+ name; &lt;br /&gt;
});&lt;br /&gt;
console.log(sayHello);&lt;br /&gt;
&lt;br /&gt;
จะแสดง&lt;br /&gt;
&lt;br /&gt;
[ &#39;Hello James&#39;, &#39;Hello John&#39;, &#39;Hello Jane&#39; ]</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/7397738540751036910/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/7397738540751036910' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7397738540751036910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7397738540751036910'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/javascript-map-function.html' title='Javascript map function'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRdAidPVdlh_afKnSP89Afm-7gTErp5Fl8ia5ExU5KoHLyE5RkH5SS48JzABmnyGk8UvIAp4s1QiCQnkIhgz7EAHgZXCPsRrnvo6nAUYXHr40RLH4M_k962UtwlMRmlQ6orO-a/s72-c/Mmww2.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-5250378859338574139</id><published>2015-06-01T23:52:00.003+07:00</published><updated>2015-06-01T23:52:30.517+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional programming"/><category scheme="http://www.blogger.com/atom/ns#" term="Javascript"/><title type='text'>Javascript forEach</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRdAidPVdlh_afKnSP89Afm-7gTErp5Fl8ia5ExU5KoHLyE5RkH5SS48JzABmnyGk8UvIAp4s1QiCQnkIhgz7EAHgZXCPsRrnvo6nAUYXHr40RLH4M_k962UtwlMRmlQ6orO-a/s1600/Mmww2.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRdAidPVdlh_afKnSP89Afm-7gTErp5Fl8ia5ExU5KoHLyE5RkH5SS48JzABmnyGk8UvIAp4s1QiCQnkIhgz7EAHgZXCPsRrnvo6nAUYXHr40RLH4M_k962UtwlMRmlQ6orO-a/s200/Mmww2.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
Javascript มีฟังก์ชัน forEach ให้ใช้ในการวนซ้ำโดยการสั่ง function เข้าไปแล้ว forEach จะทำการวนแต่ละรอบของใน Array แล้วเรียก function ให้เอง ตัวอย่างเช่น&lt;br /&gt;
&lt;br /&gt;
var arr = [1,2,3,4,5];&lt;br /&gt;&lt;br /&gt;arr.forEach(function(elem) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log(elem);&lt;br /&gt;});&lt;br /&gt;
&lt;br /&gt;
จะได้ผลลัพธ์&lt;br /&gt;
&lt;br /&gt;
1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;
&lt;br /&gt;
ถ้าต้องการเลข index ด้วยให้กำหนด arguments ที่สองให้กับ function ที่ส่งเข้าไป เช่น&lt;br /&gt;
&lt;br /&gt;
var arr = [1,2,3,4,5];&lt;br /&gt;&lt;br /&gt;arr.forEach(function(elem, index) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; console.log(&quot;index: &quot;, index, &quot;, elem: &quot; + elem);&lt;br /&gt;});&lt;br /&gt;
&lt;br /&gt;
จะได้ผลลัพธ์&lt;br /&gt;
&lt;br /&gt;
index:&amp;nbsp; 0 , elem: 1&lt;br /&gt;index:&amp;nbsp; 1 , elem: 2&lt;br /&gt;index:&amp;nbsp; 2 , elem: 3&lt;br /&gt;index:&amp;nbsp; 3 , elem: 4&lt;br /&gt;index:&amp;nbsp; 4 , elem: 5&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/5250378859338574139/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/5250378859338574139' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/5250378859338574139'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/5250378859338574139'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/06/javascript-foreach.html' title='Javascript forEach'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRdAidPVdlh_afKnSP89Afm-7gTErp5Fl8ia5ExU5KoHLyE5RkH5SS48JzABmnyGk8UvIAp4s1QiCQnkIhgz7EAHgZXCPsRrnvo6nAUYXHr40RLH4M_k962UtwlMRmlQ6orO-a/s72-c/Mmww2.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-5439731388367885884</id><published>2015-05-30T06:58:00.001+07:00</published><updated>2015-05-30T06:58:22.584+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Clojure"/><category scheme="http://www.blogger.com/atom/ns#" term="letfn"/><title type='text'>Clojure letfn</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF0K__MGyBsNRdHvEu1miMW8rLRJa_9D6_m1zazSOOIJdVj9vvpTKRFGaTRK8AyBzD1Red9ikDVRezfIn6Wt_D6QUhm_QamsySn-LrXNbwJmdZ0EtFHt39WlZUlJlK64HjcXjd/s1600/250px-Clojure-Logo.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF0K__MGyBsNRdHvEu1miMW8rLRJa_9D6_m1zazSOOIJdVj9vvpTKRFGaTRK8AyBzD1Red9ikDVRezfIn6Wt_D6QUhm_QamsySn-LrXNbwJmdZ0EtFHt39WlZUlJlK64HjcXjd/s200/250px-Clojure-Logo.png&quot; width=&quot;200&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
เคยโพสต์เกี่ยวกับ &lt;a href=&quot;http://www.iporsut.com/2015/05/clojure-let-scope.html&quot;&gt;let&lt;/a&gt; ของ Clojure ไปแล้ว ก่อนหน้านี้ วันนี้จะมาดูอีกรูปแบบในการสร้าง scope ของ function คือ letfn&lt;br /&gt;
&lt;br /&gt;
letfn ต่างจาก&amp;nbsp; let คือเราสามารถสร้าง function ได้ เช่น&lt;br /&gt;
&lt;br /&gt;
(letfn [(say [name] (str &quot;Good morning &quot; name))]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; (say &quot;iPorsut&quot;)&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
เราสามารถเอา letfn มาช่วยสร้างฟังก์ชันที่เป็น lazy-seq แล้วสร้างอีก function ครอบเพื่อเลือกว่าจะเอาแค่กี่ค่าแรกได้ เช่น สร้างฟังก์ชันที่เลือกค่า Fibonacci ออกมา เหมือนกับโจทย์นี้ &lt;a href=&quot;https://www.4clojure.com/problem/26&quot;&gt;Fibonacci Sequence&lt;/a&gt; ได้ดังนี้&lt;br /&gt;
&lt;br /&gt;
(defn fibo[n] &lt;br /&gt;&amp;nbsp; (letfn [&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (lazy-fibo&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ([] (lazy-fibo 1 1))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ([p c] (cons p (lazy-seq (lazy-fibo c (+ p c))))))]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (take n (lazy-fibo))))&lt;br /&gt;
&lt;br /&gt;
จริงๆเราก็สามารถใช้ let และ fn ช่วยสร้างฟังก์ชันได้ แต่ว่าถ้าใช้แบบนั้น เราจะไม่สามารถเรียก recursive function ได้เพราะไม่สามารถอ้างอิงชื่อฟังก์ชันได้แบบที่ letfn ทำได้นั่นเอง</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/5439731388367885884/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/5439731388367885884' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/5439731388367885884'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/5439731388367885884'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/05/clojure-letfn.html' title='Clojure letfn'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF0K__MGyBsNRdHvEu1miMW8rLRJa_9D6_m1zazSOOIJdVj9vvpTKRFGaTRK8AyBzD1Red9ikDVRezfIn6Wt_D6QUhm_QamsySn-LrXNbwJmdZ0EtFHt39WlZUlJlK64HjcXjd/s72-c/250px-Clojure-Logo.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-7652282260123503269</id><published>2015-05-27T06:23:00.002+07:00</published><updated>2015-05-27T20:40:12.334+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional programming"/><category scheme="http://www.blogger.com/atom/ns#" term="Referential transparency"/><title type='text'>Referential transparency</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQILTP-OUbgHy9YeQNi1SExSt_ey0HTi8jF6kPqyy_FO2QaULn8new14ja-SoOm-tQoWgyR11FK1viJOxPZo2-p-_-2beVzx4sUsQWouqJwuCm75DQuLmgCHUG3t6YaGqhj3GK/s1600/Screen+Shot+2557-10-20+at+10.06.57+PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;200&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQILTP-OUbgHy9YeQNi1SExSt_ey0HTi8jF6kPqyy_FO2QaULn8new14ja-SoOm-tQoWgyR11FK1viJOxPZo2-p-_-2beVzx4sUsQWouqJwuCm75DQuLmgCHUG3t6YaGqhj3GK/s200/Screen+Shot+2557-10-20+at+10.06.57+PM.png&quot; width=&quot;142&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
ในโลกของการเขียนโปรแกรมแบบ Functional Programming มีคุณสมบัตินึงที่เราจะเห็นกันบ่อยๆนั่นก็คือ Referential transparency หมายถึง&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
การเรียก function ด้วย arguments แบบเดิม จะได้ค่ากลับมาเป็นค่าเดิมเสมอ&lt;/blockquote&gt;
function ที่มีคุณสมบัตินี้ จะทำให้การทำงานของโปรแกรมทดสอบได้ง่าย และ ยังสามารถใช้เทคนิคในการจำผลลัพธ์ของการเรียกใช้งานด้วย arguments ก่อนเอาไว้ได้อีกด้วย&lt;br /&gt;
&lt;br /&gt;
ตัวอย่าง function ที่มีคุณสมบัติ Referentially transparent ยกตัวอย่างด้วย Clojure&lt;br /&gt;
&lt;br /&gt;
(defn add2&lt;br /&gt;
&amp;nbsp; [x]&lt;br /&gt;
&amp;nbsp; (+ x 2))&lt;br /&gt;
&lt;br /&gt;
จะเห็นว่า function นี้ใส่ค่าจำนวนเต็มอะไรไปจะได้ผลลัพธ์เป็นค่านั้นบวกกับ 2 เสมอ&lt;br /&gt;
&lt;br /&gt;
ตัวอย่าง function ที่ไม่เป็น Referentially transparent เช่นฟังก์ชันที่ยุ่งเกี่ยวกับ Input/Output หรือฟังก์ชันที่ยุ่งเกี่ยวกับ เวลา และ การ random เช่น&lt;br /&gt;
&lt;br /&gt;
(defn now [] (java.util.Date.))&lt;br /&gt;
&lt;br /&gt;
(defn gen-number [] (rand))&lt;br /&gt;
&lt;br /&gt;
(println &quot;Hello World&quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
สุดท้าย ไม่ว่าคุณจะลองเขียนโปรแกรมในลักษณะ Functional Programming หรือไม่ ก็ขอให้เราเขียนโค้ดแยกระหว่างส่วนที่เป็น Referential transparency ออกจากส่วนที่ไม่เป็น เพื่อเราจะได้ทดสอบได้ง่ายๆ โดยเฉพาะส่วนที่เป็น Business Logic ต่างๆสามารถแยกออกมา เวลาเขียน Unit test ก็จะทำให้ง่ายขึ้นมาก</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/7652282260123503269/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/7652282260123503269' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7652282260123503269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/7652282260123503269'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/05/referential-transparency.html' title='Referential transparency'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQILTP-OUbgHy9YeQNi1SExSt_ey0HTi8jF6kPqyy_FO2QaULn8new14ja-SoOm-tQoWgyR11FK1viJOxPZo2-p-_-2beVzx4sUsQWouqJwuCm75DQuLmgCHUG3t6YaGqhj3GK/s72-c/Screen+Shot+2557-10-20+at+10.06.57+PM.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-26659265.post-6337959147604445056</id><published>2015-05-26T16:31:00.003+07:00</published><updated>2015-05-26T16:31:48.137+07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Software"/><title type='text'>แก้เชือก</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieCKHy_4xtmiZUlZFRS2VloIvtJ9bdo_5iK-ygvb5IQhvX_bou5MhyjyoPJgwEYII8UAaWhk9Z9RCdvf2QYudIbondFYVlp-xb2gO1YUSVzOsFVrlEk1OEzLmANPaFMAjOB6dz/s1600/maxresdefault.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;222&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieCKHy_4xtmiZUlZFRS2VloIvtJ9bdo_5iK-ygvb5IQhvX_bou5MhyjyoPJgwEYII8UAaWhk9Z9RCdvf2QYudIbondFYVlp-xb2gO1YUSVzOsFVrlEk1OEzLmANPaFMAjOB6dz/s400/maxresdefault.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
เวลาที่เชือกพันกัน หรือพวกหูฟังพันกัน (แค่จับใส่กระเป๋า ก็พันกันเองได้) เราแก้โดยการเลือกค่อยๆ คลายทีละปมให้ออก ถ้าปมไหนแน่นก็จะทำให้มันหลวมๆก่อน&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ในแต่ละปม จะต้องมีปลายเส้นของเชือกที่มันพันกันอยู่เสมอ ก่อนจะแก้ได้ก็ต้องหาปลายแต่ละด้านให้เจอแล้วค่อยๆไล่มาทีปมที่พันกันด้วย เพื่อเอาแต่ละด้านที่พันกันอยู่ออก&lt;br /&gt;
&lt;br /&gt;
เมื่อกลับมาที่การเขียนโปรแกรมของเรา เมื่อเจอปัญหาที่เราไม่รู้ว่าจุดที่เป็นปัญหาจริงๆอยู่ที่ไหน รู้แค่กว้างๆ เราก็ต้องพยายามลดขอบเขตของปัญหา โดยการไล่ที่ปลายด้านหนึ่งของข้อมูลที่เข้าไป เช่น มี API หนึ่งที่ทำแล้วเรียกไปที่ path แบบนี้&lt;br /&gt;
&lt;br /&gt;
POST /customer/save&lt;br /&gt;
&lt;br /&gt;
สิ่งที่เราต้องไล่หาต่อไปคือ function อะไรที่เป็น Handler ของ API path นี้ เมื่อเจอแล้วก็ไล่ไปในนั้นต่อว่า ข้อมูลที่ส่งไปกับ request เอาไปทำอะไรบ้าง จนกระทั่งเจอจุดที่ทำให้เป็นปัญหา แล้วเราก็ค่อยแยกตรงส่วนนั้น มาเขียน test เพิ่ม ในกรณีที่ test ที่เคยเขียนไปแล้วไม่ครอบคลุมปัญหาที่เกิดขึ้น&lt;br /&gt;
&lt;br /&gt;
นี่เป็น pattern ในการไล่โค้ดของผมครับ เพื่อท่านใดเจอปัญหาแบบเดียวกันได้ลองเอาวิธีนี้ไปใช้ดู</content><link rel='replies' type='application/atom+xml' href='http://iporsut.blogspot.com/feeds/6337959147604445056/comments/default' title='ส่งความคิดเห็น'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/26659265/6337959147604445056' title='0 ความคิดเห็น'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/6337959147604445056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26659265/posts/default/6337959147604445056'/><link rel='alternate' type='text/html' href='http://iporsut.blogspot.com/2015/05/blog-post_26.html' title='แก้เชือก'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06806442027905887893</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieCKHy_4xtmiZUlZFRS2VloIvtJ9bdo_5iK-ygvb5IQhvX_bou5MhyjyoPJgwEYII8UAaWhk9Z9RCdvf2QYudIbondFYVlp-xb2gO1YUSVzOsFVrlEk1OEzLmANPaFMAjOB6dz/s72-c/maxresdefault.jpg" height="72" width="72"/><thr:total>0</thr:total></entry></feed>