PHP+Symfony人間が、Go+GinでTodoアプリを作ってみた感想

Go言語の時代が来てますね。マイクロサービス作るとしたらまずGo言語を検討、というくらいの存在感を放っている気もします。

が、私はGo言語を触ったことがありません。このままでは時代に乗り遅れ……私はエンジニアとしてのキャリアを諦め……オレンジ農園で余生を過ごす……。

というわけで。

とりあえずTodoアプリ作るぞ~~~!!!

そして、できたよ~!っていうだけだとこの記事の価値はゼロなので、PHP+Symfonyで普段開発している人間がGo+Ginを触ってみた感想、というところをメインに書きたいと思います。

それぞれの雑な説明(知っている人は読み飛ばしてください)

  • PHP

    • プログラミング言語

    • 「汚いコードでもなんでもとりあえずWebサービスを作れる」という思想に特化

    • 動的型付け言語だが、PHP8ではかなりしっかりセルフで型を定義できるようになってきた

    • でも配列周りはマジで無理だし、型を書かなくても何も言われない

  • Symfony

    • PHPのMVCフレームワーク

    • 大規模なシステムをしっかり作るのに向いている

    • ひとつひとつの機能が単体で動くようになっており、Laravelのような他フレームワークでも一部パーツが使われたりしている

    • PHPは微妙だけどSymfonyは好き

  • Go

    • プログラミング言語

    • とにかくシンプル。ひとつのことを実現するのにひとつくらいの方法しかあえて用意していない(Pythonに似ている)

    • 静的型付け言語なので、絶対に型を定義する必要がある

  • Gin

    • GoのWebフレームワーク

    • 大きいシステムを作るのには向いていなさそうだが、小さい独立したシステムを作る分には十分そう

Todoアプリの要件

  • 画面はとりあえずなくて良い。APIだけあれば(アプリじゃなくない?)

  • 「追加」「編集」「削除」「完了」ができる

  • DBへの保存はとりあえずせずにインメモリで良い

  • エラー処理は……まあ……とりあえずしなくてもいいかな……


そして出来上がったコードがこちらです。

この記事ではコードの説明は行いません。シンプルなのでGitLabでコードを見たら大体わかります。

書いてみて感じた差

型をしっかり定義しないといけないGoの安心感

面倒?いいえ、安心です。

Goは何をするにも型を定義しないといけません。POSTで送られてきたJSONを受け取るタイミングですら、送られてくるJSONの構造体を定義しないといけません(interfaceとかで無理矢理受け取れるのかな?あんまりわかってません)。
そのおかげで、送られてきたJSONから値を取り出す際に迷いがありませんでした。今回使用したVSCodeも補完で後押ししてくれました。

PHPの場合はjson_decodeした際にstdClassかarrayに入って、これはこれでササッと書けるメリットもありましたが、他の人が書いたコードでjsonが引数として渡されているのを見ると「これ中身何!?型は!?」となってしまうので、やはり型は良いな……と思いました。(ちなみに私は型がわからなくなるのが嫌だったので、リクエストされたJSONを「XxxRequestJson」のようなクラス内のフィールドに詰め替えて取り回すようにしたりしていました)

他にも、やはり配列周りの型付けはGoの圧勝ですね。PHPも最近型がしっかりしてきたので、言語仕様としてint[]みたいな感じに定義できたり、ピュアな配列と連想配列を区別できるようになったらいいんですが……。

Goでクラスってどう書くの!?

「構造体がクラスみたいなものだよ~」というのは知識としては知っていたんですが、実際に書いてみるとめちゃくちゃ戸惑いました。

例えば、PHPやJSではクラス内でフィールドをprivate宣言すれば、それは他のファイルからは使用できませんでした。しかし、Goではpackage privatepublicかの2択です。なので、「まあ今回は小さいお試しアプリだし、Controllerと構造体は同じ場所に置いちゃうか~」とやると、構造体の中身にアクセスし放題です。IDとか外部から設定できないようにしたのに台無しです。なので、フォルダとパッケージを分ける必要がありました。
ただ、分ける必要があるおかげで、どのファイル群が関連しているのかというのがわかりやすくなるので、これはこれで良さそうな気もしますね。

ただ、PHPだとコンストラクタをprivateにして、インスタンスを生成する際は専用のstaticなファクトリメソッドを強制することができましたが、Goだと今のところそれはできなさそうでした。意図しない方法で初期化される可能性があるのは注意が必要そうです(ファクトリメソッドを強制する方法あるんでしょうか?)。

基本的に値渡し(ポインタとかアドレスとか久々に気にしたぜ)

*とか&とか書いたの、大学でC言語習ったとき以来かもしれません。

Go言語では基本的に値渡しになります(ですよね?)。なのでPHPのクラスを扱う感覚でいると、あっという間に値渡しの罠に陥ります。

この辺りの感覚はPHPと全然違うので、もし両方書いたりする機会が来たら気を付けないといけませんね。

大規模なWebアプリ作るならSymfonyのほうが良さそう

それはそう。

GinもGoも、そもそもめちゃくちゃでかいシステムを作る用に作られた言語ではないですからね(PHPもですが)。Symfonyは反対にでかいシステムでも堅牢性持って作れるようにというところが目的としてあるはずなので、ここは「それはそう」っていう感じですね。

テストの書き方でちょっと戸惑う

Goには元々テスト用のツールが付属しているので、PHPのようにわざわざPHPUnitを入れたりする必要はありません。

ただ、PHPUnitだとassertEquals(expected, actual)のような専用の検証用メソッドが用意されていると思うんですが、Goだとそれがありません。自分でif文を書いて、エラーがあれば自分でt.Error()のようにエラーだよ!!と宣言する必要があります。

Goでは基本的に例外が投げられることはなく、if err != nilみたいな条件分岐を書いていく必要があるらしいですが、ここでも徹底していますね。

で、どっちが書きやすいの?

そんなこと他人に聞くな!!!!自分で書いて確かめろ!!!!!

陳腐な結論になりますが、どちらにも良さはありますね。

PHPはとにかく簡便に書くことができますし、割と他のオブジェクト指向言語に似た感覚で書くことができます。Javaからも割とスルッと入れます。ただ型は少し弱いです。

Goはしっかり型を書かないといけない部分は良いですね。ただ、PHPでいうarray_xx系のメソッドがなかったり、クラスも(構造体という形ではありますが)なかったりと、他のオブジェクト指向言語と比べると多少面食らうところはあります。そこを受け入れられるか次第ですかね。

ちなみに、両方触った上で、今私が一番好きな言語はやっぱりTypeScriptです。型と書きやすさの両立ができているところがやっぱりいいですね……。クラス周りはまだちょっとクセがありますけど……。

結論

TypeScriptいいよね

この記事が気に入ったらサポートをしてみませんか?