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


Goの型について

Go言語も、他の言語と同じようにintやfloat型といったサイズがシステムによって異なる型を持ってます。
サイズを明示したint8やfloat64型もあり、加えてuint, uint32といった符号なし整数型もあります。これらはすべて異なる型であり、たとえint型が32ビットのシステム上であっても、intとint32は同じ型ではありません。
一方、byte型はuint8型の同義語です。(byte型はstring型の要素)

string型もまた言語に組み込まれた型です。これについて説明します。
string型は単純なbyte型の配列ではなく不変、すなわち一度string型の値を作成すると値は変更できません。あたりまえですが代入によりstring型の値を入れ替えることは可能です。strings.goプログラムから抜き出した下のコードは正しく動作します。

11        s := "hello";
12        if s[1] != 'e' { os.Exit(1) }
13        s = "good bye";
14        var p *string = &s;
15        *p = "ciao";

しかし下のコードはstring型の値を変更しようとしているので不正なコードです。 

    s[0] = 'x';
    (*p)[1] = 'y';

Go言語のstring型はC++言語の文字列定数(const string)のようなもので、string型のポインタは文字列定数の参照とほぼ同じです。

はい、ここでポインタという言葉が出てきました。
Go言語ではポインタの扱いが若干シンプルとなっています。では続きをどうぞ。

配列はこのように宣言します。 

    var arrayOfInt [10]int;

配列はstring型と似ていますが、要素の値は変更可能です。
C言語では、上の例のarrayOfInt変数をint型のポインタとしても扱えますがGo言語では扱えません。
配列のポインタはとても重要(かつ有益)であるため追って説明します。

配列はそれ自身がサイズ情報を持っています。そして配列からスライス変数をつくれます。スライスとは同型の配列のポインタを割り当てることができる変数です。
より一般的に説明すると、a[low : heigh]と記述すると配列aのlow~high-1までを参照しているスライスができます。
スライスは配列とそっくりですが、サイズを明示的に持たず([] と[10]の違い)、配列内の一部分だけを参照します。
配列はデータを共有はできませんが、複数のスライスで同じひとつの配列を参照していればデータが共有されます。

Go言語のプログラムにおいて、スライスは通常の配列より柔軟であり、他オブジェクトへの参照情報をもっていて、かつ効率的であるため多用されます。
その一方、スライスでは通常の配列のようには細かいメモリ割り当ての制御はできないため、たとえば100要素の配列を持たせるような場合は通常の配列を使ってください。

関数に配列を受け渡すときは、たいていパラメータをスライスとして宣言します。関数を呼び出す側では、スライス式で配列の必要な部分のみの参照を作成して(効率的に)関数をよびだしてください。

関数でスライスを使用した例です。(sum.goから) 

09    func sum(a []int) int {   // returns an int
10        s := 0;
11        for i := 0; i < len(a); i++ {
12            s += a[i]
13        }
14        return s
15    }

このsum関数を呼び出すにはこうします。 

19        s := sum(&[3]int{1,2,3});  // a slice of the array is passed to sum

sum関数の戻り値の型はintです。戻り値の型は関数のパラメータリストの直後に記述します。

[3]int{1,2,3}"の箇所で、角括弧[]につづいて型を記述して配列を作成しています。この例だとint型3要素を持つ配列です。&記号を前に書くことでこの配列のインスタンスのアドレスを得られます。
配列を暗黙的にスライスにしてsum()関数に配列のポインタを渡しています。

配列作成時、要素数を指定する代わりにコンパイラ側にカウントしてもらうには、配列のサイズに…を指定します。 

    s := sum(&[...]int{1,2,3});

実際のところ、配列データのメモリ割り当てについて気にしない限りは、角括弧[]を空にして&をつけずにスライスを作成するだけで事足ります。 

    s := sum([]int{1,2,3});

マップも同様に、次のように初期化できます。 

    m := map[string]int{"one":1 , "two":2}

sum関数内で初めて出てきた関数len()は組み込み関数で、要素数を返します。
このlen関数は文字列、配列、スライス、マップ、チャネルで利用可能です。 

話は変わりますが、同様に文字列、配列、スライス、マップ、チャネルに対して機能するrangeについて説明します。これはforループ節で使用します。説明するより見てもらったほうが早いので、

    for i := 0; i < len(a); i++ { ... }

これはスライス(またはマップなど)の要素数ループを繰り返します。これを下のように書き換えることが出来ます。 

    for i, v := range a { ... }

この例ではi変数にループのインデックス、v変数にrangeで指定したaの要素が順番に代入されます。
rangeの使用例は Effective Go をご覧ください。