第3回 ハロー、goroutine!
赤坂 けい
チームWordProgress
2010/1/22
突然登場した新しいプログラミング言語「Go」。その独自性、魅力を余すところなく堪能してみよう(編集部)
Goのマーケットシェアは1.25%
2009年末のグーグルの発表以降、世のプログラマの注目を集めているプログラミング言語Go。プログラミング言語のマーケットシェア(普及度合い)の測定結果を毎月公表しているTiobeは、2009年12月からプログラミング言語のシェアの測定対象にGoを算入することとした。
測定結果は2010年1月8日に発表され、Goは約1.25%のシェアを獲得した。その結果、Goは、1年を通してもっともマーケットシェアを伸ばしたプログラミング言語に贈られる「TIOBE Programming Language of Year」を受賞することとなった。
この賞は、C++(2003年)、PHP(2004年)、Java(2005年)、Ruby(2006年)、Python(2007年)、C(2008年)と、名の通ったメジャー言語、準メジャー言語が受賞してきた。
新言語のGoが受賞することは異例のことであろう。ちなみに、2009年にマーケットシェアを大きく伸ばした言語には、ほかにObjective-C、PHP、C#、Lisp、Scalaなどがある。
Objective-Cは、iPhoneの開発言語として注目を集めたため、PHPは安価なホスティングサービスで安心して使える言語としてシェアを伸ばしたのであろう。
ひょっとすると、長引く不況の中、「稼げる言語」であったJavaやC/C++がさほど稼げなくなっていることが、オルタナティブとしてのマイナー言語、新興言語を探す傾向につながっているのかもしれない。
ともあれ、新興言語の代表格の1つに収まりつつ感のあるGoを今回も学んでいこう。今回は、Goの特徴的な機能であるgoroutineを取り上げたい。
Goの軽量で簡潔な並列処理記述
Goでは、並列処理したい関数(goroutine)を呼び出すgo文とgoroutine間での通信に用いられるチャネルを用いて、簡単に並列処理を記述できる。goroutineは、マルチコアCPUで同時実行可能であり、Javaのスレッドなどに比べ極めてリソース消費が極めて小さいという特徴がある。
こうしたGoのアプローチは、並行処理を行うプログラムの相互作用パターンを記述するためのCSP(Communicating Sequential Processes)に基礎を置いている(ほかにもCSPに基礎を置く言語として、マイクロソフトがラボとして公開しているC#風の並列処理言語Axumがある)。
CSPの背景にある数学的理論の学習を筆者は後回しにしてしまっているが、Goで並列処理記述は不自由なく体験できている。理論的背景に興味のある方は、WikipediaのCSPの解説などを起点にネットで調べていただきたい。
チャネル間の通信を記述する<-演算子
それでは、単純なgoroutineのプログラムを見ていこう(Goのコンパイル方法などは第2回の記事を参考にして欲しい)。
package main var ch = make(chan string) func g(str string) { println(str); ch <- "printed"; } func main() { go g("hello, gorutine!"); <- ch; }
D:\go-win\mysrc\gorou>.\8.exe hello, gorutine!
プログラムの冒頭部では、make関数を用いてチャネル(chan)を初期宣言している。チャネルは、ほかの要素(オブジェクト)への参照であり、goroutine間での通信に用いられる。チャネルは、初期宣言時に、通信されるオブジェクトの型を指定する必要がある。
また、main関数の中では、go文を用いて、関数g()を呼び出している。g()は、引数として渡された文字列を表示するだけの簡単な関数である。
ここまでは一読してすぐに理解できるだろう。少し奇妙なのが、「<-」という演算子を用いて記述された残りの2行である。<-演算子は、チャネルでの通信を記述するためのものである。
ch <- "printed";
とすると、チャネルchに文字列"printed"が渡される。また、チャネルを右側に書いた
<- ch;
という記述は、チャネルから値を取り出す記述である(ここでは、取り出すだけで、値を受け取るオブジェクトは存在しない)。
値を受け取るオブジェクトは存在しないということから、このプログラムにおいてチャネルは必要ないと思われるだろう。
だが、試しにチャネル部分を除いてみると、"hello, gorutine!"は表示されなくなる。
package main func g(str string) { println(str); } func main() { go g("hello, gorutine!"); }
(表示なし)
これは、呼び出された関数g()がprintlnを実行する前にmain関数が終了してしまうためである。goroutine1.goでは、main関数は、「<- ch」という演算を完結させるため、関数g()の処理「ch <- "printed"」を待つこととなり、結果、関数g()のprintlnが実行され文字列が表示されてから、main関数が終了する。
1/2 |
Index | |
ハロー、goroutine! | |
Page1 Goのマーケットシェアは1.25% Goの軽量で簡潔な並列処理記述 チャネル間の通信を記述する<-演算子 |
|
Page2 goroutineが生成した値を、そのつど受け取るパターン goroutineでクロージャを活用するパターン |
新世代の並列処理言語Google Goをひもとく |
Coding Edgeお勧め記事 |
いまさらアルゴリズムを学ぶ意味 コーディングに役立つ! アルゴリズムの基本(1) コンピュータに「3の倍数と3の付く数字」を判断させるにはどうしたらいいか。発想力を鍛えよう |
|
Zope 3の魅力に迫る Zope 3とは何ぞや?(1) Pythonで書かれたWebアプリケーションフレームワーク「Zope 3」。ほかのソフトウェアとは一体何が違っているのか? |
|
貧弱環境プログラミングのススメ 柴田 淳のコーディング天国 高性能なIT機器に囲まれた環境でコンピュータの動作原理に触れることは可能だろうか。貧弱なPC上にビットマップの直線をどうやって引く? |
|
Haskellプログラミングの楽しみ方 のんびりHaskell(1) 関数型言語に分類されるHaskell。C言語などの手続き型言語とまったく異なるプログラミングの世界に踏み出してみよう |
|
ちょっと変わったLisp入門 Gaucheでメタプログラミング(1) Lispの一種であるScheme。いくつかある処理系の中でも気軽にスクリプトを書けるGaucheでLispの世界を体験してみよう |
|
- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
|
|