Go Conference 2024に参加し、登壇してきました。
登壇しました
Dive into gomockというタイトルで発表しました。2トラックのどちらかで40分トークかな? と思っていたら2部屋ぶち抜きでトークだったのでビビっていました。
発表資料はこちらです。
gomockの内部実装を見て、なぜライブラリの内部実装を見るのがよいことなのか、という話をしました。reflectパッケージが好きなので合間にreflectパッケージの話もしています。つまり主題が3つあるわけですね。
- gomockの内部実装を見よう
- リフレクションを知ろう
- なぜライブラリの内部実装を見るのか知ろう
今回はgomockの実装を掘り下げることで、魔法のように見えるイディオムの裏にある処理を知ろう、という方向性でやりました。今回の発表でgomockの内部実装を全員が完全理解できたかは分かりませんが (理解できていたらすごいと思います)、これをきっかけにライブラリの実装を読むことの楽しさや効能について多くの人に知ってもらえたら幸いです。
ポスト見ました
自分の想像よりもXのポスト (旧Twitterのツイート) が盛り上がっていそうでしたね。いくつかお返事を書いてみています。
Controller/Recorderがtype safeになってほしいのとmockgen速くなってほしい願望がずっとある #gocon
— かるぱねるら (@karupanerura) 2024年6月8日
m.EXPECT().MethodName(arg1, arg2).Return(ret1, ret2)
のうち .MethodName(arg1, arg2)
の部分は、任意の値もしくはMatcherを受け付けられる必要があるので、パッと実現できるかは分からないですね。
.Return(ret1, ret2)
の部分については、mockgenに -typed
というオプションを渡すことで、メソッドの返り値をany型じゃなくて本来の型にすることができます。具体的には Do
DoAndReturn
Return
メソッドに型がつくようになります。
モックするメソッドごとに *gomock.Call
をラップした型をコード生成する、という仕組みで動いているため、代わりに生成されるコードの量は増えることになりますね。
Cond MatcherのStringメソッドどうなってるんだろ #gocon
— furudono (@furudono2) 2024年6月8日
Cond Matcherの String
メソッドが返す値は adheres to a custom condition
という文字列です。つまりカスタム条件であることしか分からない!! こういう場合はWantFormatterを通すほうがテスト失敗時のログが分かりやすくなりそうですね。
gomock 色々便利とは思うけど、現代だとGenericsでもう少し良い感じにできないかなという気はしなくもない #gocon
— mizutani (@m_mizutani) 2024年6月8日
わかる〜うまくシグネチャを設計していくとジェネリックな感じにできるのかも。もしくはそういうライブラリがある?? 誰か知ってたら教えてください。
なんでmatcherとかは独自に型定義してreturnしてるのかわからなかった。
— 鹿 (@mizushika1) 2024年6月8日
あ、interfaceをimplementsした型をそこで定義してるってこと?なんでglobalに定義しないんだろ。
#gocon
推測ですが、struct定義を関数内に閉じ込めることで名前を消費しないようにしているんですかねえ。これぐらいで済むなら自分でもこういう感じで書いて済ませるかも。
gomockのmatchesの実装、コードだけだと伝わらないと認識しているからか、ふんだんにドキュメンテーションのコメントが書かれていて良い #goconhttps://t.co/bCsTOD8cJN
— syumai (@__syumai) 2024年6月8日
発表資料を作っているときはこの観点は抜けていたのですが、確かに!! 難しいことをやるからには相応の解説をコード中にコメントとして残して、なんとかメンテナンス可能にしていこう、という気概を感じますね。
Do 使ったことないんだけど、副作用だけを期待する mock って mock の本来の目的から外れてないか? #gocon
— チェシャ猫@技術書典16 オンライン (@y_taka_23) 2024年6月8日
Do
メソッドが返り値を使わないのは過去の経緯があるようですね。godocにも「下位互換性のために返り値を無視している」ということが書いてあるので、基本的に DoAndReturn
メソッドを使うほうがよさそうです。
おそらく昔は Do
メソッドと Return
メソッドを組み合わせる、という使い方しかできなかったのかも。DoAndReturn
メソッドが追加されたときの様子を見るにそんな感じなのかな?
発表見ました
tenntennさんのイテレータの話は、Goの最新の言語機能を速習できるという感じでした。ジェネリクスを活用してよくあるスライス操作を簡潔に書くためのライブラリは既にありますが、どうしてもスライスを経由するので実行効率が気になるところでしたが、イテレータを組み合わせることで効率と書きやすさ・表現力を両立できることに期待したいですね。これは自分でもイテレータを駆使してなにかを作ってみることで知識が定着するのでしょう。
Iwaminさんのフィーチャーフラグを自動計装する話は、なかなか興味深い切り口でおもしろかったです。フィーチャーフラグとその運用には昔から今まで悩まされていたところなので、簡単に入れて外せるようになると夢っぽい。if文を起点とするほかにbuild tagsでファイルごと差し替える、みたいなアプローチもあるのかな?
karamaruさんの "Fixing For Loops in Go 1.22" を深く掘り下げた話は、よくあるイディオムとその修正というだけにとどまらず本当に深く掘り下げられていておもしろかったです。発表資料を拝見した感じだと、他にもいろいろなトピックや取り組みの話題がありそうで、枠が20分しかないのがもったいないぐらいでした。fmt.Println
関数で変数をエスケープさせられる例がよかったです。
ありがとうございました
参加者のみなさま、運営のみなさま、現地でお話ししたみなさま、ありがとうございました。40分トークで2部屋ぶち抜き、ライブラリの実装を読んでいく、というトークを聞いてもらうという感じで緊張感がありましたが、おもしろかったと言っていただけたのでよかったです。
次回のGo Conferenceでも何か発表したいですね。自分で作ったものの話とか、もうちょっと別のテーマで話せるといいかも。あるいは会社の人に登壇してもらうとか……。