datsukan blog
🦺

Goでフィールドに安全にアクセスする

やりたいこと

Goでフィールドにアクセスする際、nilの構造体のオブジェクトに対してフィールドを参照しようとしてにるぽ(ぬるぽ)になることは結構やりがちです。
なので多くの場合は参照前に明示的にnilチェックをすると思いますが、頻繁にアクセスするフィールドなどは取得メソッドを挟むようにすることで事故率を下げられるかもしれません。

サンプル

TeamのオブジェクトをUserのフィールドで、UserのオブジェクトをCommentのフィールドで持つ形になっています。

type Team struct {
	ID string
	Name string
}

type User struct {
	ID string
	Name string
	Email string
	Team *Team
}

type Comment struct {
  ID string
  text string
  User *User
}

取得用のメソッド

func (u *User) SafeTeam() *Team {
	if u == nil {
		return nil
	}
	return u.Team
}

func (u *User) SafeTeamID() (*Team, bool) {
	if u == nil {
		return nil, false
	}
	return u.Team, true
}

func (u *User) TeamWithResult() (*Team, bool) {
	if u == nil {
		return nil, false
	}
	return u.Team, true
}

func (c *Comment) Team() *Team {
  if c == nil || c.User == nil {
    return nil
  }
  return c.User.Team
}

呼び出した例

func hoge(u *User) error {
  if t := u.SafeTeam(); t == nil {
    return errors.New("could not get team")
  }

  fmt.Println(u.SafeTeamID())

  if t, ok := u.TeamWithResult(); !ok {
    return errors.New("could not get team")
  }
}

func fugo(c *Comment) error {
  t := c.Team()
  if t == nil {
    return errors.New("could not get team")
  }
}

まとめ

今回のコードはシンプルですし、一人で開発している分には事前にnilチェック入れればいいように思えるかもしれません。
ただ、大人数での開発や長期間に渡る保守・追加開発を考慮すると、こういった安全装置がじわじわと効いてくることはあると思います。
もっと良いやり方があればコメントなどで教えていただけると嬉しいです。

コメント
 
URLをコピーしました
Profile picture
datsukan

24歳。埼玉県在住。東京都のSaaS企業でバックエンドエンジニアとして勤務しています。

© 2022 datsukan