私が歌川です

@utgwkk が書いている

YAPC::Hiroshima 2024に参加した #yapcjapan

参加しました。前日祭や懇親会・アフターイベント・YAYAPCも含めて全て出席していました。

yapcjapan.org

どの発表もおもしろく、全てについて詳細に取り上げるには紙面 (紙じゃなくない??) が足りないので、ピックアップ形式にさせていただきます。

とほほのWWW入門

キーノートが本当によかったです。ちょうど生まれたぐらいの頃*1からずっとインターネットで発信を続けられていて、まさにアウトプットの祖といえるでしょう。好きだから継続しているという話だったけど、しかしあの情熱は「好き」だけでは説明がつかないのでは??

若者にじゃんじゃん来てほしい

よく言ってるのですが、YAPCは学生支援制度が整っていて、学生でも交通宿泊費を気にせずに参加できるようになっているんですよね*2。YAPC::Japan運営ブログの方にも、学生支援制度を活用してくれ!! という趣旨のブログ記事を寄稿させていただいたことがあります*3

学生支援制度で参加された学生の方 (名前を思い出せず恐縮です) とも少しお話ししたのですが、YAPCは名前にPerlを冠するカンファレンスだけど、Perlは実は書いたことなくても気軽に参加できます。「Perlコミュニティのカンファレンス」ぐらいに思ってもらうのがちょうどよさそう。今回は応募多数で抽選になったようですが*4、学生支援制度で参加された方にはぜひこの制度のことを知り合いにも広めてもらいたいですね。あとはYAPCの参加記を書いてほしい!!

学生の頃から、身の回りに id:Pasta-Kid:nna774 のような人がいたのでYAPCの学生支援制度に素早くリーチできていたけど、そうじゃない学生の方はどうやってこの制度を知ったのか、誰かこっそり教えてください。

廊下とか懇親会とか

廊下や懇親会で、久しぶりに会う人・初めましての人・インターネットでは見たことがあるという人といろいろ会話できてよかったです。オンラインカンファレンスの懇親会会場で発話するのってめちゃくちゃ緊張感があると思っていて、懇親会でおもしろそうな話をしている人のところにフラッと寄ってみたり、とほほさんに話しかけにいったり、実装の議論をしたりなど、これはオフラインじゃないと現状ここまでやるのは無理だよな〜と思っている次第です。

しかし毎日遅くまで飲んでいたので満身創痍!! こういう暮らしがいつまでできるかな??

熱量を浴びる

他のカンファレンスでもそうなんですが、YAPCに行くと、世の中にはまだまだ知らない世界があって問題が解かれているのだ、人々が日々取り組んでいるのだ、ということを実感できますね。自分も誰かの学びになるような発表をできるようにありたいです。

フィードバック

名札の裏にスタンプラリーの台紙があるのを気にせずにスタンプラリーを回っていたら、白いパーカー*5にスタンプの色が付いてしまった!! 来年以降はこちらの件についてご対応を検討いただけますと幸いです。

ところで、こういった要望みたいなのをお伝えする公式のフォームとかあるんですかね?

全てに感謝

運営スタップの皆様、当日お話しできた方、出張として交通宿泊費補助を出してくれた株式会社はてな*6様に森羅万象に感謝を申し上げます。来年のYAPCで会いましょう。

ToKyoto.js #02 に参加した #kyotojs

kyotojs.connpass.com

登壇もしました。発表資料は以下です。「発表枠(Kyoto)」という枠がなかなか埋まっていなかったので、自分に話せることがないか、を2日前の夜に絞り出しました。

speakerdeck.com

create-react-appの現状と自分との関わりについて話しました。エモーショナルに振った話になったと思いますが、Twitterでの反応を見るに想像以上に響いていそうでよかったです。

他の方の発表もどれも面白かったです。明日から使える便利な話、突然腕力が発動する話、ディープな話をいろいろ聞けて、東京にいるけどわりといつも通りのKyoto.jsだな、と思いながら聞いていました。最終的にはASTをいじりたくなる人がいっぱいいてよかったです。

Go Conference mini 2023 Winter IN KYOTOに参加した #kyotogo

参加しました。本当はプロポーザルを提出しようかと思っていたのですが、忙殺されていたら〆切を過ぎていました。そして参加記を書くのも忙殺されていて遅くなったのであった……。

kyotogo.connpass.com

聞いたトークのメモは以下のScrapboxにあります。

scrapbox.io

すぐ近くでGoのカンファレンスが開催されるということで参加しました。河原町周辺はだいたい知っているのでホームグラウンド感覚で参加できておもしろい。

タイムゾーン安全な日時ライブラリの話がいちばん面白かったと思います。ジェネリクスをうまく活用している、ISO 8601に準拠するためになかなかの労力を割いいていそう、contextに入れるのを考慮したAPIがある、というトピックがなかなかいい。最近の個人的な関心は、各社で何をcontextに入れているのか、ということにあります。

さすがにCOVID-19も落ち着いた (ということにする) だろうし、もうちょっと各地のコミュニティを見にいくようにしたらいいのかな?

次回のGo Conferenceは東京開催ということで、これも行きたいですね。

mockgenのreflect modeで型引数を取る型を返すメソッドのあるinterfaceのモックを生成できない

表題が全てです。たとえば以下のように定義されている I interfaceのモックをmockgenのreflect modeで生成するとエラーになる。

package generic

import (
    "go.uber.org/mock/sample/imp1"
)

type V[T any] map[string]T

type I interface {
    X() V[imp1.Imp1]
}

エラーメッセージをよく見ると、X メソッドの返り値の型が generic.V[imp1.Imp1] ではなく generic.V[go.uber.org/mock/sample/imp1.Imp1] という型になっていておかしい。これは reflect.Type 型の Name() メソッドがこういう文字列を返すことに起因している。

github.com

このissueでも言及されているように、2023/10/3 時点ではGoの reflect.Type からジェネリックな型の引数の情報を取得するインタフェースは提供されていない。proposalはある。

github.com

type VImp1 V[imp1.Imp1] のように型を定義してあげれば回避できる。あとはreflect modeではなくsource modeだとちゃんと動く。

ここで緊急アンケート

みなさまはGoのinterfaceのモックに何を使っていますか?

go-sql-driver/mysqlのプレースホルダ置換を有効にしつつJSONカラムを使うときは[]byte型を経由しない

tl;dr

  • JSONカラムをマッピングするときは []byte 型を使わない
  • string 型や json.RawMessage 型を使う

起こっていたこと

Goのwebアプリケーションで、go-sql-driver/mysqlの interpolateParams=true オプションを有効にしてテストを回したら、以下のようなエラーでテストが落ちた。 interpolateParams=true はプレースホルダ置換を有効にするオプションである*1

Cannot create a JSON value from a string with CHARACTER SET 'binary'.

アプリケーションのコードは interpolateParams=true を指定しただけで他の箇所は書き換えていない。MySQLと通信するときのcharacter setに binary を指定した覚えは全くない。何が起こっていたのか?

原因と解決策

DBの行をマップしているstructの構造をかいつまんで書くと以下の通り。JSON型のカラムを書き込むところでエラーになっていた。

type User struct {
  Id   string     `db:"id"`
  Data JsonColumn `db:"data"` // JSON NOT NULL
}

// JsonColumn は driver.Valuer, sql.Scanner を実装している
// 内部的に json.Marshal, json.Unmarshal を呼んでいる
type JsonColumn []byte

出てきたエラーメッセージで検索してみると以下のissueがヒットした。 JSON型のカラムをやり取りするときは []byte 型ではなく string 型や json.RawMessage 型を使うようにするといいらしい。

github.com

ということで、筆者が関わっているプロダクトではstructのフィールドの型を自由に調整できるのでこれで解決しました。

何が起こっていたのか

これだけで記事を終わっても備忘録*2としてはいいだろうけど、ついでなのでプレースホルダ置換を有効にしてエラーになったとき何が起こっていたのか見てみる。

mysqlConn structの interpolateParams メソッドの []byte 型に対する処理を読んでみると、文字列リテラルの前に _binary というのを書いていて、いかにもバイナリにしていそう。

github.com

これはイントロデューサというもので、文字列リテラルのcharacter setを指示しているらしい。謎が解けましたね。

dev.mysql.com

go-sql-driver/mysqlを使ってMySQLの疎通確認を行うコマンドラインツールを書いた

絶対もうあるでしょう、と思いつつも書きました。go-sql-driver/mysql を使っているのでlibmysqlclientが入っていなくても動くと思います。

github.com

mysql コマンドでホスト名・ポート番号を指定して接続するのと同じコマンドライン引数が使えます。ほかのコマンドライン引数は必要になったら対応します。

$ go-mysqlping -h127.0.0.1 -P3306 -uroot -ppassword

1秒おきにDBアクセスしつつcontextでキャンセルできるようにする、みたいなのを初めて書いたけど意外と書けるものですね。time.Tickという関数があることは知っているけど、最初にアクセスするときに1秒待ってほしくないので手作りしています*1。goroutineがリークしていたら教えてください。