🗻

Goの命名やコーディングの方針について検討する

2023/01/15に公開

はじめに

Goでは先人たちにより、下記に挙げるような資料が公開されています。コミュニティの活動に大いに感謝するとともに、参考にさせていただきます。

この記事では、それらの資料から個人的に興味を持った内容をピックアップし、Goを書くときにどのような命名やコーディングしていくかについて検討します。

また、資料で挙げられているルールについても、それを採用するかどうかは、開発チーム内で議論し、合意を取るようにするのが良いかなと思います。

Go Style

https://google.github.io/styleguide/go/

Effective Go

https://go.dev/doc/effective_go

uber-go/guide

https://github.com/uber-go/guide


Goを書くときの考え方

Goを書くときの考え方については、このドキュメントでは5つの原則が挙げられています。
https://google.github.io/styleguide/go/guide#style-principles

  1. Clarity
  2. Simplicity
  3. Concision
  4. Maintainability
  5. Consistency

例えばClarityでは「より説明的な変数名を用いること」、Simplicityでは「コードを全て記憶できていることを前提としないこと」など、Goを書く上での考え方がまとめられています。
変数名やパッケージ名を決める際、またはロジック等を書く際には、これらの考え方を知っておくと、Goらしい書き方をするのに役立つと思われます。


パッケージ名

https://google.github.io/styleguide/go/decisions#package-names

Go package names should be short and contain only lowercase letters. A package name composed of multiple words should be left unbroken in all lowercase.

Goのパッケージ名には、短い名前で、かつ小文字のみを使うようにします。

Avoid selecting package names that are likely to be shadowed by commonly used local variable names. For example, usercount is a better package name than count, since count is a commonly used variable name.

一方でパッケージ名は、一般的によく使われるローカル変数と名前が被らないように、注意する必要があります。

https://go.dev/doc/effective_go#package-names

Another convention is that the package name is the base name of its source directory; the package in src/encoding/base64 is imported as "encoding/base64" but has name base64, not encoding_base64 and not encodingBase64.

上記の例のように、base64パッケージは、encoding_base64や、encodingBase64といった命名ではなく、encoding/base64が良いとされます。


変数名

https://google.github.io/styleguide/go/decisions#variable-names

Omit types and type-like words from most variable names.
For a number, userCount is a better name than numUsers or usersInt.
For a slice, users is a better name than userSlice.
t is acceptable to include a type-like qualifier if there are two versions of a value in scope, for example you might have an input stored in ageString and use age for the parsed value.

変数名には、型や型のような単語を入れないようにします。
例にもあるように、usersSliceよりもusersといった名前を使うようにします。


ゲッター

https://go.dev/doc/effective_go#Getters
https://google.github.io/styleguide/go/decisions#getters

ゲッターのプレフィックスにGetgetを使う慣習はないため、必要なければプレフィックスはつけないようにします。


Initialisms

https://google.github.io/styleguide/go/decisions#initialisms

Words in names that are initialisms or acronyms (e.g., URL and NATO) should have the same case. URL should appear as URL or url (as in urlPony, or URLPony), never as Url. This also applies to ID when it is short for “identifier”; write appID instead of appId.

頭文字から構成される単語、例えばURLやID等はケースを統一する。URLの例では、urlURLを使うようにして、Urlとは書かないようにする。

In names with an initialism containing a lowercase letter (e.g. DDoS, iOS, gRPC), the initialism should appear as it would in standard prose, unless you need to change the first letter for the sake of exportedness. In these cases, the entire initialism should be the same case (e.g. ddos, IOS, GRPC).

iOSやgRPCのような小文字を含む単語には注意する。エクスポートする場合は、先頭の文字を大文字にする必要があるが、そうでない場合は元のケースを使う。

例)

  • iOS => エクスポートする場合はIOS。エクスポートしない場合はiOSとする。
  • gRPC => エクスポートする場合はGRPC。エクスポートしない場合はgRPCとする。

インタフェースに準拠しているかどうか確認する方法

https://github.com/uber-go/guide/blob/master/style.md#verify-interface-compliance

Verify interface compliance at compile time where appropriate.

コンパイル時にインタフェースに準拠しているかどうかを確認する方法として、つぎのような手法があります。

type MyHandler struct {}

var _ http.Handler = (*MyHandler)(nil) // (1)

func (h *MyHandler) ServeHTTP(
  w http.ResponseWriter,
  r *http.Request,
) {}

このコードでは、(1)でnet/httpパッケージのHandlerインタフェースの変数を_と定義し、nilを*MyHandlerにキャストして初期化しています。
(1)の処理はMyHandlernet/httpパッケージのHandlerインタフェースを満たさなくなった場合、コンパイルエラーとなります。

以下、随時更新

今後も気になったところをピックアップして更新する予定です。

Discussion