風がなければ公園でバドミントンもできそう

風がなければ公園でバドミントンもできそう

先日購入した ポータブルネット を使って公園で屋外バドミントンを1時間ほどした。持ち運びするときの折り畳み状態が次になる。筒の中に紐が通っていてバラバラにならないので簡単に組み立てできる。初見でも2分あれば組み立ても片付けもできる。予想以上に組み立て/片付けの体験がよかった。

みなとのもりの運動

前回の所感 。水曜日に運動部の slack チャンネルに投稿していた。とがいさんが久しぶりにバスケの練習に来られた。9時から準備を始めて10時から公園で運動する。土曜日の午前中に運動の予定を入れるのは朝ちゃんと起きる理由にもなってよい。予定がなければ、お昼までだらだらしてしまっていたかもしれない。私はトラックを4周ジョギングしてストレッチをしてからバドミントンのひとり練習をしていた。とがいさんもバスケ練習が終えてから合流して一緒にバドミントンの練習もした。10時半頃から軽くウォームアップして、ネットを挟んで打ち合いをした。ネットがあるとバドミントンの練習をするモチベーションにもなるし、場所を固定するのにもよい。太陽とシャトルが重ならないような位置取り、風の向きなども考慮して場所を決めないといけない。2回休憩して11時半頃まで打ち合いの練習をして終えた。よい運動になった。

バドミントンは体力さえ続けば1時間ぐらいなんとなくでやってしまう。誰でもできる有酸素運動としてよさそうにみえる。テトリスのような、シンプルなゲームだからついついやり続けてしまう魅力がある。

ストレッチ

今週は毎日30-60程度はバドミントンの練習をしてきて汗をかくぐらいには運動してきて太ももに張りを感じていた。ゆっくりやっているつもりでもたまにチカラが入ってしまうときもある。以前 SPINE SALON さんで診察 してもらったときの状況に似ている。また筋が少しズレているのかもしれない。運動を再開してからはこのときに教えてもらった体操もしていた。トレーナーさんも気遣ってくれて右太ももを念入りにゆっくり伸ばしてくれた。そのせいか、ストレッチ前と比べてずいぶん楽になった。今日の開脚幅は開始前146cmで、ストレッチ後154cmだった。少し休みながら様子をみてみようと思う。

雨上がり後の練習

目次

今日のバドミントン練習はリフティングを10分、キャッチを10分、壁当てを10分した。今日も近所のビル横の広場へ行った。本当は10分だけやって帰ろうと思っていたのにやり始めたら楽しくなってきて30分やっていた。ちょうど23時半から始めて24時になるとビルの玄関が消灯した。これまで22時台でしか練習していなかった。その時間帯に行くのがよいということもわかった。

リフティングは夜でも200回は続けられるようになった。ラケットコントロールが少しずつ上達してきたのは実感できる。単純に回数を続けるだけであれば、もっと回数を増やすこともできると思う。回数を増やすことにあまり意味はないのでリフティングのやり方を工夫したりしている。最初のウォームアップに200回ほどリフティングをやってから別の練習をするようになった。バドミントンのひとり練習動画 でリフティングもキャッチもラケットの持ち方をフォア持ちとバック持ちに切り替えて繰り返しやることを紹介している。昨日からこの練習に挑戦しているが、まだまだ安定的に切り替えることが私には難しい。

真上に打ち上げるロビングもシャトルを狙ったところに打つにはラケットのスィートスポットでシャトルを捉える必要がある。うまく打てるときもあるが、連続して何度も真上に打ち上げるのは難しい。何回かに1回はきれいに真上にあがるがそのときに落ちてきたシャトルを連続して真上に上げるのは難しい。ラケットコントロールがうまくできていないから、やや角度がついて斜め上にあがってしまう。そうすると落下点へ移動するためにドタバタしてしまってロビングの練習にならない。毎日数十分でも続けていける雰囲気はする。

一日中テストコードを書いていた

目次

今日のバドミントン練習は22時半頃から近所のビル横の広場でリフティングを20分、キャッチを10分、壁当てを10分した。

リフティングや壁当てをしていて、自分の感覚とはずれてラケットを空振りしてしまうことがある。またラケットのスィートスポットでシャトルを捉えられず、フレームでこねてしまうこともある。この感覚のズレはなぜ起きるのかを考えるようになった。1つわかったことは飛んでいるシャトルを点で捉えようとすると空振りしやすい。シャトルの軌道を見極めてシャトルの移動する放物線でラケットを振ると捉えやすい。野球の球をうつときにもよく指摘される話しでもある。そのままバドミントンにも応用できるように思えた。体勢が崩れたり、向かってくるシャトルの速度にあわせられないときなど、シャトルの移動する放物線を目で捉えられなくて空振りしてしまう。理論がわかったからと言ってそんなすぐに対応できるわけでもないが、今日の練習をしていた気付いたことを書いていく。

外へ出掛けるときにラケットとシャトルをもって時間があれば、空きスペースで練習するのに慣れてきた。

バドミントンの雨天練習場

バドミントンの雨天練習場

目次

今日のバドミントン練習はお昼に20分、夜に30分ほどした。

15時頃コンビニへ飲みものを買いにいくついでに東遊園地へ寄り道して練習した。そんなに人が多いわけではないけど、公園でのんびりしている人たちがちょこちょこいる。空きスペースでおっさんが昼間からバドミントンの練習をするのはやや恥ずかしい。下手だし。「あの人働いてないんやろか」とか周りからみられているかもしれない。最初はそんなことを考えながらも、練習をやり始めたら集中してきてあまり気にならなくなった。昼間はリフティングを10分、キャッチを10分した。連続最大回数は127回、10分間に20回ほどキャッチできた。ほんの数十分でも毎日やっていれば徐々にうまくなっている気はする。

夜も近所でビルの玄関横の少し広いスペースをみつけた。ビルの正面玄関の電気がある。十分に明るくはないけど、ぎりぎりリフティングやキャッチの練習ならできる。しかも屋根があるから雨の日でも練習できる。22時頃ならほとんど人がいないからたぶん練習していても怒られない。なんだかんだで30分以上はやっていたと思う。シャトルを上に放り投げてキャッチするときに、一番簡単なのはシャトルが落ちてくる速度にあわせてラケット面を落としながら受ける。もっとも簡単で少し練習すれば5回に1回は成功する。しかし、このやり方は上下のシャトルの動きにしか対応できない。シャトルを上に放り投げてキャッチするときに上下のチカラの調整だけではなく、シャトルの落下速度にあわせながら横からラケットを当てて包み込むような取り方がある。うまくはまればかっこいい。失敗すると空振りするのでもう少し練習が必要になる。リフティングやキャッチのような基本的な練習でもチカラの向きやシャトルの動きから学ぶことはいくつもある。

磯上公園での夜間練習

磯上公園での夜間練習

今日のバドミントン練習はリフティングとシャトルキャッチを30分、ながいさんと打ち合いを30分した。1時間近くバドミントン練習をしていたことで歩数で言えば5千歩相当の運動になった。バドミントンは激しい運動ではないものの、わりと動き回るので有酸素運動としても優等生だと思う。よい感じにカロリーを消費する。

社内ハンズオン

社内向けハンズオンの2回目。前回の社内ハンズオン 。いまの開発フェーズの機能開発が落ち着いたのでハンズオンを実施して ui などのレビュー会も実施した。朝10時半から始めて、お昼休みをはさみつつ、16時頃までやっていた。私はハドルでつないで聞きながら自分の作業をやろうと思っていたものの、なにかしらハンズオン会場の会話や質問を聞いていると、その回答や背景などを slack に書いたりして注意力が取られてあまり自分の作業はできなかった。みんなでわいわい検証したり、プロダクトへのフィードバックや意見が出て楽しかった。

いそがみ体育館お休み

ながいさんとバドミントン練習する前に筋トレしようと早めにお仕事を切り上げて向かったらお休みだった。偶数月の第1火曜日が休館日らしい。それはわからんやろと帰ってきてから google カレンダーに登録した。2ヶ月ごとの第1火曜日の繰り返し予定という設定は google カレンダーで用意に登録できる。次は12月3日、その次は2月4日・・・今後はこの失敗を回避できるはず。

いそがみのバドミントン練習

スーパーで買いものして家に戻って晩ご飯を作って食べてから20時半にいそがみ公園へ戻る。21時半まで約1時間、バドミントンの練習をした。リフティングやシャトルキャッチの練習をしていて、ながいさんが来られてから打ち合いをしてみた。街灯の隣でやればシャトルはみえなくはないけど、体育館で行うような集中したラリーにはなりそうもない。それは暗くてシャトルがみえにくいから。軽い運動で流す程度ならぎりぎりできるかもしれない。昼間と夜間で練習してみて、左右のシャトルの変化は暗くても把握しやすいが、前後のシャトルの変化は暗いと遠近感をつかみにくい。夜間の方がリフティングが難しいのも微妙に遠近感が狂うから。ラケットコントロールがうまくなればブレずにシャトルを空中に上げられて遠近感を気にせずにリフティングできるようになるかもしれない。

昨日からアウトドア用の メイビスフィールドメイビスフィールドII の、2つのシャトルを実際に使っていて、その違いを比べてみた。結論からいうとメイビスフィールドIIの方が性能がよいようにみえる。メイビスフィールドIIの方がシャトルをうったときの反発力は強く、軽い力で速く遠くへ飛ばせるように感じる。初期モデルに改良が施されていることが明らかに伺える。一方で初期モデルが不要かというとそうでもなく、リフティングやシャトルキャッチの練習をするなら反発力は必要ではないから跳ねない方がラケットコントロールが適切にできているかの練習になりそうな気もする。ラケットの中心 (スィートスポット) でシャトルを捉えられているか、シャトルのコルクをどの角度で捉えているかの感覚を養うにはあまり反発しない方が感触を確認しやすいようにも思えた。反発しないから強い打球をうつ練習にもなる。適材適所で使い分けようと思う。

ほかに LED ライトがついた光るシャトルというのも売っていて気になっている。電池交換は不可で数時間から数十時間ほど使えるらしい。屋外で行う エアバドミントン というのもある。風の影響を受けにくいエアシャトルを使う以外はバドミントンと大差なさそう。バレーとビーチバレーのような関係?これらのシャトルも近いうちに買ってみて試してみようと思う。

9月最終日に主開発を完了

今日のバドミントン練習はリフティングを10分した。連続最大回数は70回できた。シャトルを上に放り投げてラケットでキャッチする練習も10分やってみた。昨日よりは少しうまくなった気がした。それでも5-10回に1回ぐらいの頻度。なかなか難しい。

最後の厄介なリファクタリングを完了

一昨日から着手しているリファクタリング作業に朝から着手していた。一晩寝かせた効果だと思うが、昨日の夜にノーアイディアだった設計もさくさく進んでシンプルに実装できた。無意識の脳の働きがすごい。13時頃には実装を終えてマージリクエストを作るのに約1時間。なぜリファクタリングするのかの目的と意図をマージリクエストに書いた。最終的にはこの issue の対応は丸2日かけてコードを書き直した。これが早いのか遅いのか、もう私にはわからなくなってしまっている。昔の方が体力と集中力がある分、土日で終えられたかもしれないし、いまの方が経験がある分、昔よりも高い品質のコードを短い時間で書いているのかもしれない。

老いは誰にもやってくる 歳を取れば技は練れる 駆け引きにもたける だが圧倒的なパワーに対して対抗しきれない日は必ず来る

幻海師範

知人が「プログラミングは長い間やっているとわかるようになる」と表現していてその通りだなと私も思う。プログラミングに限らず習熟によってスキルアップする対象はだいたい同じなのかもしれない。いまバドミントンの練習を始めたばかりだが、1年後にはいまより少し上手くなっていると嬉しい。

1ヶ月ぶりの休日出勤

1ヶ月ぶりの休日出勤

今日のバドミントン練習はリフティングを昼間に10分、夜に10分、壁当てを10分した。連続最大回数は82回できた (昼間) 。昼間にやってみたら夜に街灯の隣でやるときとの違いに気付いた。ほんのそよ風でもシャトルは風の影響を受けるので空中で少し流れたりする。その微妙な変化が暗いとみえにくい。昼間にリフティングをやってみたことで真っ直ぐ落ちてこず微妙に風で流れていることを観察できた。あとシャトルを高くあげた方が重力による加速がつくので真っ直ぐ落ちてきやすくなるかもしれない。

ポータブルネット

外でバドミントンができる準備をしていく。調べてみたらいくつか製品の候補がみつかる。価格帯は3千円から1万円ぐらいの幅。最終的には YONEX の ポータブルネット(バドミントン用).AC334 に決めた。なにかの記事で初心者は製品の良し悪しの判断が難しいから YONEX を買っておけば間違いないと書いてあった。amazon で購入すると9千円ほどだった。土日の昼間に公園へ持っていって練習できるかもしれないし、バドミントン設備がない体育館を借りて練習するのもよいかもしれない。たまたま組み立てしている動画をみつけた。一緒にクリップを用意しておけば幅の調節もできるみたい。

お昼からずっとコードを書いてた

昨日は家に帰る途中でバドミントンの練習場所を探したり、軽く練習をしたりしていて、1時過ぎに帰ってだらだらして3時頃に寝たせいか、少し寝坊してお昼頃にオフィスへ行った。ちゃんと休日にオフィスへ行ってお仕事できるぐらいには体調 (モチベーション) が回復した。病気だったわけでもないが。本当は今日中にマージリクエストまで作りたかったが、ラストワンマイル的なところがなかなか煩雑で24時過ぎまでやって明日に持ち越すことにした。寝ているときに無意識で設計するから明日にした方がコードの品質も上がるだろうと、既存のコードのロジックの確認や設計のヒントになりそうなことの調査をして終えた。

日曜日にお仕事をしたのは1ヶ月ぶり。しかも12時から24時と途中で晩ご飯休憩をはさみながらほとんどフルタイムに働いていた。他人のコードのリファクタリングだから私が直さないといけない積極的なインセンティブがない。この開発フェーズの最後の issue だったのと、私がコードレビューして知ってしまっているからやる・やらないを選択しないといけない。やらなくても誰からも非難されないかもしれない。逆に言えば、だからこそ、やらないといけないなと昨日、決心した。覚悟したからどれだけ労力をかけようが気にならなくなった。そんな休日のモチベーション管理。

バドミントンのひとり練習

今日のバドミントン練習はリフティングを30分した。連続最大回数は27回だった。

最後の厄介なリファクタリング

10時頃に起きて11時にはオフィスへ来て作業をしていたと思う。昨日ジョギングと筋トレしたから寝起きジョギングはやめて普通にオフィスへ行って作業していた。この issue はどこまでリファクタリングするかの決めの問題もあり、少し寝かせてあった。私のもてるスキルを駆使して思い切りやることを決めて土日で大半を終わらそうと思う。いくつかの葛藤と逡巡を振り払って着手はした。昼間は既存のコードの本質的な問題の分析、再設計のための要項の調査、軽くコードを書きながらの感触の確認などをしていた。その後、ストレッチに出掛けて戻ってきてから続きをやるつもりが、いろいろ雑務をやっていたら22時ぐらいになってしまってまた明日でいいやと諦めた。モチベーションが足りない。一回休み。

ストレッチ

昨日、久しぶりに筋トレをして夜は全然平気だったのに寝て起きたらあちこち全身筋肉痛でストレッチもかなりきつかった。悪い痛みではないから筋肉をほぐしてもらった感じになる。今日の開脚幅は開始前146cmで、ストレッチ後153cmだった。筋肉痛だから硬めのように思えたが、数字だけ比べたら普段とそんなに変わらなかった。

トレーナーさんと自民党の総裁選挙の話題になって、一通りニュースをみて私も思うところはあったものの、政治的な話題のやり取りする場所がないから誰と話すこともないだろうとしまいこんでた矢先、トレーナーさんから話題が出てきたのでいろいろ話してみた。石破さんは自民党内で嫌われているから決戦投票で勝てないだろうという大方の見通しを覆したのは見事だったし、石破さんは良識なリベラル、且つ金融所得課税の強化に前向きだったりもするから市場の反応は悪い。これまでは総理大臣が変わったタイミングはご祝儀相場のように歓迎されることが多かったのに対して、月曜日は株価が急落するようにみられている。これほど市場からネガティブな反応が出るのも珍しいなという所感。余談だが、私はいまどちらのポジションもとっていないので株価が下がってもあまり影響はない。個人的にはシステムへの理解が深いという側面だけで河野さんを応援しているものの (一方で官僚に対するもの言いがパワハラ的なところがマイナス)、今回は後ろから2番目と不人気だった。日本では自民党総裁=総理大臣なわけではあるが、政治家が影響力をもつタイミングというのは本当に難しい。石破さんも5回目の総裁選ということで悲願が叶ってよかったんじゃないかと応援したい。

ひとりでできるバドミントンの練習

ストレッチを終えてから 購入したラケットを受け取り してきた。試し打ちではないけど、買ったばかりで使ってみたいから KALIDIA チャンネルから1人でできる練習を探してみた。次の練習はラケットとシャトルとの距離感を掴むための練習になるという。なるべく日課としてしばらく続けてみたい。

  1. シャトルのキャッチ
  2. バドミントンの技を3つ行う
    • スピンネット
    • ミニクロスネット
    • ロビング
  3. リフティング
  4. 屋外で向かい風に向かってロビングを打つ

2ヶ月ぶりの筋トレ

今日は簡単な issue を2つ fix して作業の区切りがよかったので17時にはお仕事を終えた。この開発フェーズで対応する厄介な issue はあと1つだけ。それをもって私の開発者としての集中時間も一区切りとする。これ以上は自分の時間を開発に費やさず、普段通りのお仕事ペースでいこうかなと決めた。

ラケット選び

先週やまとさんに教えてもらった バドミントンプロショップチャンプ というお店へ行って店員さんにラケット選びの相談をしてきた。amazon やオンラインで買いものするのが当たり前となった昨今、リアル店舗で店員さんに相談してモノを買うというのはコンサル料も込みだと思うようになってきた。初心者向けのラケット選びは、ラケットを簡単に扱えることを前提として次の特徴が大事だという。

  • ラケットの重さが軽め (4U: 80-84g が標準)
  • 重心が手元に近い方にある (これをヘッドライトと呼ぶ)
  • シャフトが柔らかい

一方で中上級者になると、フレームの先端側にあるヘッドヘビーが好まれるようで、その中間のバランスのよいタイプをイーブンと呼ぶ。ラケットの重さも重い方が強く返せるが操作が難しい。練習して上達したらヘッドヘビー側のラケットを選ぶようになっていくことを考慮すると、最初からヘッドライトではなく、イーブンでよいのではないか?という考え方もある。そしてイーブンを使っていてスキルアップして物足りなくなったら、そのときにヘッドヘビーのラケットを買い替えたらよいとのこと。事前調査した段階ではヘッドライトでよいと私は考えていたが、店員さんと話していてイーブンにしようと改めた。イーブンのラケットで製品の候補が3つあって最終的に アークセイバー3. ARC3 に決めた。このお店では12,320円だった。他候補のアークセイバー1だと1万円台だった。主な違いはフレームが台湾製か日本製かになるという。ラケットはフレームの品質が重要らしく、その違いを私がわかるとも思えないが、2千円なら別にいいかと思ってアークセイバー3にした。ガットを張るために受け渡しは翌日になるとのこと。

お店で買ったものの明細 (税込) 。ついでに練習用シャトルも1ダース買ってみた。

  • ラケット: 12,320
  • ガット + ガット張り工賃 : 2,150
  • グリップテープ: 350
  • エアロセンサ200 (1ダース): 2,700

いそがみの筋トレ

前回の所感 。気付いたら約2ヶ月ぶり。早めにお仕事を終えて十分に時間もあったから行ってきた。トレーニング器機の重さと回数を 筋トレの記録 に付けていた。2ヶ月ぶりだから前回の数値を覚えていないが、記録をみながら前回の数値を引き継いで筋トレできた。ちょっと辛めではあったものの、意外と同じ数値でこなすことができて、筋肉を増やすのは大変なものの、逆にそんな簡単に減りもしないということを確認できた場面でもあった。また週に2回ぐらいのペースで通えればよいなと思う。

fitbit 交換とサポート対応

出張へ出掛ける前に 故障したデバイスの返品手続き をしていた。今日ちょうど交換用の新しいデバイスが届いた。サポートにトラブルシューティングの連絡をして、メールで購入証明や送り先の必要情報をやり取りして、1週間ほどで交換用デバイスが届くといった無駄のない効率的なサポート対応だったと思う。私の経験則においても、お客さんのサポートはトラブルそのものが問題ではなく、トラブル発生後に適切な対応をしてくれるが大事になる。今回のケースにおいても fitbit の故障そのものにまったくネガティブな印象はない。うちの会社もトラブルが起きたときはその原因の如何によらず、コストの損得に関わらず、そのとき出来ることの対応に努めることを法人の基本的な理念としたい。そんなことは社員を雇うときに考えることでもあるが。

非同期処理のキャンセルと中断待ち

目次

バックエンドで非同期のバッチ処理を実装してサーバーが shutdown したときに実行中のバッチ処理も安全に止めないといけない。

context でキャンセルするのは簡単だけど、非同期で動いている goroutine が中断してから終了したことを main プログラム側で待つ同期をどう実装しようか悩んでいた。たまたま 【Go】Contextの魅力を感じる の記事をみたら sync#WaitGroup と組み合わせたサンプルコードがあって、これまでも sync#WaitGroup を使ったコードを何度も書いてきて知っていたはずなのに context と組み合わせるという発想はなかったなと気付きを得た。それからライブラリとして汎用のバッチ処理の controller を実装した。

type Controller struct {
	ctx    context.Context
	cancel context.CancelFunc
	wg     *sync.WaitGroup
	mu     sync.Mutex
}

func (c *Controller) Register() (context.Context, *sync.WaitGroup) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.wg.Add(1)
	ctx := context.WithValue(c.ctx, ctxKey{}, 0)
	return ctx, c.wg
}

func (c *Controller) Stop() {
	c.cancel()
}

func (c *Controller) Wait() <-chan struct{} {
	c.mu.Lock()
	defer c.mu.Unlock()
	quit := make(chan struct{}, 1)
	go func() {
		c.wg.Wait()
		slog.Debug("completed to wait group in batch.Controller")
		quit <- struct{}{}
	}()
	return quit
}

func NewController(parent context.Context) *Controller {
	ctx, cancel := context.WithCancel(parent)
	return &Controller{
		ctx:    ctx,
		cancel: cancel,
		wg:     new(sync.WaitGroup),
	}
}

parent の context でキャンセルさせることもできるし、この controller の api からキャンセルさせることもできる。

この controller を使うアプリケーションのコードは次のようになる。

c := batch.NewController(ctx)

func() {
	ctx, wg := c.Register()
	defer wg.Done()

    for {
	    // do something
        select {
        case <-ctx.Done():
            slog.Debug("canceled", "err", ctx.Err())
            return
        default:
        }
    }
}()

timer := time.NewTimer(10 * time.Second)
select {
case <-timer.C:
	slog.Debug("expected to complete waiting, but occur timeout")
case <-c.Wait():
	slog.Debug("completed to wait")
}

context.Done() に習って Wait() が channel を返すことで timer と組み合わせて、バッチ処理の中断を待たずに終了するといった制御もできる。後になってふりかえると、timer の制御も Wait() メソッドに入れてしまってもよい気もするが、それは呼び出し側の要件によって変わってくるからこのままの方がライブラリのコードの見通しがよくてよい気もする。朝から設計して、昼間に実装して夕方にテストを書いて、帰りの新幹線でアプリケーションに組み込みしていた。1日でちゃちゃっと作ったわりにはよく出来たと思う。

excel が utf-8 で保存する csv ファイルは bom 付き

昨日の定例会議で csv ファイルのエンコーディングの話しになって excel 2016 以降では utf-8 で csv ファイルを保存できるようになった。もう cp932 対応しなくてよいといった話題が出た。そのときにうろ覚えだったものの、excel は byte order mark (bom) を付けていた気がして、実際にファイルを作ってもらったらそうだった。bom の有無は file コマンドや od コマンドでなどで調べられる。

$ file book1.csv
book1.csv: Unicode text, UTF-8 (with BOM) text, with CRLF line terminators

ファイルの先頭に 0xef 0xbb 0xbf の3バイトがつく。

$ head -1 | od -t x1 book1.csv
0000000    ef  bb  bf  68  65  61  64  65  72  31  2c  68  65  61  64  65
0000020    72  32  2c  68  65  61  64  65  72  33  2c  68  65  61  64  65
...

印字可能な文字ではないため、テキストにするとわからないが、byte 列だと bom が付いているのがわかる。16進数の 0x68 が ‘h’ になる。bom がついていると header1 という文字列比較したときに別の文字列になってしまうので取り除かないといけない。

文字列: 'header1'
byte列: 'efbbbf68656164657231'

いろんな対応方法があると思うが、so の回答 でみつけたこの方法がコードの見通しもよくて気に入った。次のように io.Reader をラップするようなコードになる。

func newBOMAwaredCSVReader(reader io.Reader) *csv.Reader {
	transformer := unicode.BOMOverride(encoding.Nop.NewDecoder())
	return csv.NewReader(transform.NewReader(reader, transformer))
}

Transformer という仕組みがあって、準標準ライブラリの golang.org/x/text/encoding で実装されている。so の回答をみただけでコードを追加するのもよくないかと思って unicode#BOMOverride が返す bomOverride transformer のコードを読んで把握した上でテストを書いてマージリクエストを送った。実際の変換処理は次のようなもの。

  • fallback として encoding.Nop を使う
  • 最初に呼ばれたときに d.current (fallback) をセットして、2回目以降は fallback が呼ばれる
  • 与えられた byte 列が 2byte 以上のときに bom のチェックを行う
  • bom があるときはそのバイト数を読み飛ばして d.current (fallback) で変換する
func (d *bomOverride) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
	if d.current != nil {
		return d.current.Transform(dst, src, atEOF)
	}
	if len(src) < 3 && !atEOF {
		return 0, 0, transform.ErrShortSrc
	}
	d.current = d.fallback
	bomSize := 0
	if len(src) >= 2 {
		if src[0] == 0xFF && src[1] == 0xFE {
			d.current = utf16le.NewDecoder()
			bomSize = 2
		} else if src[0] == 0xFE && src[1] == 0xFF {
			d.current = utf16be.NewDecoder()
			bomSize = 2
		} else if len(src) >= 3 &&
			src[0] == utf8BOM[0] &&
			src[1] == utf8BOM[1] &&
			src[2] == utf8BOM[2] {
			d.current = transform.Nop
			bomSize = 3
		}
	}
	if bomSize < len(src) {
		nDst, nSrc, err = d.current.Transform(dst, src[bomSize:], atEOF)
	}
	return nDst, nSrc + bomSize, err
}

自分で実装してもなにも難しくないけど、すでに実績のあるコードがあるならそれを再利用した方が保守コストを削減できる。

同期飲み会

新卒入社した会社の同期との飲み会。2ヶ月前と同じメンバー で飲んできた。4人で飲む予定が、また1人が障害対応でドタキャンになったから3人で飲んでた。日本酒原価酒蔵 という、おいしい日本酒を原価で提供するお店があるみたい。プレミアム飲み放題プランだったのでよいお酒をいろいろ飲み比べできた。どれもおいしかったし、ちょっとずついろいろ飲み比べできておもしろかった。飲み放題メニューに神戸のお酒がなかったのがよいことなのか残念なのか。前半は辛口の日本酒を飲んで、だんだん酔っ払って味がわからなくなるから、後半にコクや甘みの強い日本酒を飲むとおいしく飲めると教えてもらった。本当にその通りで日本酒の飲み方のよい勉強になった。お店で飲んだお酒のカードがもらえる。酔っ払って忘れてしまっても後で思い出せる。

特徴的なお酒で記憶に残っているもので 三井の寿 がスラムダンクに出てくる三井寿に由来して命名されていて、その背番号である14番と同じアルコード度数14度、日本酒度 (辛口甘口の度合いを表す) +14 と意図的?にあっているとのこと。日本酒の中ではトップクラスの辛口らしい。たしかに過去に私が飲んだことがないキレだった。もう1つは 讃岐くらうでぃ という、カルピスのような風味に近い珍しいお酒。甘いので後半に飲むとよい。うちらは酔っ払って訳がわからなくなってきたときに口直しのように飲んでた。そういう飲み方をするものかどうかはわからないが、飲みやすいのでついつい飲んでしまい、さらに酔ってしまう典型的なお酒。同期飲みは記憶をなくす感じで飲む。この歳になってこんな飲み方する相手いないなと思うとまた楽しい。