経験が浅いエンジニアが Go の開発チームにスムーズに入っていくために試したこと


# はじめに

わたしは3ヶ月前(2019年の9月)にGoの開発現場に転職した、まだまだ駆け出しGopherです。

エンジニアになったのは2018年の6月のため、Goの現場に転職するまで1年と3ヶ月ほどでした。

経験が浅いため、苦労することが多くありました。

ありがたいことにGoに関わる知識はインターネットに無数に存在します。

しかし、Goの開発現場に経験が浅いエンジニアがスムーズに入って行くためのGoのTipsはそこまで多くはないと感じました。

Goは非常にシンプルな言語で習得が比較的容易(主観ではないと思う。。。)ですので

わたしのように経験の浅いエンジニアでも携わる機会が今後増えてくると思います。

そのような人の灯台となるような記事になればと思っています。

## 注意事項

- 初投稿です。読みにくさの感じる文章かもしれません。申し訳ない！  その怒りはいいねボタンにぶつけてください。

- 「おれはこうした！」「わたしはこうした！」「君は間違っている！」等のご意見大歓迎です。

- わたしはAPIの開発チームに所属していますのでAPI開発に偏ったものになるかと思います。

- 他にも色々と書くべき事があると思いましたが、Goに関わる項目のみを選びました。

# Goを駆け出しのエンジニアなりに学習する

たいした経験もないのにおこがましいと思いますが、経験が浅いエンジニアとしてGoをどのように学習していくか、迷う部分がありましたので、参考になればと思います。

わたしは下記の順でGoを学んでいきました。

- [A Tour of Go](https://go-tour-jp.appspot.com) を挫折
- [スターティングGo言語](https://www.amazon.co.jp/%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0Go%E8%A8%80%E8%AA%9E-CodeZine-BOOKS-%E6%9D%BE%E5%B0%BE-%E6%84%9B%E8%B3%80/dp/4798142417) でポインタ、インターフェイスの章以外を学ぶ
- [苦しんで覚えるＣ言語](https://9cguide.appspot.com/15-01.html) でポインタを理解
- [Gopher道場](https://gopherdojo.connpass.com/event/142892/) でインターフェイスおよびその他詳細を学習

`スターティングGo言語`は非常にわかりやすく、経験の浅いエンジニアにはおすすめです。

任意のLLを一通り学んだ方ならかなりスムーズにGoを学習していけると思います。

しかし、わたしの場合、`スターティングGo言語`ではポインタ、インターフェイスだけはさっぱり理解できませんでした。

わたし自身の理解力の問題ですが、そこで`苦しんで覚えるC言語`です！

そんな理解力のわたしでも`苦しんで覚えるＣ言語`によってあれよあれよポインタを理解できました。

「Goの勉強をしているのに、C言語って。。。」と思うことなかれです。

C言語はGoの親の言語のようなものなので、絶対に無駄にはなりません。

`スターティングGo言語`で、もやっとレベルの理解が雲が晴れるように腑に落ちることが何度もありました。

そして、最もおすすめしたいのは`Gopher道場`の参加です。

インターフェイスに対して参加時点でもふわっとした理解しかしていませんでしたが、

各言語仕様のユースケースと共に学習できるため、インターフェイスだけでなく、その他エッセンスにおいても理解が進みました。

読めないコードが劇的に無くなります。自身を持ってコードを書けるようになります。

Go の基本的な文法を理解したというレベルから飛躍的にレベルを上げてくれます。本当に参加してよかった。

わたしの場合、`Gopher道場`を終える頃にはGoの理解不足によって、開発に支障をきたすということはほとんど無くなりました。

参考になれば幸いです。

# アーキテクチャを理解する

どんな言語を開発で使っていようが、アーキテクチャの理解は欠かせませんが、わたしが一番苦労したのはこのポイントでした。

GoではRuby on Railsのようなボイラープレートを作成するフレームワークを使用しているプロジェクトは稀です。

そのため、プロジェクトごとにオリジナルのアーキテクチャを採用しています。

これが、経験の浅いわたしのようなエンジニアにはハードルになると思います。（つらかった。。。）

アーキテクチャを理解していないと、作りたいものがわかっても、どこにコードを書けば良いのかわからず、一向にコードが書けません。

おすすめのアーキテクチャの理解法は

- チームのアーキテクチャのもととなるアーキテクチャが何か知る
- もととなるアーキテクチャで小さなプログラムを作ってみる
- 実際のアーキテクチャと比較し、何が異なるのか理解する
- プロダクト初期のコミットを見て、小さなプロダクトの段階のアーキテクチャを見てみる

です。

わたしのチームではクリーンアーキテクチャを採用しており、それまで、MVCのアーキテクチャしか触れたことがありませんでした。

なので、まず[The Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)を読みました。

しかし、このブログには具体的なコードが一切ないので理解があまり進みませんでした。

そこで、下記のような、具体化した記事やコードをを片っ端から読みました。

- [Trying Clean Architecture on Golang](https://medium.com/hackernoon/golang-clean-archithecture-efd6d7c43047)
- [Goでクリーンアーキテクチャを試す](https://postd.cc/golang-clean-archithecture/)
- [Goで書くClean Architecture API](https://qiita.com/muroon/items/8add8da911341312176d)
- [bxcodec/go-clean-arch](https://github.com/bxcodec/go-clean-arch)
- [muroon/memo_sample](https://github.com/muroon/memo_sample)
- [go-api-boilerplate](https://github.com/bmf-san/go-clean-architecture-web-application-boilerplate)

これらをもとに 自分で作ってみると、かなり理解が進みます。

実際にわたしが作った[APIのサンプル](https://github.com/NasSilverBullet/twitter-clone-api)です。

しかし、チームのアーキテクチャを理解するにはこれだけでは不十分でした。必ず違いが存在します。

なので、その違いを正確に把握するために、アーキテクチャが形になってきた頃のコミット履歴を探し、

それと自分の作ったコードを見比べました。これが、最もアーキテクチャの理解につながったと思います。

# Goに入ってはGoに従え

もしもPRにGoのコーディングスタイルレベルの修正箇所が複数あるとどうなるでしょうか。

きっと、ビジネスロジックに関わる致命的なバグがあった場合にそれを見逃す可能性は大きくなります。

単純に可読性の低下や、リファクタリングの難易度も上がるでしょう。

それを解消するためにはコーディングスタイルをぜひ学びましょう。

コーディングスタイルを理解することで、自分以外の誰かが書いたコードも読みやすくなります。

何よりもGoを書くのが楽しくなります。そして早くなります。

コーディングスタイルを学ぶには下記が代表的な資料かと思います。

- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
- [Uber Go Style Guide](https://github.com/uber-go/guide/blob/master/style.md)

これらに目を通し、なじませましょう。

著名なOSSのコードを読み、学ぶのも良いかと思います。

プロジェクトの構成は下記が参考になると思います。

- [Standard Go Project Layout](https://github.com/golang-standards/project-layout)

これらを学ぶことで、書き方に迷ってしまい、手が止まるということは激減しました。

# Goに入ってはGoに従え より 郷に入っては郷に従え の時もある

上で紹介したコーディングスタイルを学ぶことでGoにはGoの読みすいコードがあり、独特の慣習があることがわかります。

しかし、チームのコードにはそれらにそぐわないコードというのは必ず存在します。

それらを無視して、Goの慣習だけに従ったらどうなるでしょうか。

コードベース全体として、統一性のないコードが生まれてしまい、それは可読性の低下につながります。

具体例で考えてみましょう。

例えば、プロダクト内に`VIPユーザー`という役割があるとします。

そして下記のようなコードがあるとします。

```go
func (vipUser *VIPUser) GetID() int64 {
	return vipUser.ID
}
```

スコープが小さい場合や、それを表すことが明確な場合は 短い変数名が好まれるGoでは下記のようなコードを書きたくなるかもしれません。

```go
func (vu *VIPUser) GetStatus() bool {
	return vu.Status
}
```

しかし

`VIPユーザー` を表す変数がコードベース内でバラバラになってしまったらどうでしょうか。

可読性は下がる上に、新しいチームの仲間はどちらに統一すべきか分からなくなります。

上記とは状況が異なりますが、同じような失敗をわたし自身がしてしまい、コードを汚くしてしまいました。

こういう場合はコードベース全体のリファクタリングを行ったPRを出すのが良いと思います。

# まとめ

あまり、Goについて言及されるときに論点とならない部分ですが、経験が浅いエンジニアとして苦労した部分をまとめてみました。

ぜひとも、わたしのようなエンジニアの方の参考になればと思います。