見出し画像

ほぼほぼ未経験のGoをいきなり内定者インターンで書いた話

はじめに

みなさんこんにちは。マグロ(X(Twitter), GitHub)です。
ピカピカの24新卒ですが、最近そのピカピカも薄れてきている感覚がします。
くふうAIスタジオのサーバーサイドエンジニアとして、現在トクバイに携わっています。

現在はトクバイですが、内定者インターンでは家計簿アプリZaimのサーバーサイドとして携わりました。
今回はその時のお話をしたいと思います。

Goを書くきっかけ

ZaimではほとんどがPHPとRubyで構成されています。
初めは既存機能の改修を進めていたのですが、ある日

「マグロくんてGo書いたことある?」

と聞かれました。
それに対して

「まあ触り程度には(文法ぐらいしか分からんけど)」

のような回答をしたところ、

「よし、Go書いてみようか!」

ということで書くことになりました。

ZaimではPHPで実装された部分をGoにリプレイスする作業を進めており、なんとそこにアサインされてしまいました。
不安だけど、Goを実践を通して学ぶチャンスだと思い、快諾しました。

当時の状況

  • Python(FastAPIでの開発経験)

  • TypeScript(ReactとNext.jsでのページ作成)

  • Go(基礎的な言語仕様)

  • 実務未経験(Zaimが初の就業型インターン)

リプレイスの流れ

一つのバッチにつき以下のようなディレクトリの構成が組まれていました。

├── example
│   ├── internal
│   │   ├── entity.go
│   │   ├── repository.go
│   │   └── repository_test.go
│   ├── cmd.go
│   ├── cmd_test.go
│   └── mock_repository_test.go

cmd.goにバッチのメイン処理を記述します。
全ての処理を書くわけではなく、データベースの操作はrepository.go、データベースから受け取った構造体の宣言をentity.goで行います。

バッチ処理を書いた後はテストコードを書きます。
repository_test.goは実際にローカルのデータベースを操作して検証を行います。
独自のDBフィクスチャが実装されていて、テストによるローカルDBの影響を考えずにテストを実行できます。
cmd_test.goではrepository.goの部分をモックにしたmock_repository_test.goを使用して結合テストを行います。
モックは自動生成したものを使用します。

コードレビューやステージングでの動作確認後、本番に置き換えます。

簡単ですが、以上がリプレイスの流れになります。

キャッチアップ

Goで設計を知る

Goには「一つディレクトリ内で一つのパッケージとして扱う」という独特の仕様があります。
このせいで他言語とインポートのやり方が異なり、挫折した経験があります。

上記の点をあまり意識せず、始めは見様見真似でリプレイスを進めていました。
しかし意識してみると、どのようにコードの責務や役割を分けているのかわかって来るようになりました。

  • Goは一つディレクトリ内で一つのパッケージとして扱う。

    • entity.goとrepository.goはファイルが異なるが、internalでインポートできる。

    • DB操作とバッチ本体の役割を分担させるため、internalに配置している。

    • repositoryで単体テストを行い、動作が保証されればcmdの結合テストでDB操作はモック化できる。

というのを読み取ることができました。
ここでGoという言語は、設計が色濃く現れる言語なのだと学びました。

PHPと比較しながらGoを書く

既にPHPで実装されているものをGoに書き換えるので、キャッチアップしやすかったです。

  • PHPでの動きをGoで書くとどうなるのか

  • PHPでできてGoにできないこと、逆にGoでできてPHPでできないことは何か

という点を意識しながら書いていました。

元のコードも最適化されているとは限らず、どうすればパフォーマンスの改善ができるか考える醍醐味もありました。

コードレビュー

コードレビューが一番学びになりました。
以下のような点を学びました。

  • あまりネストを深くしないこと。

    • 認知コストが高くなる原因になるため。

    • elseを使うのは避ける。書かなくても再現できる挙動が多いため。

  • panicを起こしてしまうような実装を避ける。

    • バッチ自体がその時点で止まってしまうため。

    • 空配列へのインデックスアクセスや、正規表現での参照などで結構やりがち。

  • 規模が大きいバッチが多いため、メモリ使用量に気をつける。

    • 使用済みのリソースは必ず解放すること。

    • makeで宣言することで削減させる。

    • 構造体は基本参照渡し。

  • エラーハンドリングでは発生元をラップしてスタックトレースする。

    • エラーの原因調査の際に、発生箇所を特定できるため。

  • テストを書く際、境界値を意識する。

    • 家計簿アプリという性質上、誤りが顕在化しやすくユーザーからの信用の毀損に直結する。

勉強会

実はチーム内でGoの経験者が少なく、知見を深めるため勉強会が行われました。
勉強会の詳細は以下のnoteをご覧ください。

内容はGoでありがちなミス、間違いを例としてどのような最適化を行うのかというものでした。
ただのTipsだけでなく、Goの歴史や思想の説明もあり、実装時に心がけられることが増えました。

インターンで得たこと、変わったこと

メインで書く言語がGoに変わった

個人開発での言語をPythonからGoに乗り換えました。
Pythonではコードの分離が自由すぎて難しいと個人的に悩んでいました。
Goの「一つディレクトリ内で一つのパッケージとして扱う」という仕様が責務を分けやすく、気に入ったので乗り換えました。

自動テストを意識

動作が保証されれば仕様通りに動く確率は非常に高いという、当たり前だけど重要なことを学べました。
現在の業務でもテストを真っ先に意識するようになりました。

まとめ

以上がインターンでGoをキャッチアップした経緯です。就業型のインターンは初めててうまくできるか不安でしたが、挑戦してみて良かったと思います。
Goは独特な仕様が多く、独学では理解しきれなかったのですが、実務を通してカバーできました。
トクバイではGoを書く機会がないのですが、自動テストやパフォーマンスチューニングの経験は今でも業務の役に立っています。
Zaimの開発チームに、この場を借りて感謝の意を表したいと思います
本当にありがとうございました!!!

くふうAIスタジオでは、採用活動を行っています。

当社は「AX で 暮らしに ひらめきを」をビジョンに、2023年7月に設立されました。
(AX=AI eXperience(UI/UX における AI/AX)とAI Transformation(DX におけるAX)の意味を持つ当社が唱えた造語)
くふうカンパニーグループのサービスの企画開発運用を主な事業とし、非エンジニアさえも当たり前にAIを使いこなせるよう、積極的なAI利活用を推進しています。
(サービスの一例:累計DL数1,000万以上の家計簿アプリ「Zaim」、月間利用者数1,600万人のチラシアプリ「トクバイ」等)
AXを活用した未来を一緒に作っていく仲間を募集中です。
ご興味がございましたら、以下からカジュアル面談のお申込みやご応募等お気軽にお問合せください。

いいなと思ったら応援しよう!