2025-06-18
良いコードは読みやすいコードである。そしてGoでは、その読みやすさは「優れた命名」から始まります。Goが「シンプルさ」と「明瞭さ」を重視する言語であることは広く知られていますが、その思想は命名規則にも色濃く反映されています。Javaの冗長な命名文化とは対照的に、Goは文脈を活用した簡潔で意味のある命名を推奨します。
この記事では、Goの公式ドキュメントでも推奨されている、パッケージ、変数、関数、インターフェースなどの命名に関するベストプラクティスを、具体的な例と共に解説していきます。これらの規則をマスターすることで、より「イディオマティックなGo(Goらしい作法)」を実践できるようになるでしょう。
ここで紹介するプラクティスの多くは、Goの公式ドキュメントEffective Goに基づいています。
Goにおけるパッケージ名は、そのパッケージの機能を端的に表現する重要な要素です。
_
)やキャメルケースは使わないgo1// NG例 2 3package http_utils // スネークケースはNG 4package httpClient // キャメルケースはNG 5 6// OK例(標準ライブラリの例) 7 8package http 9package user 10package context
注意:
- Go 1.16以降、
ioutil
パッケージは非推奨となり、主な関数はio
やos
パッケージに移管されています。新規開発ではio.ReadAll
などを使用してください。過去資産でioutil.ReadAll
等が使われている場合は、io.ReadAll
に置き換えることを推奨します。古いコードをメンテナンスする際はこの点にご注意ください。- 上記は標準ライブラリの命名例です。自作パッケージで標準ライブラリと同名(
context
、http
など)を使用すると、importの際に衝突が起こる可能性があります。自作パッケージでは用途に応じて衝突を避ける命名を検討してください。
インポートした際にhttp.Client
のように使われるため、パッケージ名自体が名前空間として機能します。http.HTTPClient
のような冗長な繰り返し(スタッター)を避ける設計思想がGoには根付いています。パッケージ名は短く保つことで、利用する側のコードがより読みやすくなります。
注意:
util
やcommon
といった曖昧すぎる名前は避けましょう。パッケージの具体的な機能を表現する名前を選ぶことで、コードの意図がより明確になります。
Goでは、変数のスコープの広さによって適切な名前の長さが決まります。
i
、err
、req
、resp
)snake_case
は非推奨)注意: Go公式では「mixedCaps」という用語を使用しますが、一般的には「camelCase」として知られています。
Goの最重要ルールの一つが、先頭が大文字なら公開(Exported)、小文字なら非公開(Unexported)という規則です。これがアクセス修飾子の代わりとなります。
go1// 公開される変数・関数 (他パッケージからアクセス可能) 2 3var MaxConnections = 100 4func ProcessRequest() {} 5 6// 非公開の変数・関数 (同一パッケージ内からのみアクセス可能) 7 8var maxRetries = 3 9func validateInput() {}
go1// 短いスコープ:簡潔な名前 2 3for i, user := range users { 4 if err := processUser(user); err != nil { 5 return fmt.Errorf("failed to process user %d: %w", i, err) 6 } 7} 8 9// 長いスコープ:説明的な名前 10 11type UserRepository struct { 12 databaseConnection *sql.DB 13 cacheClient *redis.Client 14}
注意: コード例では
fmt
、sql
、redis
などのimport文を省略しています。実際のコードでは適切なimport文が必要です。
ALL_CAPS
は使わない多くの言語とは異なり、Goでは定数にALL_CAPS
(スネークケースの大文字)を使用しません。
PascalCase
かcamelCase
を使用するgo1// NG例 2 3const MAX_CONNECTIONS = 100 4 5// OK例 6 7const MaxConnections = 100 // 公開定数 8const defaultTimeout = 30 // 非公開定数
go1type Status int 2 3const ( 4 StatusPending Status = iota // 型名と同じベース名で始める 5 StatusRunning 6 StatusCompleted 7 StatusFailed 8)
この慣習により、コードの見た目がより統一されます。
Get
プレフィックスは冗長な場合が多いため、付けないのが慣習go1// NG例(単純なフィールドアクセス) 2 3func (u *User) GetName() string { return u.name } 4 5// OK例(単純なフィールドアクセス) 6 7func (u *User) Name() string { return u.name } 8 9// 別のロジックを含む場合は意味のある名前を使用 10 11func (u *User) DisplayName() string { 12 if u.nickname != "" { 13 return u.nickname 14 } 15 return u.name 16} 17 18func (u *User) FullName() string { 19 return u.firstName + " " + u.lastName 20} 21 22// 文脈によってはGetが適切な場合もある 23 24func GetUserData(userID string) (*User, error) {} // 外部リソース取得
注意: 単純なフィールドアクセスでは
Get
プレフィックスを避けますが、外部リソース取得やAPI呼び出しなど、文脈上Get
が自然な場合は使用することもあります。同じパッケージ内でName()
が紛らわしい場合は、DisplayName()
、FullName()
など、より意味のある名前を使用しましょう。Fetch
、Load
、Retrieve
などの動詞がより意味を表す場合もあります。
Goでは、HTTP、URL、JSONなどの頭字語は、型名や関数名などの識別子中で大文字綴りとする慣習があります。
go1// NG例: 頭字語の一部だけ大文字/小文字混在 2 3func parseJson(data []byte) error {} // "Json" の "J" は大文字、残りは小文字 → NG 4func HttpGet(url string) error {} // "Http" の "H" は大文字、残りは小文字 → NG 5 6// OK例: 頭字語をすべて大文字 7 8func parseJSON(data []byte) error {} // 非公開関数 9func HTTPGet(url string) error {} // 公開関数 10func NewAPIClient() *APIClient {} // API も頭字語として扱う
代表的な頭字語例:HTTP
、URL
、JSON
、XML
、API
、ID
、SQL
、CPU
、DB
、TLS
、UUID
など
注意:
- パッケージ名は全て小文字のため
http
、url
と書きますが、型や関数ではHTTP
、URL
とします。- プロジェクト固有の略語を使う場合は、チーム内でリスト化・ルール化し、一貫して運用することを推奨します。
Goのインターフェース命名には独特の慣習があります。
go1// Read()メソッドを持つインターフェース 2 3type Reader interface { 4 Read([]byte) (int, error) 5} 6 7// Write()メソッドを持つインターフェース 8 9type Writer interface { 10 Write([]byte) (int, error) 11} 12 13// Goの標準ライブラリで最も有名な例の一つ 14// String()メソッドを持つインターフェース 15 16type Stringer interface { 17 String() string 18}
この命名規則は、標準ライブラリのfmt.Stringer
など、至る所で見られます。
複数のメソッドを持つ場合は、機能を表す名詞やInterface
を名称に含めるパターンを用います。
go1// 複数メソッドを持つインターフェース 2 3type Handler interface { 4 ServeHTTP(ResponseWriter, *Request) 5} 6 7// sortパッケージの例:何のインターフェースかが明確 8 9type Interface interface { 10 Len() int 11 Less(i, j int) bool 12 Swap(i, j int) 13} 14 15// 機能を表す名詞を使用 16 17type Database interface { 18 Query(query string, args ...interface{}) (*Rows, error) 19 Exec(query string, args ...interface{}) (Result, error) 20 Close() error 21} 22 23// 自作パッケージでは具体的な名前を推奨 24 25type UserInterface interface { 26 GetID() int 27 GetName() string 28 IsActive() bool 29}
注意: 標準ライブラリの
sort.Interface
のように、パッケージ内では単にInterface
という名前でも文脈から意味が明確ですが、自作パッケージではUserInterface
、PaymentInterface
など、何のインターフェースかが分かる名前を使用することを推奨します。
Goの命名が他の言語と比べて短い理由には、深い思想的背景があります。Goでは、変数が宣言された場所と使われる場所の「距離」が短い場合、短い名前(例:i
, err
, req
)の方が、冗長な名前よりもノイズが少なく、コードの主要なロジックを追いやすいという考え方があります。
go1// forループ内の 'i' が 'index' であることは文脈から明らか 2 3for i := 0; i < len(users); i++ { 4 // ... 5}
また、Goツールチェーン(gofmt
、goimports
)により自動で整形されるため、簡潔な命名はgofmt
後の可読性も向上させます。短い関数名は視線移動コストを下げ、チーム開発においてはレビューコストの低減にも寄与します。
ただし、Goではあえて短くしすぎない(スコープが広い場合は説明的名前を使う)バランスが重要です。短すぎて意味が不明になることも、長すぎてノイズになることも避け、コンテキストを効果的に利用することで、適切な長さの名前を選択できるようになります。
Goにおける良い命名とは「明瞭さ、簡潔さ、そして文脈の活用」です。これらの命名規則をマスターすることは、単なるルールの遵守ではなく、読みやすく保守性の高いコードを書くためのプロフェッショナルな習慣です。
良い命名は、6か月後の自分がコードを読み返したときの理解を助け、チーム開発を円滑にします。これらは、プロジェクトの成功に直結する重要なスキルなのです。
私たちGoForceは、このようなイディオマティックなGoを書きこなす、プロ意識の高いエンジニアを高く評価しています。あなたのその「綺麗なコードを書く力」を、次の挑戦的なフリーランス案件で活かしませんか。ぜひ一度、私たちにご相談ください。
最適なGo案件を今すぐチェック!