新世代の並列処理言語Google Goをひもとく

第3回 ハロー、goroutine!

赤坂 けい
チームWordProgress

2010/1/22

突然登場した新しいプログラミング言語「Go」。その独自性、魅力を余すところなく堪能してみよう(編集部)

Goのマーケットシェアは1.25%

- PR -

 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回の記事を参考にして欲しい)。

●goroutine1.go
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!"は表示されなくなる。

●goroutine2.go
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
next

Index
ハロー、goroutine!
  Page1
Goのマーケットシェアは1.25%
Goの軽量で簡潔な並列処理記述
チャネル間の通信を記述する<-演算子
  Page2
goroutineが生成した値を、そのつど受け取るパターン
goroutineでクロージャを活用するパターン

index 新世代の並列処理言語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の世界を体験してみよう
  Coding Edgeフォーラムフィード  2.01.00.91


Coding Edge フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Coding Edge 記事ランキング

本日 月間
ソリューションFLASH