List of Singleton - text.Baldanders.info
tag:text.Baldanders.info,2017-10-24:/tags
2017-10-24T14:43:01+09:00
帰ってきた「しっぽのさきっちょ」
https://text.baldanders.info/images/avatar.jpg
https://text.baldanders.info/images/avatar.jpg
Go 言語における Singleton Pattern
tag:text.Baldanders.info,2017-10-24:/golang/singleton-pattern/
2017-10-24T05:43:01+00:00
2021-11-28T02:58:44+00:00
はっきり言って「Singleton なめんな!」ですよ。
Spiegel
https://baldanders.info/profile/
<p>今回は小ネタでお送りします。</p>
<p>いや,ネットでね,<a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>での Singleton 実装をこんな感じに書く人をやたら見かけるのだが</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">//Hello class
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">Hello</span> <span class="kd">struct</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">instance</span> <span class="o">*</span><span class="nx">Hello</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//GetInstance returns singleton instance
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nf">GetInstance</span><span class="p">()</span> <span class="o">*</span><span class="nx">Hello</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">instance</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">instance</span> <span class="p">=</span> <span class="o">&</span><span class="nx">Hello</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">instance</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>はっきり言って <strong>Singleton なめんな!</strong> ですよ。</p>
<p>そうそう。
プログラマで Singleton Pattern を知らない人はいないと思うけど,一応解説しておくと, Singleton Pattern というのは,あるクラスに対してプログラム全体でインスタンスがひとつだけ生成されるよう制限するプログラミング・パターンである。
たとえば,単一セッションでシリアルに通信を行う entity class なんかはインスタンスがぼこぼこできて各々勝手に処理をされると困るわけで<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, singleton インスタンスの内部で同期をとっていく必要があるわけ。</p>
<p>という説明からも分かると思うけど「<strong>スレッドセーフでない singleton 実装に存在意義はない</strong>」のである。
ちなみに結城浩さんの<a href="https://www.amazon.co.jp/exec/obidos/ASIN/B00I8AT1BS/baldandersinf-22/" title="増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編 | 結城 浩 | コンピュータ・IT | Kindleストア | Amazon">デザパタ本</a>にあるサンプルコードも以下のようになっている(こっちは Java での記述だけど<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>)。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-java" data-lang="java"><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="nn">java.util.Date</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">MySystem</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="n">MySystem</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">null</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="n">Date</span><span class="w"> </span><span class="n">date</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Date</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="nf">MySystem</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="n">Date</span><span class="w"> </span><span class="nf">getDate</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">date</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kd">static</span><span class="w"> </span><span class="kd">synchronized</span><span class="w"> </span><span class="n">MySystem</span><span class="w"> </span><span class="nf">getInstance</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">instance</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">null</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">MySystem</span><span class="p">();</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="p">}</span><span class="w">
</span></span></span></code></pre></div><p><code>static</code> で <code>synchronized</code> なのがポイントね。
つまり,実際にインスタンスを生成する処理では何らかの手段でスレッドセーフであることが保証されてないといけない<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>。
最初の <a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>のパターンが何故ダメなのかは実際に動くコードを書いてみれば分かる。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"time"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//Hello class
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">Hello</span> <span class="kd">struct</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span><span class="nx">Hello</span><span class="p">)</span> <span class="nf">String</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s">"Hello"</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">instance</span> <span class="o">*</span><span class="nx">Hello</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//GetInstance returns singleton instance
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nf">GetInstance</span><span class="p">()</span> <span class="o">*</span><span class="nx">Hello</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nx">instance</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"new instance"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="nx">time</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="mi">1</span> <span class="o">*</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span> <span class="c1">//delay 1sec
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">instance</span> <span class="p">=</span> <span class="o">&</span><span class="nx">Hello</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl"> <span class="p">}</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">instance</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kd">interface</span><span class="p">{})</span>
</span></span><span class="line"><span class="cl"> <span class="k">go</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="s">"Alice"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">go</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="s">"Bob"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">go</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="s">"Chris"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="o"><-</span><span class="nx">ch</span>
</span></span><span class="line"><span class="cl"> <span class="o"><-</span><span class="nx">ch</span>
</span></span><span class="line"><span class="cl"> <span class="o"><-</span><span class="nx">ch</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span> <span class="kd">chan</span><span class="o"><-</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">person</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">hello</span> <span class="o">:=</span> <span class="nf">GetInstance</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">ch</span> <span class="o"><-</span> <span class="nx">hello</span> <span class="c1">//blocking
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">hello</span><span class="p">,</span> <span class="nx">person</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>簡単に説明すると,まず <code>GetInstance()</code> 関数内部で初期化処理時間を演出するために1秒間の delay を発生させている。
<code>run()</code> 関数内で <a href="http://golang.org/ref/spec#Channel_types" title="The Go Programming Language Specification - The Go Programming Language">channel</a> <code>ch</code> にインスタンスを食わせているのはブロッキングのため。
別に何を食わせてもいいのだが,手近に <code>GetInstance()</code> 関数で取得したインスタンスがあるので,それを食わせている。
<code>main()</code> 関数では <code>run()</code> 関数を <a href="http://golang.org/ref/spec#Go_statements" title="The Go Programming Language Specification - The Go Programming Language">goroutine</a> で3連続起動したあと, <code><-ch</code> でブロックを解除している。</p>
<p><a href="https://play.golang.org/p/cL-RMmS2ev">実行結果</a>は以下の通り。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">new instance
</span></span><span class="line"><span class="cl">new instance
</span></span><span class="line"><span class="cl">new instance
</span></span><span class="line"><span class="cl">Hello Alice
</span></span><span class="line"><span class="cl">Hello Chris
</span></span><span class="line"><span class="cl">Hello Bob
</span></span></code></pre></div><p>並行処理下の3つの <code>run()</code> 関数に対してインスタンスが3つ生成されてしまっているのが分かると思う。</p>
<p>ではどう書けばいいのか。
一番簡単なのは <a href="https://go.dev/ref/spec#Variables" title="The Go Programming Language Specification - The Go Programming Language">var</a> 宣言時に初期化してしまうことである。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">instance</span> <span class="p">=</span> <span class="o">&</span><span class="nx">Hello</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//GetInstance returns singleton instance
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nf">GetInstance</span><span class="p">()</span> <span class="o">*</span><span class="nx">Hello</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">instance</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>次に簡単なのは <a href="https://golang.org/doc/effective_go.html#init" title="Effective Go - The Go Programming Language"><code>init()</code></a> 関数を使うことである。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">instance</span> <span class="o">*</span><span class="nx">Hello</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">init</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">//create instance and initialize
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">instance</span> <span class="p">=</span> <span class="o">&</span><span class="nx">Hello</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><a href="https://golang.org/doc/effective_go.html#init" title="Effective Go - The Go Programming Language"><code>init()</code></a> 関数は少し特殊な関数で,<code>main()</code> 関数がキックされる前,パッケージ内の <a href="https://go.dev/ref/spec#Variables" title="The Go Programming Language Specification - The Go Programming Language">var</a> 宣言時の初期化の後に呼ばれる。
ひとつのパッケージ内またはひとつのファイル内にいくつも <a href="https://golang.org/doc/effective_go.html#init" title="Effective Go - The Go Programming Language"><code>init()</code></a> 関数を設置できるのが特徴なのだが,どういう順番に起動するかは言語仕様として明記されていないため<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>,パッケージ内の複数の <a href="https://golang.org/doc/effective_go.html#init" title="Effective Go - The Go Programming Language"><code>init()</code></a> 関数同士が依存また干渉するような書き方は避けるべきだろう。</p>
<p><code>main()</code> 関数がキックされるまではメイン以外の <a href="http://golang.org/ref/spec#Go_statements" title="The Go Programming Language Specification - The Go Programming Language">goroutine</a> は(生成は可能だが)起動されないことが保証されているため,記述がスレッドセーフか否か気にする必要はない。
言い方を変えると,何らかの同期を伴う初期化処理の場合はこの方法では記述できないことになる。</p>
<p>「どうしても <code>GetInstance()</code> 関数内で同期をとりたいんじゃ」という場合は… たとえば <a href="https://golang.org/pkg/sync/" title="sync - The Go Programming Language"><code>sync</code></a> パッケージを使うとかだろうか。
Singleton Pattern におあつらえ向きの <a href="https://golang.org/pkg/sync/" title="sync - The Go Programming Language"><code>sync</code></a><code>.Once</code> というのがある。
最初に挙げた例を流用するならこんな感じだろうか。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">//Hello class
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">Hello</span> <span class="kd">struct</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">instance</span> <span class="o">*</span> <span class="nx">Hello</span>
</span></span><span class="line hl"><span class="cl"><span class="kd">var</span> <span class="nx">once</span> <span class="nx">sync</span><span class="p">.</span><span class="nx">Once</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//GetInstance returns singleton instance
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nf">GetInstance</span><span class="p">()</span> <span class="o">*</span> <span class="nx">Hello</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">once</span><span class="p">.</span><span class="nf">Do</span><span class="p">(</span><span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">instance</span> <span class="p">=</span> <span class="o">&</span><span class="nx">Hello</span><span class="p">{}</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">instance</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
<p>以下のコードで実際に動かして検証してみよう。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl"> <span class="s">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"sync"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"time"</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//Hello class
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">Hello</span> <span class="kd">struct</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">h</span> <span class="o">*</span> <span class="nx">Hello</span><span class="p">)</span> <span class="nf">String</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="s">"Hello"</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">var</span> <span class="nx">instance</span> <span class="o">*</span> <span class="nx">Hello</span>
</span></span><span class="line hl"><span class="cl"><span class="kd">var</span> <span class="nx">once</span> <span class="nx">sync</span><span class="p">.</span><span class="nx">Once</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">//GetInstance returns singleton instance
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">func</span> <span class="nf">GetInstance</span><span class="p">()</span> <span class="o">*</span> <span class="nx">Hello</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">once</span><span class="p">.</span><span class="nf">Do</span><span class="p">(</span><span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">"new instance"</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">time</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="mi">1</span> <span class="o">*</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span> <span class="c1">//delay 1sec
</span></span></span><span class="line hl"><span class="cl"><span class="c1"></span> <span class="nx">instance</span> <span class="p">=</span> <span class="o">&</span><span class="nx">Hello</span><span class="p">{}</span>
</span></span><span class="line hl"><span class="cl"> <span class="p">})</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="nx">instance</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kd">interface</span><span class="p">{})</span>
</span></span><span class="line"><span class="cl"> <span class="k">go</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="s">"Alice"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">go</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="s">"Bob"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">go</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="s">"Chris"</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="o"><-</span><span class="nx">ch</span>
</span></span><span class="line"><span class="cl"> <span class="o"><-</span><span class="nx">ch</span>
</span></span><span class="line"><span class="cl"> <span class="o"><-</span><span class="nx">ch</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">run</span><span class="p">(</span><span class="nx">ch</span> <span class="kd">chan</span><span class="o"><-</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">person</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">hello</span> <span class="o">:=</span> <span class="nf">GetInstance</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"> <span class="nx">ch</span> <span class="o"><-</span> <span class="nx">hello</span> <span class="c1">//blocking
</span></span></span><span class="line"><span class="cl"><span class="c1"></span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">hello</span><span class="p">,</span> <span class="nx">person</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></div>
<p><a href="https://play.golang.org/p/8ODOeffoyF">実行結果</a>は以下の通り。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">new instance
</span></span><span class="line"><span class="cl">Hello Chris
</span></span><span class="line"><span class="cl">Hello Alice
</span></span><span class="line"><span class="cl">Hello Bob
</span></span></code></pre></div><p>ちゃんと singleton として動作していることが分かる。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="http://ascii.jp/elem/000/001/235/1235262/">GASCII.jp:Goならわかるシステムプログラミング</a>
<ul>
<li><a href="http://ascii.jp/elem/000/001/480/1480872/">ASCII.jp:Go言語と並列処理(2)|Goならわかるシステムプログラミング</a></li>
</ul>
</li>
<li><a href="https://qiita.com/ruiu/items/54f0dbdec0d48082a5b1">Goでスレッド(goroutine)セーフなプログラムを書くために必ず注意しなければいけない点 - Qiita</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B00I8AT1EU?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41GPVATQiZL._SL160_.jpg" width="125" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B00I8AT1EU?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">Java言語で学ぶリファクタリング入門</a></dt>
<dd>結城 浩 (著)</dd>
<dd>SBクリエイティブ 2007-01-26 (Release 2014-03-12)</dd>
<dd>Kindle版</dd>
<dd>B00I8AT1EU (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">結城浩さんによる「リファクタリング本」の Kindle 版。意外にも Java 以外でも応用できる優れもの。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2018-12-11">2018-12-11</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- Java言語で学ぶリファクタリング入門 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B00I8AT1BS?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/41uoMp5etSL._SL160_.jpg" width="126" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B00I8AT1BS?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編</a></dt>
<dd>結城 浩 (著)</dd>
<dd>SBクリエイティブ 2004-06-18 (Release 2014-03-12)</dd>
<dd>Kindle版</dd>
<dd>B00I8AT1BS (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">結城浩さんによる通称「デザパタ本」の Kindle 版。意外にも Java 以外でも応用できる優れもの。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2018-12-07">2018-12-07</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- Java言語で学ぶデザインパターン入門 マルチスレッド編 -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>HTTP なんかはステートレスでパラレルにやり取りできるため Singleton Pattern は不要。ちなみに <a href="http://golang.org/ref/spec#Go_statements" title="The Go Programming Language Specification - The Go Programming Language">goroutine</a> 間の通信は <a href="http://golang.org/ref/spec#Channel_types" title="The Go Programming Language Specification - The Go Programming Language">channel</a> を使えっちう話です,はい。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:2">
<p>このコードのパターンは Singleton Pattern を説明するにはよく出来ているしちゃんと動く(ココ重要)が,同期コストが高いため,実際にはあまり使われない。 Java における Singleton Pattern には様々な実装例があるので探してみるといいだろう。ちなみに Java 使いではなくとも結城浩さんの<a href="https://www.amazon.co.jp/exec/obidos/ASIN/B00I8AT1BS/baldandersinf-22/" title="増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編 | 結城 浩 | コンピュータ・IT | Kindleストア | Amazon">デザパタ本</a>は買って読んでおくことを強くお勧めする。 Java 使いの方から見ると古いバージョンで書かれたコードなのが難点だが,紙の本で買うとサンプルコード入りのディスクが付いてくるので若干お得? <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:3">
<p>他にもインスタンスのコピー(コピーコンストラクタ等)を暗黙的に許容する言語ではコピーを無効にする措置が必要,とかある。そういう意味じゃ今回私が書いたコードも不完全で,実際には singleton インスタンスを隠蔽するためのラッパークラスが必要になる。ビジネス・ロジックも含めると,実は Singleton の実装ってそう甘くないのよねー <a href="#fnref:3" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:4">
<p>どうもソースファイルのファイル名が影響するらしい。つまりファイル名を工夫すれば <a href="https://golang.org/doc/effective_go.html#init" title="Effective Go - The Go Programming Language"><code>init()</code></a> 関数の呼び出し順を制御できる,という噂。 <a href="#fnref:4" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>