Go言語入門:効果的なGo -Names:Getters-

スポンサーリンク
Go言語入門:効果的なGo -Names:Getters- ノウハウ
Go言語入門:効果的なGo -Names:Getters-
この記事は約7分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

本日は、Go言語を効果的に使うためのガイドラインについて解説しています。

スポンサーリンク

背景

Go言語を学び始めて、より良いコードを書きたいと思い、Go言語の公式ドキュメント「Effective Go」を知りました。これは、いわば「Goらしいコードの書き方指南書」になります。単に動くコードではなく、効率的で保守性の高いコードを書くためのベストプラクティスが詰まっているので、これを読んだ時の内容を備忘として残しました。

Go言語の命名規則(Names)

命名の重要性

Go言語において、名前は他の言語と同様に重要です。名前は単なる識別子以上の意味を持ち、セマンティック(意味論的)な効果も持ちます。パッケージ外部からの可視性は、名前の最初の文字が大文字かどうかで決まります。そのため、Go プログラムにおける命名規則について時間をかけて議論する価値があります。

Go言語のGetterとSetter

基本方針

Go言語はGetterとSetterを自動的にサポートしていません。GetterとSetterを自分で提供することに問題はなく、多くの場合適切ですが、Getterの名前に Get を付けることは慣用的でもなく、必要でもありません

Getterの命名

フィールド名が owner(小文字、非エクスポート)の場合:

type MyStruct struct {
    owner string  // 小文字、非エクスポート
}

// ✅ 正しい命名
func (m *MyStruct) Owner() string {
    return m.owner
}

// ❌ 慣用的でない命名
func (m *MyStruct) GetOwner() string {
    return m.owner
}

Getterメソッドは Owner(大文字、エクスポート)と呼ぶべきで、GetOwner ではありません。

命名の理由

エクスポート用の大文字名の使用により、フィールドとメソッドを区別するためのフック(仕組み)が提供されます。

  • owner → プライベートフィールド(小文字)
  • Owner() → パブリックGetterメソッド(大文字)

Setterの命名

Setter関数が必要な場合は、おそらく SetOwner と呼ばれるでしょう。

func (m *MyStruct) SetOwner(newOwner string) {
    m.owner = newOwner
}

実践例

両方の名前は実際の使用において読みやすくなります:

// 実際の使用例
owner := obj.Owner()        // Getterの使用
if owner != user {
    obj.SetOwner(user)      // Setterの使用
}

なぜ “Get” を避けるのか

  1. 簡潔性: obj.Owner()obj.GetOwner() よりも短く、タイプしやすい
  2. 自然な読み方: owner := obj.Owner() は英語として自然に読める
  3. Go らしさ: Go言語の「シンプルで実用的」な哲学に合致

エクスポート規則の活用

Go言語の大文字/小文字によるエクスポート規則を巧妙に活用:

type Person struct {
    name string      // プライベート(小文字)
    age  int        // プライベート(小文字)
}

// パブリックメソッド(大文字で開始)
func (p *Person) Name() string { return p.name }
func (p *Person) Age() int { return p.age }
func (p *Person) SetName(n string) { p.name = n }
func (p *Person) SetAge(a int) { p.age = a }

Java スタイル(避けるべき)

// ❌ Javaライクな命名(Go では慣用的でない)
func (p *Person) GetName() string { return p.name }
func (p *Person) SetName(n string) { p.name = n }

Go スタイル(推奨)

// ✅ Go らしい命名
func (p *Person) Name() string { return p.name }
func (p *Person) SetName(n string) { p.name = n }

実装例

package main

import "fmt"

type BankAccount struct {
    balance float64  // プライベートフィールド
    owner   string   // プライベートフィールド
}

// Getter: "Get" を付けない
func (b *BankAccount) Balance() float64 {
    return b.balance
}

func (b *BankAccount) Owner() string {
    return b.owner
}

// Setter: "Set" を付ける
func (b *BankAccount) SetOwner(newOwner string) {
    b.owner = newOwner
}

func (b *BankAccount) Deposit(amount float64) {
    b.balance += amount
}

func main() {
    account := &BankAccount{balance: 100.0, owner: "Alice"}
    
    // 自然な読み方
    fmt.Printf("Owner: %s, Balance: %.2f\n", 
               account.Owner(), account.Balance())
    
    // Setterの使用
    if account.Owner() != "Bob" {
        account.SetOwner("Bob")
    }
    
    fmt.Printf("New Owner: %s\n", account.Owner())
}

まとめ

  • Getterには Get プレフィックスを付けない
  • フィールド名を大文字にしたものをGetterメソッド名にする
  • Setterには Set プレフィックスを付ける
  • Go言語のエクスポート規則を活用してフィールドとメソッドを区別
  • 簡潔で自然に読める命名を心がける

ポイント

  1. “Get”プレフィックスは不要: 他の多くの言語(Java、C#など)とは異なり、GoではGetOwner()ではなくOwner()とします。
  2. 大文字/小文字の巧妙な活用:
    • owner(小文字)→ プライベートフィールド
    • Owner()(大文字)→ パブリックGetterメソッド
    この仕組みにより、同じ名前の概念でもスコープを明確に区別できます。
  3. 自然な読みやすさ: owner := obj.Owner()は英語として自然で、obj.GetOwner()よりも簡潔です。
  4. 一貫性のあるパターン: SetterとGetterで一貫したパターンを使用します。
    • Getter: Owner()
    • Setter: SetOwner()

Go言語の設計哲学の反映

この命名規則は、Go言語の以下の設計哲学を体現しています:

  • 簡潔性: 不要な冗長性を避ける
  • 実用性: 実際のコードで読みやすく、タイプしやすい
  • 一貫性: 言語の既存の機能(エクスポート規則)と調和する

このような細かい命名規則の理解と適用が、「Go言語らしい」コードを書くために重要です。

おわりに 

本日は、Go言語を効果的に使うためのガイドラインについて解説しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました