2016/12/27

[プログラミング言語Go] 第4章 コンポジット型

スポンサーリンク

丸善出版の『プログラミング言語Go』の読書履歴です。

出てきた内容の気になったポイントのまとめや練習問題の解答(自分なりの)を記載していきます。
(ここに記載されている内容で問題が生じても責任は負えませんのであしからず…。)

練習問題は結構長くなるものが増えてきたので、本文記載のコードの修正の場合は修正部分だけ抜粋しています。
すべてのコードが見たい場合はGitHubにあるので、そちらを見てみてください。
プログラミング言語Go GitHub

さて、第4章はコンポジット型についてです。

もくじ

4.1 配列
4.2 スライス
4.3 マップ
4.4 構造体
4.5 JSON
4.6 テキストテンプレートとHTMLテンプレート

これまでの章のまとめはこちら

第1章 チュートリアル
第2章 プログラミング構造
第3章 基本データ型

4.1 配列

配列は特定の型の0個以上の固定長列です。
配列は固定長なので、可変長なスライスを使うことのほうが多いですが、基本として押させておくといいと思います。

配列の宣言は次のように書きます。
[] が先にくるのでちょっと見慣れないですが、C/C++やJavaと同じような書き方ですね。

配列の通常の変数と同様に宣言時に初期化されます。
この例の場合は int型の配列なので、3つの要素は 0 で初期化されます。

各要素にアクセスするには次のように書きます。
インデックスは0から始まるので、3つの要素を持つ配列の場合は 0〜2を指定します。

配列のインデックスを要素を表示する場合は次のように range を使ってforでループしてあげればOKです。
インデックスか要素かどちらか一方が必要な場合は、不要な方を _ を指定してあげます。

宣言時に任意の値で初期化したい場合は次のように書きます。
また、初期化に値の数は指定した要素数より少なくても大丈夫で、その場合は 0 で初期化されます。

どちらも3つ目の要素を表示しようとしているので、3 と 0 が表示されるはずです。

初期値を指定する場合は、データ型の指定を省略できます。

さらに要素数を省略することもできて、[...] としてあげます。ただし、この場合は初期化で指定された要素数になることに注意しましょう。」

要素数は配列の型の一部なので、[3]int[4]int は違う型とみなされます。
なので、 [3]int で宣言した変数に対して、[3]int{} という形でまとめて代入することは可能ですが、[4]int{} という形で代入することはできません。

練習問題4.1

あーもう、かなり強引なやり方なので違うと思います…
アルゴリズムがわからん…。

練習問題4.2

こちらはまぁ、今までもよく出てきているコマンドラインフラグと標準入力を使ったものですね。

4.2 スライス

スライスはすべての要素が同じ型である可変長配列です。
大きさがない配列のようなもので、宣言は以下のように書きます。

使い方は配列とにていますが、スライスは比較ができないので2つのスライスが同じ要素で構成されているか調べるのに == が使えません。
バイトスライスである []byte の場合は標準で比較するためのbytes.Equalを提供されていますが、その他の型のスライスの場合は自分で比較を行う必要があります。

4.2.1 append関数

標準で用意されているappend関数を使ってスライスに項目を追加することができます。
使い方は以下のようになります。

追加したい値はカンマで区切って複数個指定することも可能です。
append()をしただけでは引数に指定したスライスは更新されないので、必ず変数に代入して上げる必要があります。

4.2.2 スライス内での技法

ここではさらに要素の修正を行う例の説明があります。
まぁここは書籍を読んでいただくことにして、さて、練習問題へ…

練習問題 4.3

スライスの代わりに配列へのポインタを使うようにreverseを書き直す、というものでして、だいぶ力技な気がするのでどうでしょうね…

練習問題 4.4

rotateを作りなさい、という問題なのですが、やっぱりゴリ押し感が…。

4.3 マップ

マップ型は map[K]V と書きます。ここでの K はキーの型で、V は値の型になります。
マップ内のすべてのキーの型は同じであり、すべての値の型は同じである必要がありますが、キーと値は同じ型である必要はありません。

map を作るには標準で用意されている make 関数を使います。

マップの作成と同時に初期値を入れることも可能で、その場合はmake関数を使わずに書くことができます。

map の要素にアクセスするときはキーを使えばいいので、このように書きます。

map に要素を追加するときは新しいキーを使って値を代入すればOKです。

map から要素を削除するときは delete関数を使います。

map の全てのキーと値を列挙するには for と range を使います。

練習問題 4.8, 4.9

すみません、マップの練習問題は飛ばします…。

4.4 構造体

構造体は合成データ型であり、0個以上の任意の型の変数をまとめて管理するものです。
それぞれの変数をフィールドと呼ばれます。

構造体の定義は type 構造体名 struct {...} となります。

それぞれのフィールドにアクセスするには、構造体名.フィールド名 という形になります。

4.4.1 構造体リテラル

宣言時に初期化を行うこともできます。

ただしこの場合は全てのフィールドに対して、正しい順序で値を指定する必要があるので、image.Point{x, y}やcolor.RGBA{red, green, blue, alpha}などのようにフィールドの順番が明らかで小さい構造体で使われることが多いです。

もうひとつ初期化の方法があり、下記のようにフィールド名を指定して値を代入する方法です。

こちらの場合は全てのフィールドを指定する必要はなく、必要なものだけ初期化できます。
初期化されていないものはゼロ値が設定されます。
フィールドの順序も気にする必要はありません。

4.4.2 構造体の比較

構造体のすべてのフィールドが比較可能なものであれば、構造体自体の比較も可能です。
その場合は ==!= が使えます。

4.4.3 構造体埋め込みと無名フィールド

構造体の中に別の構造体を使いたいということはよくあると思いますし、そういった使い方ももちろんできます。

このように宣言した場合、CircleからPointのXやYにアクセスするには以下のように書くことになり、ちょっと面倒です。

そこで、型は持つけれど名前を持たないフィールドを宣言することができて、そういったものを無名フィールドと呼びます。
その場合は以下のように宣言します。

この場合、PointのX、Yにアクセスするには以下のようにすればよいので、あたかもCircle自体にフィールドが宣言されているかのように使うことができます。

無名フィールドを使って宣言していても、きちんと構造体名を指定して c.Point.X = 8 というように指定することも可能です。

ただし、初期化を行うときには無名フィールドを使うことはできないので、以下の2つの方法で初期化してください。

4.5 JSON

Go言語は encoding/json パッケージがあります。
json.Marshaljson.MarshalIndent を使うと Go のデータ構造をJSONへ変換してくれます。

構造体を使ってJSONのデータ構造を作っておきます。
json:"released" の部分ですが、これはJSONオブジェクトを作るときにフィールドを名をYear ではなく released にする、という意味になります。

構造体ができたら、データを以下のように作っておきます。

このデータをJSONオブジェクトに変換するには以下のようにします。

Marshalでもいいのですが、MarshalIndentにしておくと、フィールドごとにインデントされた状態で出力してくれるので見やすくなります。

これを実行すると、以下のように出力されます。

練習問題4.10 〜 4.13

すみません。ちょっと練習問題はお休みします。

4.6 テキストテンプレートとHTMLテンプレート

テキストテンプレートやHTMLテンプレートは text/template や html/template パッケージを使えます。

テンプレートとは、アクションと呼ばれる二重波括弧{{...}} で囲まれた部分を1ヵ所以上含んでいる文字列またはファイルです。

{{}} のなかには構造体のフィールドを指定すれば、その値が表示されるようになります。

簡単なサンプルですが、このようになります。

まずテンプレートとなる文字列(templ)を作っておいて、templを元にテンプレートを生成します。
テンプレートに入れ込むための構造体を作って、フィールドを初期化します。
生成したテンプレートを Execute を使って出力します。

上のサンプルはテキストテンプレートの使い方ですが、HTMLテンプレートも基本的には同じように使うことができます。

その他のサンプルが見たい場合はGitHub にソースを参照してください。

さて、、、途中ちょっと他の勉強をしていたりで、だいぶ時間がかかってしまいましたが、ようやくコンポジット型を読了。
次は5章関数です。早めに終わらせたい…。

スポンサーリンク