<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Denis Papathanasiou</title>
	<atom:link href="http://denis.papathanasiou.org/feed/?amp;p=948" rel="self" type="application/rss+xml" />
	<link>http://denis.papathanasiou.org</link>
	<description>All the Pieces Matter</description>
	<lastBuildDate>Thu, 16 May 2013 18:03:13 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>The Flip-Book from &#8220;Sadaharu Oh: A Zen Way of Baseball&#8221;</title>
		<link>http://denis.papathanasiou.org/2013/05/16/the-flip-book-from-sadaharu-oh-a-zen-way-of-baseball/</link>
		<comments>http://denis.papathanasiou.org/2013/05/16/the-flip-book-from-sadaharu-oh-a-zen-way-of-baseball/#comments</comments>
		<pubDate>Thu, 16 May 2013 18:02:08 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Aikido]]></category>
		<category><![CDATA[Japan]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1235</guid>
		<description><![CDATA[I found out about the book Sadaharu Oh: A Zen Way of Baseball from Eric Neel&#8217;s old column for ESPN Page 2. More than just a simple biography of Oh, it delves into the philosophy of hitting as a process, with detours in Zen and Aikido along the way. But what really got my attention [...]]]></description>
				<content:encoded><![CDATA[<p>I found out about the book <a href="http://www.worldcat.org/title/sadaharu-oh-a-zen-way-of-baseball/oclc/10298900" target="_blank">Sadaharu Oh: A Zen Way of Baseball</a> from <a href="http://espn.go.com/page2/s/neel/020814.html" target="_blank">Eric Neel&#8217;s old column</a> for ESPN Page 2.</p>
<p>More than just a <a href="http://en.wikipedia.org/wiki/Sadaharu_Oh" target="_blank">simple biography of Oh</a>, it delves into the philosophy of hitting as a process, with detours in <a href="http://en.wikipedia.org/wiki/Zen" target="_blank">Zen</a> and <a href="http://en.wikipedia.org/wiki/Aikido" target="_blank">Aikido</a> along the way.</p>
<p>But what really got my attention was this bonus feature Neel mentioned:</p>
<blockquote><p><img src="http://i.imgur.com/naL0X.png" border="0" alt="quote" align="left" style="padding-right: 4px;" />A flip-book sequence of his up-on-one-leg hitting style right in the middle of the book. (This alone is worth the cost of the book.)</p></blockquote>
<p><a href="http://www.youtube.com/watch?v=JHOJ0wRZnQo" target="_blank">This video</a> was created from still image snapshots found in the upper right corner of all the odd-numbered pages between pp. 135-169.</p>
<p><iframe width="600" height="420" src="http://www.youtube.com/embed/JHOJ0wRZnQo?rel=0" frameborder="0" allowfullscreen></iframe></p>
<p>They were meant to be flipped to create a primitive animation of Oh&#8217;s famous flamingo batting stance, but since the book is out of print, I took snapshots of those pages manually, and compiled the stills into video using <a href="http://jupiter.ethz.ch/~pjt/makingMovies.html" target="_blank">this technique</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2013/05/16/the-flip-book-from-sadaharu-oh-a-zen-way-of-baseball/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a custom case for a handmade TV-B-Gone</title>
		<link>http://denis.papathanasiou.org/2013/04/27/building-a-custom-case-for-a-handmade-tv-b-gone/</link>
		<comments>http://denis.papathanasiou.org/2013/04/27/building-a-custom-case-for-a-handmade-tv-b-gone/#comments</comments>
		<pubDate>Sat, 27 Apr 2013 15:57:38 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Case-mod]]></category>
		<category><![CDATA[HOW-TO]]></category>
		<category><![CDATA[MakerBar]]></category>
		<category><![CDATA[TV-B-Gone]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1216</guid>
		<description><![CDATA[I had a chance to visit MakerBar the other night, and tried building my own TV-B-Gone, using MakerBar&#8217;s own upgraded design. It was the first time I&#8217;d soldered anything for a real project, and until I&#8217;d completed and tested it, I wasn&#8217;t sure if it would actually work. But it did, and a big part [...]]]></description>
				<content:encoded><![CDATA[<p>I had a chance to visit <a href="http://blog.makerbar.com/" target="_blank">MakerBar</a> the other night, and tried building my own <a href="https://en.wikipedia.org/wiki/TV-B-Gone" target="_blank">TV-B-Gone</a>, using MakerBar&#8217;s own <a href="http://blog.makerbar.com/?p=411" target="_blank">upgraded design</a>.</p>
<p>It was the first time I&#8217;d soldered anything for a real project, and until I&#8217;d completed and tested it, I wasn&#8217;t sure if it would actually work.</p>
<p>But it did, and a big part of the reason why is that <a href="http://zackfreedman.com/" target="_blank">Zack Freedman</a>, the designer of MakerBar&#8217;s upgraded circuit, not only took the time to write a <a href="http://blog.makerbar.com/?page_id=624" target="_blank">detailed set of instructions</a> but also waited patiently with us as we went through the process, and provided help as we needed.</p>
<p><a href="http://i.imgur.com/hv9Cono.jpg"><img src="http://i.imgur.com/hv9Cono.jpg" width="600" border="0" alt="My own functional TV-B-Gone, which I built myself" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">My own functional TV-B-Gone, which I built myself</div>
<p>Since the double-sided tape which was meant to mount the board on top of the battery case didn&#8217;t quite work, and I also didn&#8217;t like how the board was exposed, I went looking for a case I could use.</p>
<p><a href="http://i.imgur.com/LWgsIGB.jpg"><img src="http://i.imgur.com/LWgsIGB.jpg" width="600" border="0" alt="Hello, green tea mints" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">Hello, green tea mints</div>
<p><a href="http://i.imgur.com/Xlc0SOC.jpg"><img src="http://i.imgur.com/Xlc0SOC.jpg" width="600" border="0" alt="" /></a></p>
<p>A empty box of mints was the perfect size, and it was easy to take apart. I needed some filler material, so I used the styrofoam container from one of my computers.</p>
<p><a href="http://i.imgur.com/vg7JKKk.jpg"><img src="http://i.imgur.com/vg7JKKk.jpg" width="600" border="0" alt="" /></a></p>
<p><a href="http://i.imgur.com/FlHnwTS.jpg"><img src="http://i.imgur.com/FlHnwTS.jpg" width="600" border="0" alt="" /></a></p>
<p><a href="http://i.imgur.com/mLJcJqO.jpg"><img src="http://i.imgur.com/mLJcJqO.jpg" width="600" border="0" alt="Almost a perfect fit" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">Almost a perfect fit</div>
<p>I wanted to be able to continue to use the styrofoam for my computer, though, so to preserve the structural integrity of the container, I planned two cuts, roughly a third of the width of the middle element.</p>
<p><a href="http://i.imgur.com/h5aaXpA.jpg"><img src="http://i.imgur.com/h5aaXpA.jpg" width="600" border="0" alt="Planning to cut out the bottom right and upper left rectangles" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">Planning to cut out the bottom right and upper left rectangles</div>
<p><a href="http://i.imgur.com/pNygixg.jpg"><img src="http://i.imgur.com/pNygixg.jpg" width="600" border="0" alt="One cut-out done" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">One cut-out done</div>
<p>Just as I was about to cut out the second piece, I remembered the concept of &quot;<a href="http://lssacademy.com/2008/03/27/10-benefits-of-one-piece-flow/" target="_blank">single-piece flow</a>&quot; from <a href="http://www.amazon.com/gp/product/0307887898/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&#038;camp=1789&#038;creative=9325&#038;creativeASIN=0307887898&#038;linkCode=as2&#038;tag=denispapath-20" target="_blank">The Lean Startup</a>, and I stopped to check my first cut-out in the mint box.</p>
<p><a href="http://i.imgur.com/lmcpJTX.jpg"><img src="http://i.imgur.com/lmcpJTX.jpg" width="600" border="0" alt="One is enough!" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">One is enough!</div>
<p>It turned out that was all I needed, so not only did I not waste time cutting the second piece, but also I was able to keep the styrofoam more intact than if I&#8217;d cut the second piece.</p>
<p><a href="http://i.imgur.com/IYGxUM1.jpg"><img src="http://i.imgur.com/IYGxUM1.jpg" width="600" border="0" alt="The circuit board on top, battery case below" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">The circuit board on top, battery case below</div>
<p><a href="http://i.imgur.com/pZbFoSm.jpg"><img src="http://i.imgur.com/pZbFoSm.jpg" width="600" border="0" alt="A sectional view" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">A sectional view</div>
<p>I still needed something to stick the board to the styrofoam, and so I tried some <a href="http://www.amazon.com/gp/product/B00004Z4A7/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&#038;camp=1789&#038;creative=9325&#038;creativeASIN=B00004Z4A7&#038;linkCode=as2&#038;tag=denispapath-20" target="_blank">mounting squares</a> I had left over from another project.</p>
<p><a href="http://i.imgur.com/5h1bI1E.jpg"><img src="http://i.imgur.com/5h1bI1E.jpg" width="600" border="0" alt="" /></a></p>
<p>Next, came the hardest part: cutting holes in the lid to accomodate the LEDs and circuit components.</p>
<p><a href="http://i.imgur.com/Ku2sjGw.jpg"><img src="http://i.imgur.com/Ku2sjGw.jpg" width="600" border="0" alt="I planned on cutting off this rectangle entirely, but making the two slits was hard enough, so I stopped there" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">I planned on cutting off this rectangle entirely, but making the two slits was hard enough, so I stopped there</div>
<p><a href="http://i.imgur.com/4pe6wsO.jpg"><img src="http://i.imgur.com/4pe6wsO.jpg" width="600" border="0" alt="Cut-outs for the top of the lid" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">Cut-outs for the top of the lid</div>
<p><a href="http://i.imgur.com/fTpUoLi.jpg"><img src="http://i.imgur.com/fTpUoLi.jpg" width="600" border="0" alt="Close enough" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">Close enough</div>
<p>Cutting the top of the lid, which was mostly clear plastic instead of metal, was much easier, and eventually I was able to fit the whole thing together.</p>
<p><a href="http://i.imgur.com/lXJJIWA.jpg"><img src="http://i.imgur.com/lXJJIWA.jpg" width="600" border="0" alt="Closing the lid, with a little gentle persuasion from a pair of pliers" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">Closing the lid, with a little gentle persuasion from a pair of pliers</div>
<p>I finished it by applying electrical tape around the edge, to make sure the lid would stay closed.</p>
<p><a href="http://i.imgur.com/B1wbKEw.jpg"><img src="http://i.imgur.com/B1wbKEw.jpg" width="600" border="0" alt="The completed case mod, nice and snug" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">The completed case mod, nice and snug</div>
<p>It came out quite nicely, and having the battery case underneath, gives the whole thing a nice sense of heft and control.</p>
<p><a href="http://i.imgur.com/gxKddW3.jpg"><img src="http://i.imgur.com/gxKddW3.jpg" width="600" border="0" alt="A live action shot" /></a></p>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">A live action shot</div>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2013/04/27/building-a-custom-case-for-a-handmade-tv-b-gone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu Server + Fluxbox on Mac OSX using VirtualBox</title>
		<link>http://denis.papathanasiou.org/2013/03/31/ubuntu-server-fluxbox-on-mac-osx-using-virtualbox/</link>
		<comments>http://denis.papathanasiou.org/2013/03/31/ubuntu-server-fluxbox-on-mac-osx-using-virtualbox/#comments</comments>
		<pubDate>Sun, 31 Mar 2013 16:06:22 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Dual Boot]]></category>
		<category><![CDATA[Dual Boot Alternative]]></category>
		<category><![CDATA[Fluxbox]]></category>
		<category><![CDATA[HOW-TO]]></category>
		<category><![CDATA[Mac Mini]]></category>
		<category><![CDATA[Mac OSX]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[VirtualBox]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1205</guid>
		<description><![CDATA[I like Mac OSX as a general computing environment, but I prefer Debian (and more recently Ubuntu) for development. Instead of running my Mac in dual-boot mode, I tried using VirtualBox to run Ubuntu Desktop. Unfortunately, the virtual image was unusable: even at two gigabytes of memory (the most allowed by the vm) it was [...]]]></description>
				<content:encoded><![CDATA[<p>I like <a href="https://www.apple.com/osx" target="_blank">Mac OSX</a> as a general computing environment, but I prefer <a href="http://www.debian.org/" target="_blank">Debian</a> (and more recently <a href="http://www.ubuntu.com/" target="_blank">Ubuntu</a>) for development.</p>
<p>Instead of running my Mac in <a href="http://denis.papathanasiou.org/?p=3" target="_blank">dual-boot mode</a>, I tried using <a href="https://www.virtualbox.org/" target="_blank">VirtualBox</a> to run <a href="http://www.ubuntu.com/download/desktop" target="_blank">Ubuntu Desktop</a>.</p>
<p>Unfortunately, the virtual image was unusable: even at two gigabytes of memory (the most allowed by the vm) it was painfully slow, and using the <a href="http://www.muktware.com/3957/ubuntu-beginners-dash" target="_blank">dash</a> was basically impossible.</p>
<p>But since my development environment consists mostly of <a href="http://roxterm.sourceforge.net/" target="_blank">ROXTerm</a> and <a href="https://www.gnu.org/software/emacs" target="_blank">emacs</a>, I wanted to see how <a href="http://www.ubuntu.com/download/server" target="_blank">Ubuntu Server</a> plus a <a href="https://help.ubuntu.com/community/Installation/LowMemorySystems" target="_blank">lightweight window manager</a> such as <a href="http://www.fluxbox.org/" target="_blank">Fluxbox</a> would work instead.</p>
<p><a href="http://i.imgur.com/vRsx9EH.png"><img alt="Fluxbox running like a champ on Ubuntu Server in VirtualBox" src="http://i.imgur.com/vRsx9EH.png" width="600" height="484" /></a>
<div style="text-align:center;font-size:0.8em;font-style:italic;margin-top:-1em">Fluxbox running like a champ on Ubuntu Server in VirtualBox</div>
<p>It&#8217;s been terrific so far, and the setup was simple:</p>
<ol>
<li>After downloading the Ubuntu Server iso file, I <a href="https://www.virtualbox.org/manual/ch01.html#gui-createvm" target="_blank">created a new virtual image</a> and used the iso as the base media</li>
<li>Once installed, I <a href="https://help.ubuntu.com/community/Installation/LowMemorySystems#Install_an_entire_lightweight_system" target="_blank">followed the instructions</a> for setting up Fluxbox without a login manager:
<pre>sudo apt-get install xorg fluxbox fluxconf</pre>
</li>
<li>Then, I started Fluxbox for the first time:
<pre>startx</pre>
</li>
<li>For the <a href="https://www.virtualbox.org/manual/ch04.html" target="_blank">Guest Additions</a> installation, I installed these packages first:
<pre>apt-get install dkms build-essential linux-headers-generic</pre>
<p>And then requested the guest additions from the VirtualBox menu: <b>Devices</b> -&gt; <b>Install Guest Additions</b> which &#8220;loads&#8221; the guest additions virtual disk. Under gnome or kde the disk gets mounted automatically, but in Fluxbox I had to mount it myself before running the install script:</p>
<pre>sudo mount /dev/dvd /media/cdrom
cd /media/cdrom
sudo sh ./VBoxLinuxAdditions.run</pre>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2013/03/31/ubuntu-server-fluxbox-on-mac-osx-using-virtualbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using webcams in ubuntu: fixing the audio</title>
		<link>http://denis.papathanasiou.org/2013/03/25/using-webcams-in-ubuntu-fixing-the-audio/</link>
		<comments>http://denis.papathanasiou.org/2013/03/25/using-webcams-in-ubuntu-fixing-the-audio/#comments</comments>
		<pubDate>Mon, 25 Mar 2013 15:44:56 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[alsa]]></category>
		<category><![CDATA[avconv]]></category>
		<category><![CDATA[HOW-TO]]></category>
		<category><![CDATA[oss]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[webcam]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1198</guid>
		<description><![CDATA[I recently tried using my laptop&#8217;s webcam to record video for the first time, but ran into a problem with the audio. The ubuntu community help page says: With recent versions of Ubuntu (>= 12.10) you should use avconv instead of ffmpeg command: avconv -f oss -i /dev/dsp -f video4linux2 -s 320x240 -i /dev/video0 out.mpg [...]]]></description>
				<content:encoded><![CDATA[<p>I recently tried using my laptop&#8217;s webcam to record video for the first time, but ran into a problem with the audio.</p>
<p>The <a href="https://help.ubuntu.com/community/Webcam" target="_blank">ubuntu community help page</a> says: </p>
<blockquote><p>With recent versions of Ubuntu (>= 12.10) you should use avconv instead of ffmpeg command:</p>
<pre>
avconv -f oss -i /dev/dsp -f video4linux2 -s 320x240 -i /dev/video0 out.mpg</pre>
</blockquote>
<p>Unfortunately, that gave me this error:</p>
<pre>
[oss @ 0xd5dbc0] /dev/dsp: No such file or directory
/dev/dsp: Input/output error
</pre>
<p>It turns out that <a href="http://askubuntu.com/a/79755" target="_blank">the /dev/dsp device is part of the obsolete OSS sound API, which has since been replaced by the ALSA API</a>. </p>
<p>In fact, <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/579300" target="_blank">the OSS API was removed from the ubuntu kernel in 2010</a>, so it&#8217;s surprising to see such outdated advice on the ubuntu help page.</p>
<p>Buried deep in the <a href="http://manpages.ubuntu.com/manpages/precise/man1/avconv.1.html" target="_blank">avconv manpage</a> are notes about how to use alsa.</p>
<p>First, I had to find the recognized cards and devices, which I got by using these two commands respectively:</p>
<pre>
$ cat /proc/asound/cards
$ cat /proc/asound/devices
</pre>
<p>In my case the &#8220;CARD,DEV,SUBDEV&#8221; values which follow the &#8220;hw:&#8221; prefix were &#8220;0,0,0&#8243; and so the avconv command which did work was:</p>
<pre>
avconv -f alsa -i hw:0,0,0 -f video4linux2 -s 320x240 -i /dev/video0 out.mpg
</pre>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2013/03/25/using-webcams-in-ubuntu-fixing-the-audio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>State machines in Go (#golang)</title>
		<link>http://denis.papathanasiou.org/2013/02/10/state-machines-in-go-golang/</link>
		<comments>http://denis.papathanasiou.org/2013/02/10/state-machines-in-go-golang/#comments</comments>
		<pubDate>Sun, 10 Feb 2013 15:47:58 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[State Machine]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1190</guid>
		<description><![CDATA[I&#8217;ve been rewriting critical server components that were originally written in Python to use Go instead. Unlike Python, which is interpreted and uses a global lock because the interpreter is not thread-safe, Go has built-in support for concurrency, and is statically compiled. One of the first things I tackled was implementing a state machine. The [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been rewriting critical server components that were originally written in <a href="http://python.org/" target="_blank">Python</a> to use <a href="http://golang.org/" target="_blank">Go</a> instead. Unlike Python, which is interpreted and uses a <a href="http://docs.python.org/release/2.5.2/api/threads.html" target="_blank">global lock because the interpreter is not thread-safe</a>, Go has built-in support for concurrency, and is statically compiled.</p>
<p>One of the first things I tackled was implementing a <a href="http://en.wikipedia.org/wiki/State_machine" target="_blank">state machine</a>. The <a href="http://denis.papathanasiou.org/?p=747" target="_blank">Python version</a> was based on <a href="http://www.ibm.com/developerworks/library/l-python-state/index.html" target="_blank">this article by David Mertz</a>.</p>
<p>Mertz uses an object oriented approach, defining a class with both data and methods. His code, syntax aside, will be familiar to anyone who has worked with objects in C++, C#, and Java.</p>
<p>Go, however, does not provide a mechanism for coupling methods to specific data structures. Instead, Go allows you to <a href="http://golangtutorials.blogspot.com/2011/06/structs-in-go-instead-of-classes-in.html" target="_blank">associate methods with data structures</a>, so that any method can be applied to any struct.</p>
<p>It&#8217;s a model which is closer to <a href="http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en" target="_blank">what Alan Kay meant</a> when he defined the term object oriented in the first place.</p>
<p>With that in mind, here&#8217;s how I originally wrote the state machine class as a Go struct:</p>
<pre>type Machine struct {
    Handlers   map[string]func(interface{}) (string, interface{})
    StartState string
    EndStates  map[string]bool
}</pre>
<p>Just as in Mertz&#8217;s definition, Handlers is a map whose keys are name strings, and whose values are functions which accept a &#8220;cargo&#8221; value, and return a next state name string, along with the updated cargo value.</p>
<p>Go treats functions as first-class objects, so storing and passing them from state to state works exactly as it does in Python.</p>
<p>The only change I made was in the end state list: whereas Mertz used a list of strings, I used a map, since there&#8217;s no fast equivalent of detecting presence in a list (in Go, the only way to do it would be to iterate through the entire list of strings until or unless a match is found).</p>
<p>Since the handler function signature is a little unwieldy, I created a <a href="http://www.laktek.com/2012/02/23/learning-go-functions/" target="_blank">user-defined function type</a> for it:</p>
<pre>type Handler func(interface{}) (string, interface{})

type Machine struct {
    Handlers   map[string]Handler
    StartState string
    EndStates  map[string]bool
}</pre>
<p>All that leaves is the definition of the methods associated with the Machine struct. </p>
<p>The first two provide a way to define which handler function is associated with which name string, and which name strings constitute end states:</p>
<pre>func (machine *Machine) AddState(handlerName string, handlerFn Handler) {
    machine.Handlers[handlerName] = handlerFn
}

func (machine *Machine) AddEndState(endState string) {
    machine.EndStates[endState] = true
}</pre>
<p>It&#8217;s worth noting that since EndStates is a map (or a list, in Mertz&#8217;s original), it&#8217;s possible to have more than one state terminate processing.</p>
<p>The final method is the one which executes the state machine, by applying the appropriate handler function to the cargo value, stopping when an end state has been reached.</p>
<p>Since the set of functions are stored as first-class objects in a map, looking them up based on their names and invoking them is trivial:</p>
<pre>func (machine *Machine) Execute(cargo interface{}) {
    if handler, present := machine.Handlers[machine.StartState]; present {
        for {
            nextState, nextCargo := handler(cargo)
            _, finished := machine.EndStates[nextState]
            if finished {
                break
            } else {
                handler, present = machine.Handlers[nextState]
                cargo = nextCargo
            }
        }
    }
}</pre>
<p>The only possible fly in the ointment is Go&#8217;s strong typing, since the type of the cargo value in the handler function signature needs to be specified. </p>
<p>By using the generic interface{} as the type, however, all the handler functions need to do is invoke a <a href="http://golang.org/ref/spec#Type_assertions" target="_blank">type assertion</a> on the incoming cargo value, and they can handle any data (the <a href="https://github.com/dpapathanasiou/go-statemachine/blob/master/statemachine-test.go" target="_blank">test example</a> uses a float for the cargo, but it can be any data type, even user-defined structs). </p>
<p>The complete state machine is <a href="https://github.com/dpapathanasiou/go-statemachine" target="_blank">available as a Go package</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2013/02/10/state-machines-in-go-golang/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Simple Social Media &#8220;Share&#8221; Buttons</title>
		<link>http://denis.papathanasiou.org/2012/12/18/simple-social-media-share-buttons/</link>
		<comments>http://denis.papathanasiou.org/2012/12/18/simple-social-media-share-buttons/#comments</comments>
		<pubDate>Tue, 18 Dec 2012 17:18:43 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1182</guid>
		<description><![CDATA[I&#8217;ve recently included social media &#8220;share&#8221; buttons both here on this site, and at macaronics.com (whether or not they serve any useful purpose is another question entirely). A problem with implementing them, though, is that each site wants you to include a boatload of javascript along with the button images, and you also have to [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve recently included social media &#8220;share&#8221; buttons both here on this site, and at <a href="http://macaronics.com/" target="_blank">macaronics.com</a> (whether or not they serve any useful purpose is <a href="http://www.reddit.com/r/web_design/comments/ay5du/ask_rweb_design_are_share_this_buttons_a_waste_of/" target="_blank">another question entirely</a>).</p>
<p>A problem with implementing them, though, is that each site wants you to include a boatload of javascript along with the button images, and you also have to set the button within an iframe or other weird DOM construct foreign to your page layout.</p>
<p>Getting each of the buttons to line up in a simple row is so tricky, in fact, that a bunch of <a href="http://sharethis.com/" target="_blank">third party</a> <a href="http://www.addthis.com/" target="_blank">services</a> have cropped up to do the work for you.</p>
<p>But if you don&#8217;t care about having the current number of &#8220;likes&#8221; or &#8220;shares&#8221; displayed, there is <a href="https://gist.github.com/4329613" target="_blank">a simpler way</a>.</p>
<p>My technique is based on <a href="http://stackoverflow.com/a/9321347" target="_blank">this approach</a> by <a href="http://stackoverflow.com/users/102896/steve-wortham" target="_blank">Steve Wortham</a> and <a href="http://www.reddit.com/buttons/" target="_blank">reddit&#8217;s method</a> for using javascript within the link to identify the window.location and use that to build the share link dynamically.</p>
<p>For the button images, I used <a href="https://www.fatcow.com/free-icons" target="_blank">Fatcow&#8217;s Free Icons</a> for Facebook, Twitter, LinkedIn, and Google Plus.</p>
<p><a href="http://www.reddit.com/buttons/" target="_blank">Reddit</a> and <a href="http://pinterest.com/" target="_blank">Pinterest</a> both provide button icons (though for Pinterest I had to <a href="http://passets-ec.pinterest.com/images/about/logos/Pinterest_Favicon.png" target="_blank">download the png logo file</a> and scale it down to the same size as the others).</p>
<p>Except for reddit, none of the sites offered hosting (without involving all the extraneous javascript includes I didn&#8217;t want in the first place), so I used <a href="http://www.imgur.com/" target="_blank">Imgur</a>.</p>
<p>You can see the results here:</p>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2012/12/18/simple-social-media-share-buttons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A practical guide to selling ebooks online</title>
		<link>http://denis.papathanasiou.org/2012/12/02/a-practical-guide-to-selling-ebooks-online/</link>
		<comments>http://denis.papathanasiou.org/2012/12/02/a-practical-guide-to-selling-ebooks-online/#comments</comments>
		<pubDate>Sun, 02 Dec 2012 17:55:26 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[ebooks]]></category>
		<category><![CDATA[selling online]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1151</guid>
		<description><![CDATA[&#34;What&#8217;s Next?&#34; Since this is a question I get a lot from users at eBookBurn.com and the stock FAQ answer usually leads to even more questions, I thought I&#8217;d summarize the details here. This guide assumes you do not have a literary agent or publisher and are embarking on a self publishing journey. It also [...]]]></description>
				<content:encoded><![CDATA[<h2>&quot;What&#8217;s Next?&quot;</h2>
<p>Since this is a question I get a lot from users at <a href="https://ebookburn.com/" target="_blank">eBookBurn.com</a> and the <a href="https://ebookburn.com/faq.html#sales" target="_blank">stock FAQ answer</a> usually leads to even more questions, I thought I&#8217;d summarize the details here.</p>
<p>This guide assumes you do not have a literary agent or publisher and are embarking on a <a href="http://en.wikipedia.org/wiki/Self_publishing" target="_blank">self publishing</a> journey.</p>
<div style="text-align:center">
<a target="_blank" href="http://i.imgur.com/WpTag.jpg" title="All the wedges except the blue one are too big"><img src="http://i.imgur.com/WpTag.jpg" width="320" alt="" /></a>
</div>
<p>It also describes the steps I went through in posting my own ebook, &quot;<a target="_blank" href="http://www.amazon.com/gp/search/ref=as_li_qf_sp_sr_tl?ie=UTF8&#038;camp=1789&#038;creative=9325&#038;index=aps&#038;keywords=B00A6CY5JE&#038;linkCode=ur2&#038;tag=denispapath-20" title="Buy from Amazon.com">Hurricane Sandy: The Diet</a><img src="https://www.assoc-amazon.com/e/ir?t=denispapath-20&#038;l=ur2&#038;o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />&quot; for sale (and of course, I would be remiss not to mention that it&#8217;s also available on <a target="_blank" href="https://itunes.apple.com/us/book/hurricane-sandy-the-diet/id579401894?ls=1" title="Buy from the AppStore">iTunes</a> and <a target="_blank" href="http://www.barnesandnoble.com/w/hurricane-sandy-denis-papathanasiou/1113787886" title="Buy from BN.com">Barnes &amp; Noble</a> as well).</p>
<h2>What you&#8217;ll need</h2>
<ul>
<li> A <a href="http://validator.idpf.org/" target="_blank">specification-valid</a> <a href="http://idpf.org/epub" target="_blank">epub file</a> (there are many different ways to create one, though I&#8217;m naturally biased towards <a href="https://ebookburn.com/" target="_blank">eBookBurn.com</a>)
</li>
<li> A cover image in <a href="http://en.wikipedia.org/wiki/JPEG" target="_blank">jpeg format</a>, ideally in a <a href="http://en.wikipedia.org/wiki/Golden_ratio" target="_blank">1.6 ratio between the height versus the width</a> (<a href="http://keithdraws.wordpress.com/2012/09/02/composition-using-the-golden-ratio-on-your-cover/" target="_blank">this post</a> discusses using the golden ratio in book cover design in more depth)
</li>
<li> A brief description of your book
</li>
<li> One or more <a href="http://www.loc.gov/catdir/cpso/lcco/" target="_blank">book classification categories</a> which best defines your book
</li>
<li> Tax information: your <a href="http://www.ssa.gov/" target="_blank">Social Security Number</a> or <a href="http://www.irs.gov/Businesses/Small-Businesses-&#038;-Self-Employed/Employer-ID-Numbers-(EINs)" target="_blank">Employer Identification Number (EIN)</a> if you&#8217;re selling as a company
</li>
<li> Bank information:
<ul>
<li> Your account number
</li>
<li> Your bank&#8217;s <a href="https://www.lyonsreg.com/freetrial/freetrialform.asp" target="_blank">routing number</a>
</li>
<li> Your bank name or branch name
</li>
</ul>
</li>
<li> Optionally, an <a href="http://en.wikipedia.org/wiki/ISBN" target="_blank">International Standard Book Number (ISBN)</a><sup>1</sup>
</li>
<li> Patience
</li>
</ul>
<h2>Amazon</h2>
<p><a href="http://kdp.amazon.com/" target="_blank">Amazon Kindle Direct Publishing (KDP)</a> is by far the largest marketplace and exercises the least editorial interference.</p>
<p>That&#8217;s both good and bad.</p>
<p>On the plus side you can write about almost anything, and it has the potential to reach hundreds of thousands or more readers (Amazon has never disclosed how many Kindles it has sold).</p>
<p>On the other hand, there is a ton of literary flotsam and jetsam that normally would never have seen the light of day otherwise, and your book will be competing for attention in that mix.</p>
<div style="text-align:center">
<a target="_blank" href="http://i.imgur.com/33Jmk.jpg" title="Mainstream publishers and agents do spend some time looking for the occasional pony, though"><br />
<img src="http://i.imgur.com/33Jmk.jpg" width="320" alt="" /></a>
</div>
<p>The KDP &#8220;Add Book&#8221; form is simple, and getting a book listed for sale is fairly quick, usually within a day or so.</p>
<p>While at Amazon, go ahead and <a href="https://affiliate-program.amazon.com/" target="_blank">create an affiliate account</a> so that you can take an additional share of the sale if a buyer gets it by following a link from your web site, blog, twitter feed, etc.</p>
<p>If you&#8217;re unfamiliar with how affiliate programs work, read the <a href="https://affiliate-program.amazon.com/gp/associates/help/main.html" target="_blank">help on Amazon&#8217;s site</a> or this <a href="http://en.wikipedia.org/wiki/Affiliate_programs" target="_blank">more general article at Wikipedia</a>.</p>
<h2>Apple</h2>
<p>Apple&#8217;s <a href="http://itunes.com/sellyourbooks" target="_blank">iBookstore</a>, which is part of iTunes, makes your book available to iPad and iPhone users, as well as people using Mac desktop or laptop computers.</p>
<p>Apple has some prerequisites of its own:</p>
<ul>
<li> Get an <a href="https://appleid.apple.com/cgi-bin/WebObjects/MyAppleId.woa/" target="_blank">Apple ID</a> if you don&#8217;t already have one
</li>
<li> Download iTunes Producer (as of this writing, the latest version <a href="https://itunesconnect.apple.com/itunesproducer/iTunesProducer_2.8.dmg" target="_blank">is here</a>)
</li>
</ul>
<p>Unlike the other sites which let you upload your epub file from any web browser, you must use iTunes Producer to deliver your book to the iBookstore, and since there are no versions for Windows or Linux, you must have access to a Mac OSX computer.</p>
<p>Apple is notoriously slow and capricious in its review process, and has been known to reject books for no good reason.<sup>2</sup> </p>
<div style="text-align:center">
<a target="_blank" href="http://i.imgur.com/TBs4F.jpg" title="What would Steve Jobs do?"><br />
<img src="http://i.imgur.com/TBs4F.jpg" width="200" alt="" /></a>
</div>
<p>One the plus side, the content in the iBookstore tends to be of better quality, and you can charge more for it.</p>
<h2>Barnes &amp; Noble</h2>
<p><a href="http://pubit.barnesandnoble.com/" target="_blank">PubIt</a> is Barnes &amp; Nobles&#8217; answer to Amazon&#8217;s KDP.</p>
<p>It seems the smallest of the three marketplaces, though it&#8217;s difficult to be sure: like Amazon, B&amp;N has declined to say how many Nooks have been sold.</p>
<p>Functionally it is similar to KDP, and they too have an <a href="http://affiliates.barnesandnoble.com/authors/" target="_blank">affiliate program</a> (though it&#8217;s invite only, and it&#8217;s not clear if it&#8217;s worth the trouble at this point).</p>
<p>They are a little more complicated, though, in that immediately after creating an account they may send an email asking you to call them and verify information you provided through the web form with one of their employees.</p>
<p>That verification takes a few days, but once you are cleared, adding and editing books through its web form is easy, and changes take effect within one or two days.</p>
<h2>Other ebook marketplaces</h2>
<p>There are several of them out there, but none merit any attention. </p>
<div style="text-align:center">
<a target="_blank" href="http://i.imgur.com/oR7Lt.jpg" title="Do you know how complicated/annoying it is to load a third party ebook onto your Kindle?"><br />
<img src="http://i.imgur.com/oR7Lt.jpg" width="425" alt="" /></a>
</div>
<p>The typical iPad, Kindle or Nook user is not going to look outside the built-in store for content, and the <a href="http://www.mobileread.com/" target="_blank">few technically-savvy ebook nerds who do</a> are going to want content for free.</p>
<div style="padding:1em 0 1em 0">
<div style="width:30%">
<hr /></div>
<p><sup>1</sup> I&#8217;ve never understood the value of an ISBN: it provides no intellectual property or legal protection, and with other, free or non-profit initiatives to classify books such as the <a href="http://www.loc.gov/aba/" target="_blank">Library of Congress</a> and <a href="http://openlibrary.org/" target="_blank">Open Library</a>, there&#8217;s no good reason to spend money to get one. Fortunately, none of the three marketplaces require it (perhaps they tacitly agree with my sentiment, but are not in a position to say so out loud).</p>
<p><sup>2</sup> Apple&#8217;s over-zealous editorializing has opened them up to sarcastic protests, and <a href="http://gizmodo.com/5963291/finally-goatse-lands-in-the-app-store" target="_blank">occasionally they get stung</a>.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2012/12/02/a-practical-guide-to-selling-ebooks-online/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>After Hurricane Sandy</title>
		<link>http://denis.papathanasiou.org/2012/11/06/after-hurricane-sandy/</link>
		<comments>http://denis.papathanasiou.org/2012/11/06/after-hurricane-sandy/#comments</comments>
		<pubDate>Tue, 06 Nov 2012 20:44:27 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Random Nonsense]]></category>
		<category><![CDATA[Hoboken]]></category>
		<category><![CDATA[Hurricane Sandy]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1124</guid>
		<description><![CDATA[Here are some pictures from Hoboken last week, just after the hurricane passed, and before power had been restored. Except where noted otherwise, all photos were taken by me on October 31, 2012 and are available under the Creative Commons Attribution/Share-Alike License. Before and After, Sinatra Park Monday, October 29, 2012 (photo by alyssaarminio) Before [...]]]></description>
				<content:encoded><![CDATA[<p>Here are some pictures from <a href="http://en.wikipedia.org/wiki/Hoboken,_New_Jersey" target="_blank">Hoboken</a> last week, just after the hurricane passed, and before power had been restored.</p>
<p>Except where noted otherwise, all photos were taken by me on October 31, 2012 and are available under the <a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank">Creative Commons Attribution/Share-Alike License</a>.</p>
<h4>Before and After, Sinatra Park</h4>
<p><img src="http://i.imgur.com/no2hX.jpg" alt="" /></p>
<div style="font-size:0.8em">Monday, October 29, 2012 (photo by <a href="http://instagram.com/p/RXmYFNzM4r/" target="_blank">alyssaarminio</a>)</div>
<p><img src="http://i.imgur.com/YyBw3.jpg" alt="" /></p>
<h4>Before and After, Warrington Plaza</h4>
<p><img src="http://i.imgur.com/RSI6F.jpg" alt="" /></p>
<div style="font-size:0.8em">Monday, October 29, 2012 (photo by <a href="http://instagram.com/p/RXcmNRtveu/" target="_blank">meetingpeopleiseasy</a>)</div>
<p><img src="http://i.imgur.com/9Q6Fu.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/1R7IP.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/TZWwH.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/vPv94.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/NvZtn.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/rUoSB.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/61Jm8.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/Fgubq.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/Hckht.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/uJsq4.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/u4sTA.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/Ddedb.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/osgZy.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/bSReJ.jpg" alt="" /></p>
<p><img src="http://i.imgur.com/eQQH2.jpg" alt="" /></p>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2012/11/06/after-hurricane-sandy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to extract just the text from html page articles</title>
		<link>http://denis.papathanasiou.org/2012/10/27/how-to-extract-just-the-text-from-html-page-articles/</link>
		<comments>http://denis.papathanasiou.org/2012/10/27/how-to-extract-just-the-text-from-html-page-articles/#comments</comments>
		<pubDate>Sat, 27 Oct 2012 15:51:29 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[lxml]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[text extraction]]></category>
		<category><![CDATA[text parsing]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1119</guid>
		<description><![CDATA[One of the reasons I keep going back to Python is because of the lxml library. Not only is it terrific in terms of handling xml, it can do wonders with html of all flavors, even badly-formed and specification-invalid html data. A common task I have these days is to grab the text from an [...]]]></description>
				<content:encoded><![CDATA[<p>One of the reasons I keep going back to <a href="http://python.org/" target="_blank">Python</a> is because of the <a href="http://lxml.de/" target="_blank">lxml library</a>.</p>
<p>Not only is it terrific in terms of handling xml, <a href="http://lxml.de/lxmlhtml.html" target="_blank">it can do wonders with html of all flavors</a>, even badly-formed and specification-invalid html data.</p>
<p>A common task I have these days is to grab the text from an html page or article (e.g., in <a href="http://denis.papathanasiou.org/?p=975" target="_blank">curating content for Macaronics</a>).</p>
<p>As <a href="https://gist.github.com/3965052" target="_blank">this gist shows</a>, lxml makes this dead simple, using xpath and the <a href="http://infohost.nmt.edu/tcc/help/pubs/pylxml/web/xpath.html#xpath-example" target="_blank">&#8220;descendant-or-self::&#8221; axis selector</a>.</p>
<p>The only real work is understanding the page structure and creating the correct <a href="http://msdn.microsoft.com/en-us/library/ms256086.aspx" target="_blank">xpath expression</a> for each site (the <a href="http://stackoverflow.com/a/4240037" target="_blank">readability algorithm</a> is essentially a collection of these rules), and monitoring their changes over time so that the <a href="http://www.zvon.org/comp/r/tut-XPath_1.html" target="_blank">xpath expression can be updated</a> accordingly.</p>
<p>Another bonus is that it works with foreign language sites, too, provided the parser is passed the same encoding as defined in the target page&#8217;s <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html" target="_blank">Content-Type</a> meta tag.</p>
<p>Here&#8217;s an example of grabbing the text from a web article by <a href="http://facta.co.jp/" target="_blank">Facta</a>, a Japanese business magazine, and saving it as a text file, so I can add it to the list of articles in <a href="http://macaronics.com/" target="_blank">Macaronics</a>:</p>
<p><code>>>> import urllib, text_grabber<br />
>>> data=urllib.urlopen('http://facta.co.jp/article/201211043-print.html').read()<br />
>>> t=text_grabber.facta_print(data)<br />
>>> import codecs<br />
>>> f=codecs.open('facta-201211043-print.txt', 'w', 'utf-8'); f.write(t); f.close()</code></p>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2012/10/27/how-to-extract-just-the-text-from-html-page-articles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Go (#golang) and MongoDB using mgo</title>
		<link>http://denis.papathanasiou.org/2012/10/14/go-golang-and-mongodb-using-mgo/</link>
		<comments>http://denis.papathanasiou.org/2012/10/14/go-golang-and-mongodb-using-mgo/#comments</comments>
		<pubDate>Sun, 14 Oct 2012 17:55:43 +0000</pubDate>
		<dc:creator>Denis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[go]]></category>
		<category><![CDATA[golang]]></category>
		<category><![CDATA[mgo]]></category>
		<category><![CDATA[MongoDB]]></category>

		<guid isPermaLink="false">http://denis.papathanasiou.org/?p=1090</guid>
		<description><![CDATA[After working in node.js last year, I&#8217;ve switched to learning Go instead, and I wanted to reprise my &#34;Node.js and MongoDB: A Simple Example&#34; post in Go. Of all the Go drivers available for mongoDB, mgo is the most advanced and well-maintained. The example on the mgo main page is easy to understand: Create a [...]]]></description>
				<content:encoded><![CDATA[<p>After working in <a href="http://nodejs.org/" target="_blank">node.js</a> last year, I&#8217;ve <a href="http://blog.jgc.org/2012/05/to-boldly-go-where-node-man-has-gone.html" target="_blank">switched to learning Go</a> instead, and I wanted to reprise my <a href="http://denis.papathanasiou.org/?p=704" target="_blank">&quot;Node.js and MongoDB: A Simple Example&quot;</a> post in <a href="http://golang.org/" target="_blank">Go</a>.</p>
<p>Of all the <a href="http://www.mongodb.org/display/DOCS/Drivers" target="_blank">Go drivers</a> available for mongoDB, <a href="http://labix.org/mgo" target="_blank">mgo</a> is the most advanced and well-maintained.</p>
<p>The example on the <a href="http://labix.org/mgo" target="_blank">mgo main page</a> is easy to understand:</p>
<ol>
<li>Create a <a href="http://golang.org/ref/spec#Struct_types" target="_blank">struct</a> which matches the <a href="http://www.mongodb.org/display/DOCS/Tutorial#Tutorial-DynamicSchema%28%22SchemaFree%22%29" target="_blank">BSON documents in the database collection</a> you want to access
</li>
<li> Obtain a session using the <a href="http://go.pkgdoc.org/labix.org/v2/mgo#Dial" target-"_blank">Dial function</a>, which creates a connection object
</li>
<li>Use the connection object to access a particular collection in your database:
<ul>
<li>Searches load documents from the database into the struct
</li>
<li>Inserts and updates take data defined in a struct and create/update documents in the database
</li>
</ul>
</li>
</ol>
<p>So for a collection named &#8220;Person&#8221;, where a typical document looks like this:</p>
<pre>{
        "_id" : ObjectId("502fbbd6fec1300be858767e"),
        "lastName" : "Seba",
        "firstName" : "Jun",
        "inserted" : ISODate("2012-08-18T15:59:18.646Z")
}</pre>
<p>The corresponding Go struct would be:</p>
<pre>type Person struct {
    Id         bson.ObjectId   "_id,omitempty"
    FirstName  string          "firstName"
    MiddleName string          "middleName,omitempty"
    LastName   string          "lastName"
    Inserted   time.Time       "inserted"
}</pre>
<p>It turns out the third field in each line, the string literal tag which is normally optional in a Go struct, is <i>required</i> here, because mgo won&#8217;t find those fields in the database otherwise.</p>
<p>It&#8217;s also possible to convert database results directly into <a href="http://json.org/" target="_blank">json</a>, which is useful for creating <a href="https://github.com/dpapathanasiou/go-api" target="_blank">API services</a> that output json.</p>
<p>In that case, it&#8217;s necessary to define both a bson tag and a json one, surrounded by backticks:</p>
<pre>type Person struct {
    Id         bson.ObjectId   `bson:"_id,omitempty" json:"-"`
    FirstName  string          `bson:"firstName" json:"firstName"`
    MiddleName string          `bson:"middleName,omitempty" json:"middleName,omitempty"`
    LastName   string          `bson:"lastName" json:"lastName"`
    Inserted   time.Time       `bson:"inserted" json:"-"`
}</pre>
<p>The json tag follows the conventions of the built-in <a href="http://golang.org/pkg/encoding/json/#Marshal" target="_blank">Go json package</a>: &#8220;-&#8221; means ignore, &#8220;omitempty&#8221; will exclude the field if its value is empty, etc.</p>
<p>So far so good.</p>
<p>But accessing different collections in a database means that for each one: it has its own struct defined, it has its own connection with the collection name specified, and an access function (<a href="http://go.pkgdoc.org/labix.org/v2/mgo#Collection.Find" target="_blank">Find</a>, <a href="http://go.pkgdoc.org/labix.org/v2/mgo#Collection.Insert" target="_blank">Insert</a>, <a href="http://go.pkgdoc.org/labix.org/v2/mgo#Collection.Remove" target="_blank">Remove</a>, etc.) which marshals/unmarshals those results. </p>
<p>And the last step in particular can lead to a lot of code repetition. </p>
<p>Inspired by <a href="https://groups.google.com/group/mgo-users/msg/fe1e9f1e03096729?hl=en" target="_blank">Alexander Luya&#8217;s post</a> on <a href="https://groups.google.com/group/mgo-users?hl=en" target="_blank">mgo-users</a>, I&#8217;ve created a framework that allows for multiple access functions with a minimum of repetiton.</p>
<p>First, this function, which creates or clones the call to <a href="http://go.pkgdoc.org/labix.org/v2/mgo#Dial" target="_blank">Dial()</a> as needed (this is very similar to what Alex posted):</p>
<pre>var (
    mgoSession     *mgo.Session
    databaseName = "myDB"
)

func getSession () *mgo.Session {
    if mgoSession == nil {
        var err error
        mgoSession, err = mgo.Dial("localhost")
        if err != nil {
             panic(err) // no, not really
        }
    }
    return mgoSession.Clone()
}</pre>
<p>Next, a higher-order function which takes a collection name and an access function prepared to act on that collection:</p>
<pre>func withCollection(collection string, s func(*mgo.Collection) error) error {
    session := getSession()
    defer session.Close()
    c := session.DB(databaseName).C(collection)
    return s(c)
}</pre>
<p>The withCollection() function takes the name of the collection, along with a function that expects the connection object to that collection, and can execute access functions on it.</p>
<p>Here&#8217;s how the &#8220;Person&#8221; collection can be searched, using the withCollection() function:</p>
<pre>func SearchPerson (q interface{}, skip int, limit int) (searchResults []Person, searchErr string) {
    searchErr     = ""
    searchResults = []Person{}
    query := func(c *mgo.Collection) error {
        fn := c.Find(q).Skip(skip).Limit(limit).All(&#038;searchResults)
        if limit < 0 {
            fn = c.Find(q).Skip(skip).All(&#038;searchResults)
        }
        return fn
    }
    search := func() error {
        return withCollection("person", query)
    }
    err := search()
    if err != nil {
        searchErr = "Database Error"
    }
    return
}</pre>
<p>The skip and limit parameters are optional in that if skip is set to zero, it is effectively asking for all the results, and, similarly, if limit is set to an integer less than zero, it is ignored in the query that gets invoked inside the withCollection() function.</p>
<p>So with that framework in place, making a variety of different queries on the "Person" collection reduces to writing simple (often one-line) BSON queries, as in the following examples.</p>
<p>(1) Get all people whose last name beings with a particular string:</p>
<pre>func GetPersonByLastName (lastName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{"lastName": bson.RegEx{"^"+lastName, "i"}}, skip, limit)
    return
}</pre>
<p>(2) Get all people whose last name is exactly the given string:</p>
<pre>func GetPersonByExactLastName (lastName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{"lastName": lastName}, skip, limit)
    return
}</pre>
<p>(3) Find people whose first and last names being with the particular strings:</p>
<pre>func GetPersonByFullName (lastName string, firstName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{
        "lastName": bson.RegEx{"^"+lastName, "i"},
        "firstName": bson.RegEx{"^"+firstName, "i"}}, skip, limit)
    return
}</pre>
<p>(4) Find people whose first and last names match with first and last names exactly:</p>
<pre>func GetPersonByExactFullName (lastName string, firstName string, skip int, limit int) (searchResults []Person, searchErr string) {
    searchResults, searchErr = SearchPerson(bson.M{"lastName": lastName, "firstName": firstName}, skip, limit)
    return
}</pre>
<p>et. cetera.</p>
<p>As far as code repetition goes, however, this framework is not that efficient in that each collection requires its own Search[Collection]() function, where the only difference among the different functions is the type of the searchResults variable.</p>
<p>It would be tempting to write something like this:</p>
<pre>func Search (collectionName string, q interface{}, skip int, limit int) (searchResults []interface{}, searchErr string) {
    searchErr = ""
    query := func(c *mgo.Collection) error {
        fn := c.Find(q).Skip(skip).Limit(limit).All(&#038;searchResults)
        if limit < 0 {
            fn = c.Find(q).Skip(skip).All(&#038;searchResults)
        }
        return fn
    }
    search := func() error {
        return withCollection(collectionName, query)
    }
    err := search()
    if err != nil {
        searchErr = "Database Error"
    }
    return
}</pre>
<p>Except this is where Go's strong typing gets in the way: <a href="https://groups.google.com/group/mgo-users/msg/c6226894a33e95d7?hl=en" target="_blank">&quot;there's no magic that would turn an interface{} into a Person&quot;</a>, and so each Search[Collection]() function has to be written separately.</p>
]]></content:encoded>
			<wfw:commentRss>http://denis.papathanasiou.org/2012/10/14/go-golang-and-mongodb-using-mgo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
