2017/01/08

[プログラミング言語Go] 第5章 関数

スポンサーリンク

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

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

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

とはいえ、練習問題に時間がかかりすぎて、なかなか先に進めない感じもあるので、飛ばしてしまっています。
すみません(;´Д`)
気が向いたら練習問題もやっていこうと思うので、その際は追記します。

さて、第5章は関数についてです。

もくじ

5.1 関数宣言
5.2 再帰
5.3 複数戻り値
5.4 エラー
5.5 関数値
5.6 無名関数
5.7 可変個引数関数
5.8 遅延関数呼び出し
5.9 パニック
5.10 リカバー

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

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

5.1 関数宣言

関数の宣言は以下のような構文になります。

parameter-listは引数で、名前を型を指定します。
result-list は戻り値の型を指定します。

なので、具体的に書いてみると、以下のようになります。

Go言語には引数のデフォルト値や名前付き引数、というのもないのですね。

5.2 再帰

Goでは関数を再帰的に使うことができます。
自分自身を直接的にも間接的にも呼び出すことができます。
4.4節のサンプルですでに使っているのですが、さらに詳細な説明がされています。

ここの節では golang.org/x/net/html パッケージを使うので、 go get を使ってインストールしておきましょう。

使い方、と言ったほどのことはなくて、普通に自分自身を呼び出してあげればOKです。

具体的な使い方はGitHub のサンプルコードを見ていただいて…。

5.3 複数戻り値

今までも出てきていましたが、関数は複数の戻り値を返すことができます。
戻り値の型を指定するところで (データ型, データ型) と複数カンマ区切りで書いてあげます。
もちろんそれぞれ違う型でも大丈夫です。

5.4 エラー

Go言語の場合、他の言語によくある例外を使ってエラー処理をするのでなく、戻り値で error を一緒に返すというような方法と取っているようです。
いままでのサンプルコードでも error を受け取るコードは出てきていましたね。

error は nil か nil でないかであり、nil の場合は成功を、nil でなければ失敗を意味します。
nil 出ない場合の error は fmt.Println(err) などとすると、エラーメッセージを表示してくれます。

5.5 関数値

関数はファーストクラス値なので、関数は他の値と同様に型を持ち、変数に代入したり、関数に渡したり、関数から返したりすることができます。

以下のように3つの関数があったとして、変数 f に関数である square を代入して、f として実行することが可能です。
square と negative は引数と戻り値の数、型が同じなので、同じデータ型とみなされるので、そのまま f に negative を代入することはできます。
product は引数の数が違うので違う型になるので、f に代入することはできません。

5.6 無名関数

関数値を表す関数リテラルは全ての式内で使うことができ、関数リテラルは関数宣言のようにかきますが、func の後に名前がありません。こういった関数を無名関数と呼びます。

例えば、strings.Map の第一引数を無名関数で書くと次のようになります。

このように無名関数は引数に渡すこともできますし、次のように戻り値として返すこともできます。

5.7 可変個引数関数

可変個引数関数とは可変個の引数で呼び出すことができる関数です。
いままでにも使っている fmt.Printf などがこれにあたります。

可変個引数関数を宣言するには、パラメータの型の前に ... を付けます。

この sum 関数を呼び出すときは、0個以上の引数を指定すればいいので、以下のように書きます。

また、スライスを渡すこともできて、その場合は次のように書きます。

5.8 遅延関数呼び出し

普通の関数やメソッドの呼び出しの前に defer を付けると、遅延関数呼び出しとなります。
遅延関数呼び出しを行うと、関数と引数の式は defer文が実行されるときに評価されますが、実際の呼び出しは defer 文を含む関数が完了されるまで遅延されます。

5.9 パニック

Goの型システムはコンパイル時に多くの誤りを検出しますが、それ以外の境界外への配列アクセス、nilポインタ参照などの誤りは実行時の検査が必要になります。
Goランタイムがそのような誤りを検出した際にパニックとなります。

パニックは通常の実行を停止し、ログメッセージを表示してクラッシュします。

パニックを発生される場合は panic("error message") とすればいいようです。

5.10 リカバー

パニックは通常プログラムを終了してしまいますが、パニックから回復したときもあります。
そのときに使えるのがリカバーです。

遅延された関数内で recover 関数が呼び出され、かつ defer 文を含む関数がパニックになると、recover はパニックを終了させてパニック値を返します。

と、ここまでで関数については終了です。

ちょっと私自身理解不足なところが多いので、時間があるときにでも見直せたらな、と思います。

ひとまず、先に進むことにします!

スポンサーリンク