チュートリアルの翻訳、2回目です。
前回までの訳はチュートリアル[日本語訳]にまとめてありますのでごらんください。


Echoコマンドの実装例

次は、Unixのecho(1)コマンドを実装した例です。
echoはコマンドラインパラメータで渡された文字列を標準出力に書き出すユーティリティです。 

05    package main

07    import (
08        "os";
09        "flag";  // command line option parser
10    )

12    var omitNewline = flag.Bool("n", false, "don't print final newline")

14    const (
15        Space = " ";
16        Newline = "\n";
17    )

19    func main() {
20        flag.Parse();   // Scans the arg list and sets up flags
21        var s string = "";
22        for i := 0; i < flag.NArg(); i++ {
23            if i > 0 {
24                s += Space
25            }
26            s += flag.Arg(i)
27        }
28        if !*omitNewline {
29            s += Newline
30        }
31        os.Stdout.WriteString(s);
32    }

短いプログラムですが、目新しいことがいくつか含まれています。前のhello worldプログラムで関数の前にfuncキーワードを使ったようにvar, const, type(これはまだ使っていません)キーワードを宣言を行うために使用します。
7~10行目、14~17行目のように同じ種類の宣言をセミコロン区切りで括弧で括り、ひとまとめにできることを覚えておいてください。ただし、必ずこうすべきという訳ではありません。

    const Space = ” ”
    const Newline = “\n”

この場合はセミコロンはいりません。トップレベルの宣言ではセミコロンは不要です。
宣言リストを括弧で括った場合はセミコロンが必要です。

このechoプログラムでは*os.File型のStdout変数にアクセスするために“os”パッケージをインポートしています。一見そうは思えないかもしれませんが、importステートメントも宣言のひとつです。前の”hello world”で記述したimportの使い方(import fmt “fmt”)で説明すると、2つのfmtのうち最初のfmtはプログラムコードがパッケージメンバーにアクセスする際に使われます。後ろの”fmt”はパッケージをカレントディレクトリもしくは所定の場所から読み込むためのファイル名として使われます。

echoプログラムではimportの際、明示的に名前をつけませんでした。名前をつけない場合はパッケージのファイル名がコードからアクセスするときに使う名前となります。すなわち”hello world”プログラムのほうは、単にimport “fmt”とも書き表せます。

インポートの際、明示的に名前を付けるかどうかは自由です。
ただ本当に名前を付けなければならないケースはパッケージ名が競合したときだけです。

 osパッケージをインポートしたので、os.Stdoutを使ってその中のWriteStringメソッド(文字列出力)にアクセスできます。

12行目で インポートしたflagパッケージを使ってechoコマンドの-nフラグを格納するためのグローバル変数を作っています。
変数omitNewlineは*bool型(=bool型のポインタ)です。

mainパッケージのmin関数の20行目で、コマンドラインパラメータの解析(parse)を行い、出力する文字列を格納するローカル変数を作っています。

変数の宣言は下の形式です。 

    var s string = "";

 var キーワードに続いて、変数名、変数の型、イコール記号、初期値記述します。

Go言語はシンプルさを目指しています。その結果、この宣言文を短くすることに成功しました。文字定数がstring型なので、わざわざそれをコンパイラに伝える必要はありません。 

    var s = "";

また、さらに短い書き方が出来ます。 

    s := "";

この:= 演算子は初期値を宣言する際にGo言語で多用されます。 次の行のfor文で使われています。

 22        for i := 0; i < flag.NArg(); i++ {

flagパッケージはコマンドラインパラメータを解析した際、フラグ以外のパラメータをリスト内に残したままにします。
リストは当然ながら内部要素を繰り返して取り出す(イテレート)ことが可能です。

Go言語のforステートメントは、C言語と比べると若干違いがあります。まず、ループ処理を記述できるのはforだけで、whileやdoはありません。次に、for節は括弧でくくる必要がありません。ただしループの本体部分は波括弧{}でくくる必要があります。ifやswitchステートメントもこれと同様です。
チュートリアルの後ろのほうでは、for文の他の書き方がでてきます。

ループ内では+=記号を使って文字列を結合しています。
ループを抜けた後は、-nフラグがセットされていなければ改行コードを文字列に加え、最後に作成した文字列を標準出力に書き出します。

mainパッケージのminはパラメータ・戻り値を持たない関数です。main関数の最後まで実行されれば処理が成功したことになります。エラーを返したいときは、下の呼び出をします。 

    os.Exit(1)

このosパッケージは、このほかにもコマンドラインパラメータを格納したos.Args変数などが含まれています。


今回はここまでです、いかがだったでしょうか。Go言語を少しでもなじんでいただければ幸いです。
それではまた次回をお楽しみに。