ゼロから学ぶGo言語プログラミング(5) 命名とセミコロン

引き続き、各種命名とセミコロンについて。

前回同様以下のドキュメントを参照していきます。

名前

パッケージ名の付け方

冒頭、パッケージのエクスポートが名前で制御されていることへの言及が。

たとえば名前の頭文字が大文字かどうかで、パッケージの外からの可視性が決まります。

先頭大文字の要素はエクスポートされ、それ以外は不可視。 publicだとかinitだとかに頼らず、名前のみで可視性が決まる。 ここもシンプルですが、頭が慣れるまで少し時間がかかりそうです。

慣例では、パッケージ名は小文字でひとつの単語です。アンダースコアや大文字が混ざって(mixedCaps)はいけません。パッケージ使用者がその名前をタイプすることを考慮して、簡潔すぎるぐらいにしてください。名前が重複することを気にする必要はありません。パッケージ名は、単にインポート時にデフォルトとして使われる名前であり、ソースコード全体でユニークである必要はありません。万が一、パッケージのインポート時に重複が起きたときは、別なローカルな名前をつけることができます。

ここもかなり重要そうな。 自分でパッケージ名付ける場合は、以下が基本らしい。

  • 小文字のみ
  • なるだけシンプルに
  • 重複を気にするな
  • 衝突はインポート側で解決できる

そして以前疑問だった、インポート時のパッケージ名のエイリアスを"."とできる件にも言及が。

import . 表記を使うとアクセス時にパッケージ名が不要となりますが、これはテストや他の一般的でない状況で使うためのものなので必要でない限り避けるべきです。

テストコードでは、パッケージ名を省略してアクセスできるようなインポートの仕方が、便利な場合があるということでしょうか。

エクスポート対象の名前の付け方

パッケージを経由してアクセスするエクスポート対象の命名は、使用されるシーンを意識すべき、ということか。

パッケージ名を使うので、エクスポートされる名前は、同じ名称が繰り返されることを避けるためにパッケージ名を利用することがあります。たとえば、bufioパッケージ内の、バッファ付きリーダ型は、BufReaderではなくReaderと名づけられています。

複雑もしくは微妙なニュアンスを持つものに名前をつけるときは、すべての情報を名前で表現しようとするより、通常は役立つドキュメントコメントを書いたほうがよいでしょう。

説明的で厳密な名前を取るよりも、冗長さを減らして直感的に"パッケージ.要素"という構造が表現できるようにせよ、という思想のようです。

これまで他の言語でなんとなくプログラミングをしていて、こういう命名にはいつもグダグダと悩んでいました。 しかし言語のガイドでこうばっさり言われると、これで良いのだと割りきれて、気持ちが良い。 但し、例に上がっていた次のケースは悩む。

ring.Ring型の新しいインスタンスを作成する関数(Go言語におけるコンストラクタ)は通常、NewRingと名づけられますが、Ringがそのパッケージからエクスポートされている唯一の型で、かつパッケージ名がringであれば、単にNewとします。この関数はパッケージを利用する側からは、ring.Newとなります。

ring.Ring が唯一のエクスポート対象ならそれでいいけれど、ring.Bufferとか新しいエクスポート対象が増えた場合、Newの意味がRingと対応しなくなります。 こういう拡張をするなということなのか、それとも、ring.Bufferが増えた時点でリファクタリングすればいい、ということなのか。

ゲッター・セッター

Goには組み込みのゲッター・セッターは無く、必要なら作りなさい、と。 そして、以下のように規則を設ける。

foo.bar のゲッターは foo.Bar() foo.bar のセッターは foo.SetBar()

getとsetがペアで刷り込まれていると少し違和感ありますが、コードにしてみると確かに自然です。

bar := foo.Bar()
if bar != boo {
    foo.SetBar(boo)
}

でも、Goってオブジェクト指向なの?? 今のところドットシンタックスでアクセスするのはパッケージのメンバーなんだけど…。 基礎の言語仕様を確認せずに、実践から入っている弊害ですかね。

インターフェース

Goにインターフェースが存在することは分かったけれど、

Read、Write、Close、Flush、Stringといったメソッドは、決められた役割とシグネチャを持ちます。

この辺の特別なメソッド名の立場がよくわからない。 そしてそれがインターフェースの場合にのみ言及される理由も。

インターフェース周りは、じっくり確認する。

MixedCaps

Go全般で、複数語で構成される命名では、区切りのアンダースコアは使わず、Capsを使う。

pythonでアンダースコア多用しているので、ちょっと違和感。 まあ慣れですね。

セミコロン

lexer(字句解析プログラム)がソースを調べて、ある単純なルールに基づき自動的にセミコロンを付け加えるので、打ち込むコードにはセミコロンがほとんど不要です。

JavaScriptの自動セミコロン挿入っぽい。 それが混乱をもたらす可能性がある点も。

ただし一行を複数ステートメントに分割するにはセミコロンが必要なので、このようなコードを記述するときはセミコロンを挿入してください。

基本的に、単一行に複数ステートメントをまとめる書き方は避けるべきなんだろう。

if i < f()  // 不正
{           // 不正
    g()
}

このコードが不正と扱われるのは、Go特有か。 でも { は if の後ろについていて欲しいので、全く苦にならない。


次は制御構造。