概要
この記事は、2018年のGothamGoのMat Ryerさんのtalkの動画のサマリーになります
GothamGo 2018 - Things in Go I Never Use by Mat Ryer
この動画では、主に、「Goで可読性の高いコードを書く上で使わない文法」について具体的なポイントを挙げて話しているので、それらのまとめとなります。
まとめ
elseはできるだけ使わない
Goでは、Happy Path(正常系)は左端に寄せて(関数内でインデントをしない)で書いて、エラーハンドリングなどのその他のケースのみインデントするという書き方が好ましいとされている。
なので、異常系のみ都度if
節で処理して、正常系はネストの中には入れないようにする。
そうすると、必然的にelseを使わないといけないケースは限られてくる。
動画内でも紹介されているリンク: Code: Align the happy path to the left edge
// bad
if ok {
err := something()
if err != nil {
return errors.Wrap(err, "something")
}
// do more great things
} else {
return errors.New("not ok")
}
// good
if !ok {
return errors.New("not ok")
}
err := something()
if err != nil {
return errors.Wrap(err, "something")
}
// do more great things
labelは使わない
処理の流れが把握しづらくなるため。
gotoは使わない
処理の流れが把握しづらくなるため。
arrayは使わない
slice
を使えばメモリの細かい挙動を考えずに複数のarrayを内部で作ってくれるので、厳密なメモリ最適化をしたい場合でもなければ、slice
で事足りる。
newは使わない
&type{}
みたいに直接オブジェクトを初期化すれば事足りる。
panicはそのままでは使わない
error
を使う。
ただし、下記のように、既存のpanicをカスタマイズして使う場合は有意義なものとなる。
func (t *Greeter) Greet1(name string) {
// Speakerがnilの場合に、下記の既存のpanicが起きる
// "invalid memory address or nil pointer dereference"
return t.Speaker.Speak("hello" + name)
}
func (t *Greeter) Greet2(name string) {
if t.Speaker == nil {
panic("greeter: cannot call Greet with nil Speaker")
}
return t.Speaker.Speak("hello" + name)
}
Structを初期化するときはfield名も明示する
それぞれの値がなにを表すのかわかりづらいため。
// bad
// どっちが緯度でどっちが経度かわからない
pos := &Position{40.712772, -74.006058}
// good
pos := &Position{
latitude: 40.712772,
longitude: -74.006058,
}
冗長なレシーバ付き関数の呼び出しはしない
type Greeter struct {
Format string
}
func (g Greeter) Greet(name string) { fmt.Println("hello", name) }
func main() {
g := Greeter{}
Greeter.Greet(g, "Mat") // bad
g.Greet("Mat") // good
}
最後に
さっと振り返れる用にまとめとして書いたもののこの動画自体そこまで長くなく、また前半では「そもそもGoにおける良いコードとは」という話もしており、冗談も交えつつで話も面白いので、もし英語に抵抗がなければ動画を全部実際に見てみることをおすすめします。