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

第2回 GoのPrint文、forループ、if文

赤坂 けい
チームWordProgress

2009/12/24

初めてのGoプログラム

 では、いよいよGoプログラムを作成していこう。

 ここからは、Cなどのプログラム言語の経験者を前提とした解説を行う。プログラム初心者の方は、CやPythonなどの言語入門をこなした後に、Goにチャレンジしてほしい。

 まず、「Hello World」プログラムで、Goのprint文関係を確認しておこう。

 Goのプログラムでは、package文を用いたパッケージ宣言が必要である。また、関数の宣言はキーワードfuncによって行う。そして、改行なし・改行ありの文字列出力文printおよびprintlnを特に宣言することなく使うことができる。

 そのため、ミニマムな「Hello World」プログラムは以下のようなものとなる。

●hello.go
package main
func main() { println("hello world.") }

 お使いのエディタでhello.goを作成した後は、作業フォルダ(筆者の場合、D:\go-win\mysrc)に保存してほしい。

 次いで、コマンドプロンプトを開き、以下のようにタイプする。

D:\go-win\mysrc>8g hello.go

D:\go-win\mysrc>8l hello.8

D:\go-win\mysrc>8.exe
hello world.

 1行目の「8g」コマンドはgoプログラムのコンパイルを行い、中間ファイルhello.8を生成する(「8」は、x86向けのコンパイルという意味である)。次の「8l」コマンドは、ライブラリなどのリンクを行い、実行ファイル(go-windowsでは、デフォルトで「8.exe」)を生成する。最後に、生成した実行ファイルを実行している。

 Goのソースは複数のCPUのバイナリコードへとクロスコンパイル可能である。64-bit x86や32-bit ARMで実行されるバイナリコードを生成する場合には、それぞれの専用のコマンド(6g、5gなど)を用いてほしい(参考:
Go言語のインストール[日本語訳])。

 Goのprint文は、fmt(フォーマット)パッケージにもPrint、PrintlnおよびPrintf文が用意されている。このうち、フォーマット付き出力を行うPrintf文は、利便性が高い。

 Printf文を用いた日本語版ハローワールドを試しておこう。

●hello2.go
package main
import ("fmt")

func main() {
 //変数の初期化
 var hello = "ハローワールド";
 //フォーマット対応Printf
 fmt.Printf("%s。\nただの%sにはあまり興味ありませんけど。\n",hello,hello);
}

 パッケージのインポートはimport文で行う(fmtパッケージの場合、import ("fmt")とする)。変数宣言はキーワードvarを付けて行う(このあたり、どこかJavaScript風だと個人的に思っている)。

 第1回で述べたように、Goは静的型付けを行うコンパイル言語であるが、"ハローワールド"といった自明な型(ここでは文字列リテラル)については、型宣言を省略できる。

 本ファイルには、コメントを入れた。コメントはJavaなどと同様に「//」または「/*〜*/」で記述する。

 また、hello2.goのように、日本語(あるいは2バイト圏の文字)を含むソースコードの場合には、ファイルの文字コードをUTF-8に指定しなければならない。お使いのエディタで文字コードをUTF-8にして、保存しておいてほしい。

D:\go-win\mysrc>8g hello2.go

D:\go-win\mysrc>8l hello2.8

D:\go-win\mysrc>8.exe
ハローワールド。
ただのハローワールドにはあまり興味ありませんけど。

2種類のforループと配列

 続いて、Goのforループを見ていこう。GoのforループにはC風のシンプルなループとスクリプト言語風の拡張forが提供されている。まず、拡張forの方から見ていきたい。

 拡張forは、配列などの集合(コレクション)の要素を1つずつ処理するための命令文である、と理解しておくと良いだろう。より詳細な説明は、連載が進んだ後に行いたい。

●basic.go
package main
import ("fmt")
//文字列配列の定義
var str = [...] string {"いち","に","さん","ダー"}

func main() {
//拡張for
   for i, s := range str {
       fmt.Printf("%d: %s\n", i, s)
   }
}
D:\go-win\mysrc>8g basic.go

D:\go-win\mysrc>8l basic.8

D:\go-win\mysrc>8.exe
0: いち
1: に
2: さん
3: ダー

 押さえておくべきポイントが3点ある。

 第1に、配列の定義方法について。配列の簡易な定義方法は、

[配列のサイズ] 型 {初期の値}

である。

 basic.goでは、変数strに配列を割り当てている。ここでは、初期の値を明示する場合、[...]という表記でサイズ指定を省略して、コンパイラに自動で決めてもらっている。

 第2に、拡張forは以下のように記述する。

for 変数名 := range コレクション名 {(処理内容)}

 注意すべき点は、プログラム中の「変数名」のところで変数iと変数sが同時に宣言されていることであろう。

 1番目のiには、0からはじまるループカウンター(0、1、2……)が代入される。2番目のsには、コレクションの要素が代入される。括弧がなくそっけない表記がGo流である。そっけない表記ではあるが、必要なループカウンターとコレクションの要素がいっぺんに取得でき、便利ではある。

 最後に、注意深い読者は気付いていると思うが、今回のbasic2.goのコード中には、セミコロンが1つも出てきていない(前出のhello2.goの方には、セミコロンがある)。

 現状のgoでは、以下の2カ所でセミコロンが省略できる。

  1. セミコロンは、トップレベル(括弧や中括弧で囲まれていない部分)の文では省略できる
  2. セミコロンは、括弧・中括弧の最後の文で省略できる

 逆にいうと、括弧・中括弧中では、最後の文以外ではセミコロンは省略できない。

 この省略ルールは、いささか原始的であり、さほど役に立たないかもしれない。覚えるのが面倒であるならば、CやJavaと同様にセミコロンを付けるのだと思っておいても問題はないだろう。

2009年12月25日追記

 12月末のアップデートにより、セミコロンは大胆に省略できるようになった。末尾に省略表記の例を示す

 さて、配列の理解を深めるため、「配列のサイズ」を初期値のサイズ以上に設定してみよう(「配列のサイズ」を初期値以下にした場合はエラーとなる)。

●basic2.go
package main
import ("fmt")
//文字列配列の定義
var str = [10] string {"いち","に","さん","ダー"}

func main() {
//配列の要素への代入
   str[3]="たんたかたん";
   str[6]="ろく";
//拡張for
   for i, s := range str {
       fmt.Printf("%d: %s\n", i, s)
   }
}
D:\go-win\mysrc>8g basic2.go

D:\go-win\mysrc>8l basic2.8

D:\go-win\mysrc>8.exe
0: いち
1: に
2: さん
3: たんたかたん
4:
5:
6: ろく
7:
8:
9:

 実行結果を見ると、サイズ指定を行うことで指定されたサイズの配列が用意されることと、配列の要素は、初期値を含め代入により上書き可能であることが分かるだろう。

 次に、C風のforループを簡単に確認しておきたい。

●basic.go3
package main
import ("fmt")
//ふつうのforループ
func main() {
   for i := 0; i < 10 ;i++ {
       fmt.Print(i)
   }
}
D:\go-win\mysrc>8g basic3.go

D:\go-win\mysrc>8l basic3.8

D:\go-win\mysrc>8.exe
0123456789

 forの後で、「ループカウンタiを0に初期化し、ループの継続条件としてi < 10を宣言し、ループが回るたびにiを増加させる(i++)ということ」が宣言されている。そっけないGoらしく括弧がないのが、なれないうちは気になるかもしれないが、Cとほぼ同様なので容易に理解できるだろう。

2種類のforループと配列

 最後に、if文と関数呼び出しを見ておこう。

●basic4.go
package main
import ("fmt")

func f( x int ) int {
   if x > 0 { return x * x } 
   return 0 
}

func main(){
	y := f(2);
	fmt.Printf("f(2) = %d\n", y);
	fmt.Printf("f(-2) = %d\n", f(-2));
	
}
D:\go-win\mysrc>8g basic4.go

D:\go-win\mysrc>8l basic4.8

D:\go-win\mysrc>8.exe
f(2) = 4
f(-2) = 0

 Goの関数は、

func 関数名(引数名 引数の型) 返り値の型 {関数本体の記述}

と記述するのが基本となる。関数の返り値は、return文で行う。

 また、if文はCなどと同様に記述するが、for文と同じく条件式のところに括弧を付けない。

 以上、駆け足であったが、今回はGoのWindowsマシンへのインストール方法、Print文関係と2種類のforループ、関数呼出し、if文を見た。次回は、今回解説し切れなかった部分を補充したうえで、Goの特徴の1つであるgoroutineを体験したい。

 その後、Goの賢いビルド方法やGoのライブラリの概要、さらには、新バージョンのライブラリなどへの更新方法についても取り上げていく予定だ。

2009年12月25日追記

 本稿を書き上げた後(2009年12月22日)、Goの比較的規模の大きなアップデートが、Goのメーリングリストでアナウンスされた。Linux/Mac OSユーザー限定となるが、新機能を試したいユーザーは、Mercurialを用いたアップデートを試みてほしい。こうしたアップデート情報は確認が取れ次第、本稿でも紹介していきたい。

 このアップデートでセミコロンが省略できる場合が増えている(命令間のセミコロンは基本的に省略可能)。筆者はまだ省略ルールの詳細を把握しておらず、また、今後、変更される可能性もあるため、詳細は後ほどの報告としたい(go-windowsは、このアップデートを追随できていない)。

 アップデート後、例えば、basic2.goのセミコロンはすべて省略できる。また、以下のようなセミコロンなしのソースも動作している。

●strings.go( 最新アップデートでのみ動作することを確認)
package main
import (
"fmt"
"strings"
)

func countTest(src, term string) {
    count :=strings.Count(src, term)
    if count > 0 {
        fmt.Printf("%sは、%d個を発見\n",term, count)
    } else {
        println("文中に見つかりませんでした :" + term)
}

}
func main() {
    str := "XML(Extensible Markup Language)は、「メタ言語」(metalanguage)
と呼ばれる言語のひとつ。"
    println("対象とする文 :" + str)
    countTest(str,"XML")
    countTest(str,"言語")
    countTest(str,"言葉")
}

お詫びと訂正

 連載第1回において、「現状のGoでは、関数内に複数のreturnを書くことができない」との記述を行いましたが、こちらは、「現状のGoでは、if文内に複数のreturnを書くことができない」の誤りでした。申し訳ございませんでした(ご指摘いただいた方、ありがとうございました)。

 上述の「basic4.go」にあるように、if文内にreturnを書くことができます(こうした表現は、Goのライブラリ中にも頻出しています)。

prev
2/2
 

Index
GoのPrint文、forループ、if文
  Page1
Goをインストールする
Windowsマシンへのインストール
  Page2
初めてのGoプログラム
2種類のforループと配列
if文と関数呼び出し
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 記事ランキング

本日 月間