<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>something tech.</title><link>https://blog.web-apps.tech/</link><description>Recent content on something tech.</description><generator>Hugo -- 0.153.1</generator><language>ja-jp</language><copyright>@nasa9084</copyright><lastBuildDate>Sat, 06 Jun 2026 23:00:00 +0900</lastBuildDate><atom:link href="https://blog.web-apps.tech/index.xml" rel="self" type="application/rss+xml"/><item><title>梅仕事2026</title><link>https://blog.web-apps.tech/ume-2026/</link><pubDate>Sat, 06 Jun 2026 23:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/ume-2026/</guid><description>&lt;p&gt;気を抜いて生活していたら、梅仕事が今年初めての記事になってしまいました。
&lt;a href="https://blog.web-apps.tech/ume-2025"&gt;去年、スーパーで全然梅を見ない&lt;/a&gt;
と書いたんですけど、今年もなかなか売っているのを見つけるのに時間がかかりました。
去年は結局ふるさと納税で梅を入手したので去年の相場は結局分からないんですが、今年は500g1000円くらい、ロピア(何を買っても割と安い)で1kg1599円(税別)でした。高いですね。天候不順などが理由で3年連続梅が不作だそうです。&lt;/p&gt;
&lt;p&gt;今年の梅はサイズの表記がない南高梅ですが、L~2Lくらいのサイズはありそうです。多少の傷はありましたが、今年は梅酒だけで梅シロップを作らないことにしたので、多少の傷は問題無かろう、ということで1つもハネずに使用しました。&lt;/p&gt;
&lt;p&gt;今年は梅も普通の南高梅、割けも果実酒用のホワイトリカーとしましたが、砂糖はすずらん印のてんさいグラニュー糖としました。昨年パッケージデザインが新しくなった、と聞いたのを思い出して、オッ、となったので。&lt;/p&gt;
&lt;p&gt;なんやかんやグラニュー糖、というか粉末状の砂糖を使って梅酒を仕込むのは初めてかもしれません。過去使用した梅酒用の砂糖でもっとも細かったのは中ザラ糖で、粉末・・・というには結晶が大きいですね。梅酒の仕込みではゆっくり溶けて濃度に変化が発生する氷砂糖が良い、とされていますが、どんなもんでしょうか。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2026/images/without_liquor_hu_91f38e419250db5f.jpg" alt="酒を入れる前の状態" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2026/images/with_liquor_hu_3408bd9734b8bb5f.jpg" alt="酒を入れた後の状態" /&gt;
&lt;/p&gt;
&lt;p&gt;結晶の大きい砂糖に比べて密度が高いので、酒を入れた後でも浸透には少し時間がかかりましたし、ポコポコと気泡が上がっていました。&lt;/p&gt;
&lt;p&gt;扨、昨年の梅酒の味見です。昨年は紫宝梅というちょっと変わった梅の実を使用しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2026/images/last_year_hu_e13a31161c71b804.jpg" alt="昨年の梅酒" /&gt;
&lt;/p&gt;
&lt;p&gt;梅シロップはかなりきれいなピンク色でしたが、梅酒は1年も経つと退色してしまっていて、ピンクというよりは琥珀色、という感じでしょうか。年数の経った梅酒ともちょっと違うような、クリアだけど色づいている、そんなようなきれいな色です。&lt;/p&gt;
&lt;p&gt;味・・・というか、香りがすごく良いですね。砂糖も酒もごくごく普通の、ホワイトリカーと氷砂糖でしたので、雑味のようなものはなくて、梅の香りがダイレクトに出ている感じがします。梅の酸味、みたいなものも若干感じるような、甘めの梅干しをお酒にしたような、スッキリとした良い感じです。&lt;/p&gt;
&lt;p&gt;年々気温が高くなっているからか、今年の南高梅は少し完熟気味だったので、今年の梅酒も香りが楽しみです。&lt;/p&gt;
&lt;p&gt;ではまた来年。&lt;/p&gt;</description></item><item><title>2025年買って良かったもの</title><link>https://blog.web-apps.tech/2025-must-buy/</link><pubDate>Sun, 28 Dec 2025 20:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/2025-must-buy/</guid><description>&lt;p&gt;今年は主に園芸と料理の年でした。また、&lt;a href="https://blog.web-apps.tech/move-to-sapporo/"&gt;2024年9月末から札幌で一人暮らしを始めた&lt;/a&gt;
ので、自分で選んだ日用品が増えた年でもありました。
2024年に買って良かったものブログを書かなかったので、2024年に買って、今でも買って良かったな、と感じているものも入れておきます。&lt;/p&gt;
&lt;h1 id="園芸"&gt;園芸&lt;/h1&gt;
&lt;h2 id="道具資材"&gt;道具・資材&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.kingjim.co.jp/products/detail/RH24.html" target="_blank" rel="noopener"&gt;KINGJIM テプラ ハーフカッター&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ハーフカット機能がついていない機種を使っているテプラユーザは全員買った方がいい。剥離紙を剥がすときのストレスがないのはもちろんのこと、きれいに剥がれることで、貼った後に剥がれにくくなる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3MFVp6Y" target="_blank" rel="noopener"&gt;Kaiju Plant 園芸シート&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;室内で植え替えをするには必須と言っても良い。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://store.fujick.co.jp/?pid=147482344" target="_blank" rel="noopener"&gt;ベラボン・プレミアム&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://shop.takii.co.jp/products/detail/MDH367" target="_blank" rel="noopener"&gt;竹炭畑&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;用土は主に、ベラボン・プレミアムと竹炭畑、軽石、ゼオライトを混ぜたものを使っている。ベラボン・プレミアムが高いのと、竹炭畑がその辺ではあまり売っていないのが難。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="植物"&gt;植物&lt;/h2&gt;
&lt;h3 id="斑入りバオバブ"&gt;斑入りバオバブ&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/baobab_hu_b4caa3b0bb6c2bcf.jpg" alt="斑入りバオバブが我が家に届いたときの写真" /&gt;
&lt;/p&gt;
&lt;p&gt;初めて買った高級めな植物で、今でも我が家の中で最も高級な植物。のはず。シマムラ園芸で購入。
昨年の冬は見るも無惨なほどに落葉してしまったけど、夏ごろ、また葉が吹いてくれた。&lt;/p&gt;
&lt;p&gt;いまはまた冬なのでちょいちょい落葉している。多分年末年始に函館に帰省したタイミングで、室温がグッと下がる見込みなので、がっつり落葉すると思われる。&lt;/p&gt;
&lt;h3 id="アングレカムディスティカム"&gt;アングレカムディスティカム&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/angraecum_disticum_hu_e7092b498275338e.jpg" alt="アングレカムディスティカム" /&gt;
&lt;/p&gt;
&lt;p&gt;洋ランの一種。葉っぱを見てるだけでも可愛いし、気が向いたら花も咲かせてくれる。
サンシャインシティ世界のらん展2025で、ナーセリーイデさんから購入。&lt;/p&gt;
&lt;h3 id="ドリナリア-リギデュラ"&gt;ドリナリア リギデュラ&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/drynaria_hu_b58e3236da53e845.jpg" alt="ドリナリア リギデュラ" /&gt;
&lt;/p&gt;
&lt;p&gt;着生シダの一種らしい。枯れ葉のような部分と、細長い茎的な部分の2パートがあり、ちょっとかわってる。
板付だと乾かしすぎてアレだったので、今は鉢に植えた状態でつるしている。
サンシャインシティ世界のらん展2025で、Tropical Exotiqueさんから購入。&lt;/p&gt;
&lt;p&gt;これでドリナリアが好きになり、他の品種も買ってしまいました。&lt;/p&gt;
&lt;h3 id="アスパラガス-プルモーサス-ナナス"&gt;アスパラガス プルモーサス ナナス&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/nanas_hu_dfa604c1cb84457a.jpg" alt="アスパラガス プルモーサス ナナス" /&gt;
&lt;/p&gt;
&lt;p&gt;購入時はおつとめ品で、50円とかだった。カインズで購入。&lt;/p&gt;
&lt;h3 id="カンパニュラ-ダークゲットミー"&gt;カンパニュラ ダークゲットミー&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/campanula_hu_2cbeae2b939e1312.jpg" alt="カンパニュラ ダークゲットミー" /&gt;
&lt;/p&gt;
&lt;p&gt;めっちゃ咲いてくれて、満足度が高かった。ジョイフルエーケーで購入。
枯れずに元気なので、またたくさん咲いてくれることに期待している。&lt;/p&gt;
&lt;h3 id="ネメシア-グッピー"&gt;ネメシア グッピー&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/campanula_hu_2cbeae2b939e1312.jpg" alt="ネメシア グッピー" /&gt;
&lt;/p&gt;
&lt;p&gt;こちらもめっちゃ咲いてくれて満足度が高かった。香りも良い。
ジョイフルエーケーで購入し、こちらもまたたくさん咲いてほしい。&lt;/p&gt;
&lt;h3 id="カーネーション-ピンクアンドプラウド"&gt;カーネーション ピンクアンドプラウド&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/pink_and_proud_hu_d1882e0d48752a9a.jpg" alt="カーネーション ピンクアンドプラウド" /&gt;
&lt;/p&gt;
&lt;p&gt;カーネーション、と言いつつ花は小さめ。
花の色がかわっていて、濃いピンクと薄いピンクが入り交じった花を咲かせる。
割と最近の品種っぽい。
百合が原公園ガーデンショップで購入した。&lt;/p&gt;
&lt;h3 id="サニーレタスのタネ"&gt;サニーレタス(のタネ)&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/lettuce_hu_a4c40f15cdebeca8.jpg" alt="種から育てたサニーレタス" /&gt;
&lt;/p&gt;
&lt;p&gt;2024年末くらいからサニーレタスを実生で育てた。多分ジョイフルエーケーで購入。
室内にサニーレタス栽培エリアがあると、葉物野菜をいつでも摂取できるという点がものすごく良い。
もちろんスーパーとかでサニーレタスを買ってくることもできるけど、近年は野菜が高いし、何より葉物野菜は日持ちしないので。。。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/lettuce_2_hu_c25936c779a5bcba.png" alt="全盛期" /&gt;
&lt;/p&gt;
&lt;p&gt;全盛期は、取っても取っても食べきれないくらいだった。&lt;/p&gt;
&lt;h3 id="モンステラ-デリシオーサ-タウエリーのタネ"&gt;モンステラ デリシオーサ &amp;lsquo;タウエリー&amp;rsquo;(のタネ)&lt;/h3&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/2025-must-buy/images/monstera_tauerii_hu_2724e867f02bdf2.jpg" alt="モンステラ デリシオーサ &amp;lsquo;タウエリー&amp;rsquo;" /&gt;
&lt;/p&gt;</description></item><item><title>串鳥</title><link>https://blog.web-apps.tech/kushidori/</link><pubDate>Tue, 02 Dec 2025 00:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/kushidori/</guid><description>&lt;p&gt;本記事は&lt;a href="https://adventar.org/calendars/11865" target="_blank" rel="noopener"&gt;吉祥寺.pmについての25個の小さな話、またはMagnolia.Kの雑記 Advent Calendar 2025&lt;/a&gt;
2日目の記事です。
昨日はKaitouさんの&lt;a href="https://kaitou.hatenadiary.com/entry/%E5%A4%A7%E5%90%89%E7%A5%A5%E5%AF%BApm2025_%E3%82%B5%E3%82%B3%E3%83%83%E3%82%B7%E3%83%A5" target="_blank" rel="noopener"&gt;大吉祥寺.pmのPCが入るサコッシュを勝手に作ったお知らせ #kichijojipm&lt;/a&gt;
でした。
吉祥寺.pm、ロゴが可愛いのでサコッシュになっても映えますね。ちょっとほしいけどPCをサコッシュに入れて持って歩くことはなさそう・・・&lt;/p&gt;
&lt;p&gt;扨、実は吉祥寺.pmは&lt;a href="https://blog.web-apps.tech/dai-kichijoji-pm/"&gt;昨年の大吉祥寺.pmに行った&lt;/a&gt;
だけで、通常の吉祥寺.pmに行ったことも無く、吉祥寺自体も大吉祥寺.pm以外に1回行ったことがあるかないか、というレベルなのですが、&lt;a href="https://x.com/kichijojipm/status/1987871600092610748" target="_blank" rel="noopener"&gt;吉祥寺.pm公式のX Post&lt;/a&gt;
によれば、吉祥寺の美味しいもの情報でも可、ということなので、吉祥寺の美味しいものとして&lt;a href="https://kushidori.com/" target="_blank" rel="noopener"&gt;串鳥&lt;/a&gt;
をご紹介いたします。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;なんかアドベントカレンダー熱が再燃したので、初めての吉祥寺.pmアドベントカレンダーを作りました&lt;br&gt;&lt;br&gt;吉祥寺の美味しいもの情報でも可です&lt;a href="https://t.co/jVZZWhByxx"&gt;https://t.co/jVZZWhByxx&lt;/a&gt;&lt;a href="https://x.com/hashtag/kichijojipm?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#kichijojipm&lt;/a&gt;&lt;/p&gt;&amp;mdash; 吉祥寺.pm (@kichijojipm) &lt;a href="https://x.com/kichijojipm/status/1987871600092610748?ref_src=twsrc%5Etfw"&gt;November 10, 2025&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;h2 id="串鳥"&gt;串鳥&lt;/h2&gt;
&lt;p&gt;串鳥は北海道札幌市に本社を置き、本日時点で北海道に31店舗、仙台に5店舗、そして吉祥寺に店舗のある焼き鳥チェーン店です。
なお、筆者は現在北海道札幌市在住で、前述の通り吉祥寺にはほとんど行ったことがないため、串鳥吉祥寺南口店にも行ったことがありません。
本記事中の写真は串鳥東区役所前店で撮影しました。&lt;/p&gt;
&lt;p&gt;まさか誰も、吉祥寺.pmのアドベントカレンダーの2日目にして札幌の焼き鳥屋の話を書くとは思わなかろう。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://maps.app.goo.gl/M9yKLssBvjC35ocA9" target="_blank" rel="noopener"&gt;噂&lt;/a&gt;
によれば、吉祥寺南口店は駅から武蔵野公会堂方面に出た時、駅前すぐにあるようです。&lt;/p&gt;
&lt;p&gt;以下、串鳥で食べたものの写真を掲載します:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/soup_hu_616a7a957f8c45c4.jpg" alt="鶏ガラスープ" /&gt;
&lt;/p&gt;
&lt;p&gt;串鳥といえば鶏ガラスープ。これはサービスで出てくるもので、ポットで出てくるので好きなだけ飲めます。
写真を撮るのを忘れたのですが、お通しとしてこれとともに大根おろしが出てきます。&lt;/p&gt;
&lt;p&gt;噂によると吉祥寺南口店では大根おろしが出てこないという話もあるので、一度確認しに行きたいところです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/1_hu_b3bdd8da3a364227.jpg" alt="ひな皮、手羽先、つくね" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/2_hu_d25480778f96f822.jpg" alt="もちベーコン、豚精肉" /&gt;
&lt;/p&gt;
&lt;p&gt;ひな皮、手羽先、つくね(梅しそ)。
これは東区役所前店特有のやつだとおもうんですが、「店長のおまかせセット」なるものがあり、この日はそれが少し安いです、ということだったので頼みました。
もちベーコン、串鳥以外で見たことない気がする。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/3_hu_f1762baba73afc53.jpg" alt="岩下の新生姜豚巻、焼きカチョカヴァロ" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/4_hu_fb0bd1f7f36510bf.jpg" alt="焼きカチョカヴァロのメニュー" /&gt;
&lt;/p&gt;
&lt;p&gt;岩下の新生姜豚巻き、焼きカチョカヴァロ。
チーズが焼かれてるとなんか食べたくなりますよね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/5_hu_28b9ab4e6b989ae8.jpg" alt="ぽんぽち、豚味噌海苔巻き、豚しそ巻き" /&gt;
&lt;/p&gt;
&lt;p&gt;ぽんぽち、豚味噌海苔巻き、豚しそ巻き。
豚を巻いた、豚味噌海苔巻きと豚しそ巻きも串鳥といえば、のメニューの一つですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/6_hu_632fafdbeb96af79.jpg" alt="鳥ももハニーマスタード、チキン南蛮" /&gt;
&lt;/p&gt;
&lt;p&gt;鳥ももハニーマスタード、チキン南蛮。チキン南蛮はなんかフェアメニュー的なやつでした。&lt;/p&gt;
&lt;h2 id="コラボグッズ"&gt;コラボグッズ&lt;/h2&gt;
&lt;p&gt;最近、串鳥と&lt;a href="https://www.shimamura.co.jp/" target="_blank" rel="noopener"&gt;島村楽器&lt;/a&gt;
のコラボアイテムが発売されまして、地元企業とのコラボグッズは嬉しいな〜など思いながら買いました:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kushidori/images/strap_hu_9f02361a810daf57.jpg" alt="ギターストラップとピック" /&gt;
&lt;/p&gt;
&lt;p&gt;改めて島村楽器のお知らせ一覧を眺めていると、ここ最近で九州乳業やら矢場とんやらとのコラボもやっているらしく、各地元企業がフィーチャーされるというのは良いことだな、と思います。&lt;/p&gt;
&lt;h2 id="締めの一句"&gt;締めの一句&lt;/h2&gt;
&lt;p&gt;しってるか&lt;br&gt;
吉祥寺にも&lt;br&gt;
串鳥が&lt;/p&gt;</description></item><item><title>Tech Rock Festival 2025.11.22</title><link>https://blog.web-apps.tech/tech-rock-festival-2025-11-22/</link><pubDate>Wed, 26 Nov 2025 21:57:45 +0900</pubDate><guid>https://blog.web-apps.tech/tech-rock-festival-2025-11-22/</guid><description>&lt;p&gt;2025年11月22日に新宿SUNFACEで開催されたITエンジニアによるITエンジニアのためのライブイベントTech Rock Festival Day3に参加してきました。ハッシュタグは&lt;a href="https://x.com/hashtag/TechRockFestival" target="_blank" rel="noopener"&gt;#TechRockFestival&lt;/a&gt;
でした。
そういえば、昨冬に配信ライブやったんですが、それのブログ書いてなかった・・・&lt;/p&gt;
&lt;p&gt;イベント自体の開催経緯は&lt;a href="https://blog.web-apps.tech/tech-rock-festival-2023/"&gt;2023年のレポート&lt;/a&gt;
を参照のこと。&lt;/p&gt;
&lt;p&gt;毎年出演希望者が増えており、今年はなんと3回の開催となりました。例年同様開催地は新宿である一方、現在私は札幌在住で、ギターやエフェクターを持って移動するのがなかなか大変なため、今回はギターではなくボーカルでの参加としました。&lt;/p&gt;
&lt;h2 id="機材"&gt;機材&lt;/h2&gt;
&lt;p&gt;今回は初めてのボーカル・・・ということで、あまりむやみやたらに機材投入ができなかったのですが、それでも唯一どうしても使ってみたかったのがワイヤレスインイヤーモニターです。
以前ボーカルに少しだけ挑戦したときはボーカル慣れしていないというのもあり、自分の声を見失ってしまって全然音が取れなかったため、イヤホンで確実に自分の声をモニターしたい！と思ったのでした。
プロが大規模な会場で使うような大型のものから、近年では小型・安価なものも複数販売されていますが、その中でも今回は&lt;a href="https://amzn.to/4oXasaR" target="_blank" rel="noopener"&gt;Xvive XV-U4&lt;/a&gt;
を購入し、使用しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tech-rock-festival-2025-11-22/images/xvive_xv_u4_hu_37ee8687ce425653.jpg" alt="Xvive XV-U4" /&gt;
&lt;/p&gt;
&lt;p&gt;価格もそれなりに手頃(購入時点で34,100円)で、余分なケーブル等が必要無く、本番でも単に挿して音を流してもらえば良い、ということで選択しました。
モニタリングイヤホンはまぁ何でもいいかな、と思ったので、ある程度信頼できそうなメーカーのモニタリングイヤホンの中で価格が手頃だった&lt;a href="https://amzn.to/4oci0Fn" target="_blank" rel="noopener"&gt;Sennheiser IE100 PRO&lt;/a&gt;
を選びました。&lt;/p&gt;
&lt;p&gt;結果としては大満足で、PAさんには「ワイヤレスイヤモニを使いたい」ということを伝えていただけであとは当日合わせだったのですが、何の問題も無く使用することができました。
唯一の欠点はUSB micro-B充電である、という点ですね・・・&lt;/p&gt;
&lt;h2 id="バンドと演目"&gt;バンドと演目&lt;/h2&gt;
&lt;p&gt;今回のバンドは、バトルプログラマーヨシセという名前で、アニソンやらボカロやらをやるバンド、ということで結成しました。
なんなのだこの名前は・・・
今回もキーボードあり編成で豪華でしたが、なんやかんやどのバンドにもキーボードがいる感じになっていてすごいな、と感じましたね・・・&lt;/p&gt;
&lt;p&gt;面子:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://x.com/nasa9084" target="_blank" rel="noopener"&gt;nasa9084&lt;/a&gt;
(Vo)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/takasp_2350" target="_blank" rel="noopener"&gt;takasp&lt;/a&gt;
(Gt)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/capytan_el34" target="_blank" rel="noopener"&gt;capytan&lt;/a&gt;
(Ba)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/featherplain" target="_blank" rel="noopener"&gt;Hano&lt;/a&gt;
(Key)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/japan_rook" target="_blank" rel="noopener"&gt;うつぼ&lt;/a&gt;
(Dr)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;曲目:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;テレキャスタービーボーイ&lt;/li&gt;
&lt;li&gt;アンノウンマザーグース&lt;/li&gt;
&lt;li&gt;月光花&lt;/li&gt;
&lt;li&gt;怪獣&lt;/li&gt;
&lt;li&gt;ヒトリノ夜&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="次"&gt;次&lt;/h2&gt;
&lt;p&gt;打ち上げでも話をしたんですが、次はなんかこう、訳の分からん楽器で組んだ訳の分からんバンドをやりたいんですよね・・・
あと、打ち上げで、誰も知らないギターリフを弾いたらドボン、という闇のゲームに参加したんですが、全然指が動かなかったので、そろそろちゃんとギターも練習しないと何も弾けなくなるな、と思いました。&lt;/p&gt;</description></item><item><title>YAPC::Fukuoka 2025</title><link>https://blog.web-apps.tech/yapc-fukuoka-2025/</link><pubDate>Tue, 25 Nov 2025 23:42:00 +0900</pubDate><guid>https://blog.web-apps.tech/yapc-fukuoka-2025/</guid><description>&lt;p&gt;2025年11月14日〜15日に福岡工業大学で開催された、&lt;a href="https://yapcjapan.org/2025fukuoka/" target="_blank" rel="noopener"&gt;YAPC::Fukuoka 2025&lt;/a&gt;
に参加してきました。
YAPCはPerlのイベントで、“Yet Another Perl Conference&amp;quot;の略です。Xハッシュタグは前回に引き続き&lt;a href="https://x.com/hashtag/yapcjapan" target="_blank" rel="noopener"&gt;#yapcjapan&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.web-apps.tech/yapc-hakodate-2024/"&gt;前回の函館&lt;/a&gt;
から約1年ぶり、&lt;a href="https://blog.web-apps.tech/yapc_fukuoka_2017/"&gt;福岡での開催は2017年以来2度目&lt;/a&gt;
で、YAPC::Japanとしては初めての2日間開催となりました。&lt;/p&gt;
&lt;p&gt;今回は2日間フルでの開催ということで、前日木曜日に博多入り、金曜、土曜とYAPCに参加して、日曜日に帰るというスケジュールで臨みました。&lt;/p&gt;
&lt;h2 id="前日"&gt;前日&lt;/h2&gt;
&lt;p&gt;普段の業務で実は福岡にいるメンバーとの関わりがあるのですが、現職に入社してこの方福岡に出張の用事が無かったため、福岡のメンバーと会う機会が無かったので、昼ご飯を一緒に食べました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/oyakodon_hu_dcf5080206f1bb83.jpg" alt="親子丼" /&gt;
&lt;/p&gt;
&lt;p&gt;なんやかんや都合が合わなかったりして、全員と会うことはできなかったのですが、かれこれ数年オンラインでやりとりをしていた人と「初めまして〜」するのはなかなか感慨深いものがありますね。&lt;/p&gt;
&lt;p&gt;その後、カーシェアを借りて、&lt;a href="https://fukuoka-effect.jp/" target="_blank" rel="noopener"&gt;FUKUOKA EFFECT&lt;/a&gt;
に行きました。札幌はもう既に園芸店は冬期休業・時短営業に入っているため、普通に園芸店が営業していて、商品もしっかり並んでいる、というのはやはり暖地だな、というのを感じました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/fukuoka_effect_hu_3b880e35f6dc5b54.jpg" alt="FUKUOKA EFFECT" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/fukuoka_effect_2_hu_fd9f4501ef5143cc.jpg" alt="アガベ" /&gt;
&lt;/p&gt;
&lt;p&gt;アガベ、多肉、庭用の苗、プランター類が多い印象でした。札幌はプランター類が多い販売店は今のところ見つけられてないんですよね・・・&lt;/p&gt;
&lt;p&gt;エケベリア カンテ、白丁花、ヒサカキ「残雪」を購入しました。白丁花もヒサカキも観葉植物・・・とはちょっと違うと思いますが、斑入りで観葉っぽいし、シェードガーデン用にも良い、ということなので室内でも育つでしょう。多分。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/kante_hu_7dea4a3601ddc8bb.jpg" alt="エケベリア カンテ" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/hakuchouge_hu_957c97f70cc46cea.jpg" alt="白丁花" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/zansetsu_hu_b2e3d1582328d567.jpg" alt="ヒサカキ 残雪" /&gt;
&lt;/p&gt;
&lt;p&gt;夜ご飯は&lt;a href="https://www.makinoudon.jp/" target="_blank" rel="noopener"&gt;牧のうどん&lt;/a&gt;
で肉うどんを食べました。&lt;/p&gt;
&lt;h2 id="day-1"&gt;Day 1&lt;/h2&gt;
&lt;p&gt;扨、YAPC::Fukuoka 2025一日目ですが、朝からパンストック天神店に明太フランスを買いに行ったら遅刻しました・・・。パンストックが開店前から並ぶ店なのは知っていたんですが、平日なので多少マシかと踏んだんですが・・・結局1時間並びました。途中でYAPCのオープニングに間に合わないことは分かってたんですが、後に引くことはできませんでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/mentai_france_hu_6a0294591e501da8.jpg" alt="パンストックの明太フランス" /&gt;
&lt;/p&gt;
&lt;p&gt;パンストックのパン、何を買っても美味いので福岡に行く機会があれば是非。&lt;/p&gt;
&lt;p&gt;その後パンをもぐもぐしつつ会場へ。最寄りの福工大前駅から、あちこちに現在地と受付までの地図を置いておいてくれたので、迷わずにたどり着くことができました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-fukuoka-2025/images/map_hu_8e6b45a614f5efc1.jpg" alt="地図は助かる" /&gt;
&lt;/p&gt;
&lt;p&gt;一日目は以下のセッションを聴きました:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://fortee.jp/yapc-fukuoka-2025/proposal/8788e20c-bca5-4ff8-8c46-58673415f4f3" target="_blank" rel="noopener"&gt;「正規表現をつくる」をつくる&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortee.jp/yapc-fukuoka-2025/proposal/edd5ad15-3152-4f2c-9df1-6daad7944327" target="_blank" rel="noopener"&gt;なぜインフラコードのモジュール化は難しいのか - アプリケーションコードとの本質的な違いから考える&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortee.jp/yapc-fukuoka-2025/proposal/faef2cbb-9a07-4838-a67e-f8ce3615158e" target="_blank" rel="noopener"&gt;「データ無い！腹立つ！推測する！」から「データ無い！腹立つ！データを作る」へ ― ゼロからデータを作り、チームで育てられるようにするまで&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortee.jp/yapc-fukuoka-2025/proposal/0b931b36-e916-4461-bbf1-886419280759" target="_blank" rel="noopener"&gt;なぜThrottleではなくDebounceだったのか？ 700並列リクエストと戦うサーバーサイド実装のすべて&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortee.jp/yapc-fukuoka-2025/proposal/67512650-017e-4fea-ac00-23833e4221fc" target="_blank" rel="noopener"&gt;Learning Scalable DNS Resolvers from Hyper-Scalers&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortee.jp/yapc-fukuoka-2025/proposal/37827736-fba6-4e08-a9b4-a0abe131f65d" target="_blank" rel="noopener"&gt;SREのためのテレメトリー技術の探究 — モニタリングSaaS開発からAIOps・AIインフラまで&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;近年はだらだらと廊下で知り合いと話していることが多くてあまりセッションを聴くということをやっていなかったのですが、今回は結構話を聴きました。&lt;/p&gt;
&lt;p&gt;今回懇親会はDay 2の夜ということだったので、何人か捕まえて飲みに行きました。&lt;/p&gt;
&lt;h2 id="day-2"&gt;Day 2&lt;/h2&gt;
&lt;p&gt;二日目、もちろん遅刻しました。9時半は早いって。。。&lt;/p&gt;
&lt;p&gt;二日目は以下のセッションを聴きました:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ゲストゲストトーク&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fortee.jp/yapc-fukuoka-2025/proposal/5b6d3e99-45db-4c87-a369-f1b78a30e327" target="_blank" rel="noopener"&gt;やり方は一つだけじゃない、正解だけを目指さず寄り道やその先まで自分流に楽しむ趣味プログラミングの探求&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;二日を通して、すぎゃーんさんの趣味プログラミングの話が良かったですね。近年は何かとコードを書かないことがうれしいと言われがちですが、個人的には共感できなくて、コードを書くのが一番楽しくてこの仕事をしているのに、コードを書くところを持って行かれたら一番良いところがなくなっているだろう、と思っていたのですが、すぎゃーんさんの発表では「コードを書くのって楽しいよね！」を主張してくれて、なんだか救われたような気持ちになりました。&lt;/p&gt;
&lt;p&gt;二日目は懇親会があり、いろいろなひとと話せました。良かった良かった。ビールを飲むカメラマンや、次回のYAPCのco-organizerやろうよ、等と声をかけたりかけられたりする[@karupanerura](&lt;a href="https://x.com/karupanerura]" target="_blank" rel="noopener"&gt;https://x.com/karupanerura]&lt;/a&gt;
sanと&lt;a href="https://x.com/magnolia_k_" target="_blank" rel="noopener"&gt;@magnoria_k&lt;/a&gt;
sanを眺めたりもしました:&lt;/p&gt;</description></item><item><title>水の配達でゴタゴタした件</title><link>https://blog.web-apps.tech/amazon-water-delivery-issue/</link><pubDate>Thu, 06 Nov 2025 02:47:58 +0900</pubDate><guid>https://blog.web-apps.tech/amazon-water-delivery-issue/</guid><description>&lt;h3 id="context"&gt;Context&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;4階建てマンションの4階に住んでいる
&lt;ul&gt;
&lt;li&gt;宅配ボックスはオートロックの外側にある&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ローリングストックも兼ねて、ミネラルウォーターを購入し、煮炊きに使用している
&lt;ul&gt;
&lt;li&gt;ミネラルウォーターの銘柄等に特別なこだわりは無い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;自家用車を持っており、現実的な距離にコストコがある
&lt;ul&gt;
&lt;li&gt;コストコで水を買ってくることは可能だし、Amazonで買うより安い&lt;/li&gt;
&lt;li&gt;が、車から部屋までの持ち運びが大変(特にオートロックの鍵を開けるところ))なので宅配で購入したい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="timeline"&gt;Timeline&lt;/h3&gt;
&lt;h4 id="20251028"&gt;2025.10.28&lt;/h4&gt;
&lt;p&gt;Amazonでミネラルウォーター(550mL×24本×2箱)をセールで購入。
このとき、置き配設定は「置き配を使用しない」に変更した。
宅配ボックスに入れられてしまうと、取り出すだけでも大変。&lt;/p&gt;
&lt;p&gt;既に一度同じ設定で宅配ボックスに入れられてしまったことがある。
しかも2箱まとめて、ギリギリのサイズの宅配ボックスに。&lt;/p&gt;
&lt;p&gt;そのときは水注文後、水到着前に追加の注文で置き配設定を宅配ボックスに変更してしまった。
置き配設定が注文ごとではない可能性が高い(UI上から)ため、諦めて宅配ボックスと部屋を2往復した。&lt;/p&gt;
&lt;p&gt;その間宅配ボックスは開けっぱなしで。&lt;/p&gt;
&lt;h4 id="20251030-20時前"&gt;2025.10.30 20時前&lt;/h4&gt;
&lt;p&gt;Amazonから、宅配ボックスに配達した、とのメール通知がきた。ご丁寧に宅配ボックスの写真付きで。
この日は昼ご飯に出た以外は外出をしていない==配達時は在宅していたのは間違いないし、インターホンは鳴っていない==在宅確認もせず宅配ボックスに配達していることも明らか。&lt;/p&gt;
&lt;p&gt;メール通知の内容や、宅配ボックスの窓から覗く限り550mL×24本×2箱がまとめて一つの宅配ボックスに入っている。
流石にまとめて運ぶのはしんどいし、そもそも外から部屋まで自分で運ぶならコストコで買った方が安いのでサポートに連絡を入れることにした。&lt;/p&gt;
&lt;p&gt;サポートに連絡をしたところ、設定状況などから配送業者が独断で行ったものと断定、配送業者に荷物回収の上再配達するよう連絡してくれるとのこと。
また、配送業者には置き配設定を必ず確認するよう指導を入れてくれる、とのこと。&lt;/p&gt;
&lt;p&gt;サポート終了後に来たメールによると、配送業者には回収の上再配達をするよう依頼したので、対応に1~3日待てとのこと。
ローリングストックの水だし、まだ流石に凍るほどの気温ではないので気にせず承知した。&lt;/p&gt;
&lt;h4 id="20251106"&gt;2025.11.06&lt;/h4&gt;
&lt;p&gt;6日経ったが再配達がまだこないので再度サポートに連絡した。&lt;/p&gt;
&lt;p&gt;対応確認で時間を取らせるよりも、一度返金するので再注文してもらった方が早いのではないか、との提案があり、確かにそっちの方が確実っぽい気がしたので了承することに。
注文がセール中であったため、現在価格と差額が発生するが、その点はどうなるのか、と確認をしたところ、クーポン対応をする、との返答だった。
これで懸念は無くなったためその条件で了承し、問い合わせ終了。&lt;/p&gt;
&lt;p&gt;アカウントを確認したら差額分のギフトが登録されていたため再注文をした。&lt;/p&gt;
&lt;p&gt;サポートの人に聞いても仕方ないことだろうからきかなかったけど、宅配ボックスに入っている水はちゃんと回収されるのだろうか・・・&lt;/p&gt;
&lt;ins datetime="2025-11-12"&gt;
#### 2025.11.12追記
&lt;p&gt;後日談というか、今回のオチ。
水は結局回収されず、管理会社に連絡をして宅配ボックスをあけてもらえ、という謎の指示。
管理会社から費用を請求されたらそれもAmazonが支払う、とのこと。&lt;/p&gt;
&lt;p&gt;中の商品はどうすればよいのか、と聞いたところ、それはそのまま納めてくれ、とのこと。&lt;/p&gt;
&lt;p&gt;重いから注文している、とはいえ、運べない訳ではないので、回収をしてくれないのであれば管理会社に問い合わせて無闇な負担をかける意味も無く、今回は自分で運ぶことに。
まぁ、Amazonとしては商品はそのままあげるからごちゃごちゃ言わないで今回はそれでおさめてほしい、ということなんだろうけれど・・・&lt;/p&gt;
&lt;p&gt;配送業者にはちゃんと申し伝えておく、ということなので今回は2箱分がタダになったということで水に流すことにします。水だけに。
&lt;/ins&gt;&lt;/p&gt;</description></item><item><title>苗字が変わりました</title><link>https://blog.web-apps.tech/change-family-name/</link><pubDate>Thu, 18 Sep 2025 01:30:00 +0900</pubDate><guid>https://blog.web-apps.tech/change-family-name/</guid><description>&lt;p&gt;社内を含めて、私のことを実名で呼ぶ人は片手で数えられる程度しかいないので、実際問題として影響はほぼないのですが、6月2日付けで苗字が変わりました。&lt;/p&gt;
&lt;p&gt;なお、結婚ではありません&lt;/p&gt;
&lt;p&gt;多分ほとんどの人がやったことがない/やることがない手続きなので、ネタとして記録しておきます。&lt;/p&gt;
&lt;h2 id="経緯"&gt;経緯&lt;/h2&gt;
&lt;p&gt;というほど経緯は特にないのですが。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;両親が離婚した&lt;/li&gt;
&lt;li&gt;父方の親戚とは疎遠/あまり関わりたくない&lt;/li&gt;
&lt;li&gt;母方の親戚とは仲が良い&lt;/li&gt;
&lt;li&gt;結婚したとしても(一般に)男性側の姓に揃えることが多そうなので、自分の姓を変更する、という機会の発生率が低そう
&lt;ul&gt;
&lt;li&gt;そもそも結婚の予定はない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;結婚/離婚を伴わない改姓の手続きをやったことがある人は少なそう
&lt;ul&gt;
&lt;li&gt;多少調べたけど、あんまり個人のブログ記事とかでの情報は無い&lt;/li&gt;
&lt;li&gt;ブログネタとして面白そう&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;母方の氏の方が珍しい
&lt;ul&gt;
&lt;li&gt;珍しい名字の方が強い(?)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;実生活で苗字で呼ばれることはほぼないので影響が少なそう
面白半分でやってもまぁ大した問題はない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ということで改姓に至りました。&lt;/p&gt;
&lt;h2 id="手続き"&gt;手続き&lt;/h2&gt;
&lt;p&gt;改姓の手続きは大きく分けて2ステップで、まず家庭裁判所の許可を得て、その後住んでいる場所の市区町村役場で手続きをする、という形です。&lt;/p&gt;
&lt;p&gt;家庭裁判所からの許可は、&lt;a href="https://www.courts.go.jp/saiban/syurui/syurui_kazi/kazi_06_07/index.html" target="_blank" rel="noopener"&gt;子の氏の変更許可&lt;/a&gt;
から書式をダウンロードして、記入して、収入印紙、返信用切手、戸籍謄本と併せて住所地の家庭裁判所(私の場合は札幌地方・家庭裁判所)に送るだけです。
概ね悩まずに記入できるとは思いますが、「申し立ての動機」だけちょっと悩みました。が、結果としては大した理由は必要無くて、「父母の離婚に伴い、母の戸籍に入籍したいため」で十分でした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/change-family-name/images/reason_hu_49a9283e447359ef.jpg" alt="申立の理由記入欄" /&gt;
&lt;/p&gt;
&lt;p&gt;氏の変更手続き、とは言うものの、氏は戸籍に紐付いたラベルの様なものであるため、氏を変更する==父の戸籍から抜けて、母の戸籍に入るor自分の戸籍を別途立てる、という形になるようでした。&lt;/p&gt;
&lt;p&gt;一度自分の戸籍に分けてしまうと、母の戸籍に入ることはできないようで、私はどっちでも良いな、と思ったため、後で選択がきく、母の戸籍に入る、を選択しました。&lt;/p&gt;
&lt;p&gt;家庭裁判所に送る戸籍謄本はは、自分の戸籍謄本と父母の戸籍謄本と記載がありますが、父の戸籍に入っている状態では、自分の戸籍謄本(全部事項証明書)に父の情報も入っているため、父に別途戸籍謄本を取ってもらう必要はありませんでした。&lt;/p&gt;
&lt;p&gt;また、兄弟姉妹まとめて手続きをする場合、兄弟姉妹の情報も入っているため、複数戸籍謄本を取る必要はありませんでした。&lt;/p&gt;
&lt;p&gt;つまり、まとめると、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;子の氏の変更許可申立書 x 1
&lt;ul&gt;
&lt;li&gt;変更をしたい人数 x 800円の収入印紙を貼る&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;自分の戸籍謄本(全部事項証明書) x 1&lt;/li&gt;
&lt;li&gt;母の戸籍謄本(全部事項証明書) x 1&lt;/li&gt;
&lt;li&gt;返信用郵便切手 変更をしたい人数 x 封筒の切手代&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;を封筒に入れて家庭裁判所に送れば良い、です。&lt;/p&gt;
&lt;p&gt;問題が無ければ(私は妹の前科前歴がない、の記入漏れがあったため電話が来た)、2〜3日で許可するよ〜というお手紙が届きます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/change-family-name/images/result_hu_3cc5f15b25fa69db.jpg" alt="許可のお手紙" /&gt;
&lt;/p&gt;
&lt;p&gt;そのお手紙を持って市区町村役場(私の場合は札幌市東区役所)の戸籍関連手続きをする窓口に行けばシュッと手続きしてくれます。
そんなに回数こなす手続きでもなさそうなのに、スムーズに対応してくれました。&lt;/p&gt;
&lt;p&gt;場合により戸籍情報の更新に少し時間がかかるらしく、1週間以上経ってからマイナンバーカードの上書きをしにきてね、ということだったので、翌週もう一度区役所に行きました。&lt;/p&gt;
&lt;h2 id="その他変更の手続き"&gt;その他変更の手続き&lt;/h2&gt;
&lt;p&gt;結婚した人がよく言っていることでもありますが、氏が変わると当然クレジットカードなどの名義変更も必要です。
これが面倒だよ！ということだったのですが、マイナンバーパワーなのか、単に時代が良くなっているだけなのか、web/アプリで完結するものも多く、思ったよりは面倒では無いな、という印象でした。&lt;/p&gt;
&lt;p&gt;一部住民票等を求められるものもありましたが、片手で数えることができる程度でしたし、住民票はコンビニで発行することもできるので、まとめて印刷して、封筒に入れて、まとめて送るという感じで、それほど手間ではありませんでした。&lt;/p&gt;
&lt;p&gt;免許証の変更手続きも、警察署に行かなければならないのは若干面倒ではあるものの、窓口でほとんどの情報を印刷した書類を発行して、わずかな部分をちょちょいと記入して提出するだけでした。&lt;/p&gt;
&lt;p&gt;便利な世の中になったものですね。&lt;/p&gt;</description></item><item><title>"怠惰な人のための"キッシュ</title><link>https://blog.web-apps.tech/lazy-quiche/</link><pubDate>Tue, 19 Aug 2025 00:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/lazy-quiche/</guid><description>&lt;p&gt;キッシュ、という料理をご存じでしょうか。
惣菜や冷凍食品としても売っていることがありますし、スターバックスでもベーコンとほうれん草のキッシュが定番商品として売っているため、知っている人も多いかもしれません。&lt;/p&gt;
&lt;p&gt;とはいえ日本人にはあまりなじみがなく、家でキッシュを焼く、という人はあまり多くはないような気がしますが、作ってみると意外と簡単です。&lt;/p&gt;
&lt;p&gt;個人的には、料理が面倒な時こそキッシュ、という感じなので、雑に作れるレシピをご紹介します。
作業時間だいたい5分くらい、作り始めてから焼き上がるまで大体40分くらいでできあがります。
焼いている間はつきっきりである必要も無いので、混ぜて、流し込んで、焼くだけの簡単レシピです。&lt;/p&gt;
&lt;p&gt;材料はこちら:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;冷凍パイシート 1~2枚 (容器に敷けるくらい)&lt;/li&gt;
&lt;li&gt;卵 3個&lt;/li&gt;
&lt;li&gt;生クリーム 100mL&lt;/li&gt;
&lt;li&gt;具材&lt;/li&gt;
&lt;li&gt;塩&lt;/li&gt;
&lt;li&gt;こしょう&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;塩、こしょう、卵はまぁ家にあるでしょうし、冷凍パイシートは保存がきくので、作る直前に特別買ってくる必要があるのは生クリームくらいでしょうか。&lt;/p&gt;
&lt;p&gt;具材は適当な量を入れます。
ベーコンやほうれん草など、それっぽいものがあればそれで良い感じになりますし、生のほうれん草ではなく冷凍のほうれん草をつかってもいいですし、スーパーによっては冷凍のベーコン入りほうれん草ミックスを売っている場合もあり、そういったものをそのまま使っても良いでしょう。
わたしはキノコがダメなので入れませんが、キノコを入れてもよいでしょうし、ジャガイモやサーモン、ズッキーニ、ミニトマト、ベーコンの代わりにウインナーなどなど、案外雰囲気で適当なものを入れても美味しくなります。
汁気がなければ大体大丈夫です。多分。&lt;/p&gt;
&lt;p&gt;チーズがあれば雑にたくさん入れるとなお美味しいです。
我が家は最近はモッツァレラチーズ、カマンベールチーズ、パルミジャーノレッジャーノ、ピザチーズ、あたりを常備しているのでこのあたりを適当に入れています。&lt;/p&gt;
&lt;p&gt;今回は玉ねぎのみじん切りと挽肉を雑に炒めて、適当に味付けをして具材としました。&lt;/p&gt;
&lt;p&gt;焼くときの型は、キッシュ型があればもちろんそれを使ってもいいのですが、油を塗ったり、型に合わせてパイシートを伸ばしたりする必要があり、多少手間がかかるかもしれません。
私のオススメは取っ手が取れるフライパンです。
私はティファールの22cmのフライパンを使っていますが、各社似たようなものを出しており、ニトリだと1,000円前後くらいで買えると思います。
テフロン加工でパイ生地がくっつきませんし、取り出す際にも取っ手をつけて取り出せるので、取り回しがしやすく便利です。&lt;/p&gt;
&lt;p&gt;世間で売られている冷凍のパイ生地は11cm x 18cmくらいの長方形タイプと、18cm x 18cmくらいの正方形タイプの２種類がありますが、フライパンを使う場合はどちらでも大丈夫です。
長方形タイプの場合は2枚敷くとよさそうです。&lt;/p&gt;
&lt;p&gt;冷凍パイシートは調理しはじめに冷凍庫から出しておきます。
割とすぐ溶けるので、事前に出して解凍しておく必要はありません。&lt;/p&gt;
&lt;p&gt;また、この時点でオーブンを180度に予熱しておきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/lazy-quiche/images/pie-sheet_hu_76c3559a0db51fa2.jpg" alt="冷凍パイシート" /&gt;
&lt;/p&gt;
&lt;p&gt;型に合わせて伸ばしても良いのですが、私は面倒なので、フライパンに押し込める程度に溶けたらグッと押し込んでソレでよし、としています。
サイズもなんか足りていない気もしますが、気にしません。&lt;/p&gt;
&lt;p&gt;空焼きもした方がサクッと焼けて良い感じになるという噂もあるのですが、面倒なのでそれもしません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/lazy-quiche/images/cream_hu_22e6ba313ea0047d.jpg" alt="生クリーム" /&gt;
&lt;/p&gt;
&lt;p&gt;何故か札幌では200mL以上の生クリームしか販売が見当たらなかったので計量をします。生クリームは多分100mL==100gでは無いと思うのですが、まぁ大差は無いだろう、ということではかりで量っています(洗い物が減るので)。
100mL売りの生クリームがあれば、割高ではありますがそちらが便利だとは思います。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/lazy-quiche/images/egg_hu_5e8d1b6bb5e72fb4.jpg" alt="たまご" /&gt;
&lt;/p&gt;
&lt;p&gt;卵を3つ入れます。
こちらもサイズによって違いはあるとは思うのですが、面倒なのでサイズを気にせず3個、としています。
特に困ったことはありません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/lazy-quiche/images/salt_pepper_hu_e08ca3ca8e396ab3.jpg" alt="調味" /&gt;
&lt;/p&gt;
&lt;p&gt;塩こしょうを適当に入れます。
あればナツメグも入れると良い香りがします。
塩こしょうは思っているよりも多く入れるとちょうど良いです。
特に冷めてからも食べる場合は、気持ち多めに入れておきましょう。&lt;/p&gt;
&lt;p&gt;塩分が気になる人は、こしょうを多めにすると、なんとなく良い感じになります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/lazy-quiche/images/mix_hu_adf7d7efd0dfcc79.jpg" alt="具材" /&gt;
&lt;/p&gt;
&lt;p&gt;具材を入れて混ぜます。
私はあるものを適当に入れます。&lt;/p&gt;
&lt;p&gt;ほうれん草なども、生なら生のまま、冷凍なら凍ったまま入れてしまいます。
火が入るのに時間がかかったりしているのかもしれませんが、なんとかなります。
ちゃんと火が通ってないとおなかを壊しそうなもの(挽肉とか)や、火を通さないと食感が邪魔になったりしそうなものは予め火を通しておきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/lazy-quiche/images/fill_hu_1f1e75398e963268.jpg" alt="流し込む" /&gt;
&lt;/p&gt;
&lt;p&gt;ざっと混ぜ合わせたら、パイシートを敷いたフライパンに流し込みます。
テフロン加工フライパンなので、パイシートからはみ出ても大丈夫です。味には変わりありません。
見ての通り、パイ生地ものばしていないので、角がそのまま飛び出ています。&lt;/p&gt;
&lt;p&gt;ピザチーズとかがあれば適当に乗せておくと良い感じです。&lt;/p&gt;
&lt;p&gt;後は180度で20~30分くらい、卵液が固まるまで焼きます。
私は大体、雑にオーブンの最大時間にセットして、別途キッチンタイマーで20分くらいはかります。
上面が良い感じの焼き色になったら大体焼けているので、箸かなんかをさして、固まっているかどうか判別します。
固まっていなかったら適当に5分くらいずつ追加で焼く、という感じで、焼いている間は本を読むなどしています。&lt;/p&gt;</description></item><item><title>KubeCon Japan 2025</title><link>https://blog.web-apps.tech/kubecon-japan-2025/</link><pubDate>Wed, 25 Jun 2025 20:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/kubecon-japan-2025/</guid><description>&lt;p&gt;2025年6月17日/18日に開催された&lt;a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-japan/" target="_blank" rel="noopener"&gt;KubeCon + CloudNativeCon Japan 2025&lt;/a&gt;
に参加してきました。
また、その前日16日にCo-located Eventとして&lt;a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-japan/features-add-ons/co-located-events/#japan-community-day" target="_blank" rel="noopener"&gt;Japan Community Day&lt;/a&gt;
の一部としてDoc Sprintというイベントを実施しました。&lt;/p&gt;
&lt;p&gt;KubeConは&lt;a href="https://kubernetes.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
のイベントで、Cloud Native Computing Foundation (CNCF)が主催しています。
日本での開催は初めてということで、コミュニティからの期待も大きかったのですが、結果としては大盛況で、1500枚のチケットが完売だったということです。&lt;/p&gt;
&lt;h2 id="doc-sprint"&gt;Doc Sprint&lt;/h2&gt;
&lt;p&gt;本祭の前日に、Co-located eventという形で、会場の近く、NTT DOCOMO Open Lab in OdaibaでJapan Community Dayが開催されました。
Japan Community Dayでは、いくつかのセッションがあったほか、Kubernetes Upstream TrainingとDoc Sprintを開催しました。&lt;/p&gt;
&lt;p&gt;Doc SprintはKubernetesのドキュメント(の、特に日本語翻訳)にコントリビュートしよう！というイベントで、私や、&lt;a href="https://x.com/junya__okabe" target="_blank" rel="noopener"&gt;@junya__okabe&lt;/a&gt;
がKubernetes SIG Docs日本語localizationチームapproverとして初めてのコントリビュートをサポートするという企画でした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubecon-japan-2025/images/doc_sprint_hu_80abaacd5d398a74.jpg" alt="Doc Sprint・・・の前のice breakが盛り上がっている様子" /&gt;
&lt;/p&gt;
&lt;p&gt;当日はめちゃ簡単good-first-issueを用意することに成功したのもあって、実際に4人のnew contributorが誕生しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubecon-japan-2025/images/view_hu_c4a8767dc0a5cbe9.jpg" alt="NTT DOCOMO Open Lab in Odaibaからの景色" /&gt;
&lt;/p&gt;
&lt;p&gt;景色も大変良く、大変良い会場でした。&lt;/p&gt;
&lt;h2 id="kubecon本祭"&gt;KubeCon本祭&lt;/h2&gt;
&lt;p&gt;本祭は概ね廊下をうろうろして知り合いと話したり、ブースを冷やかしたりしていました。
ヘイシャもプラチナスポンサーということで、なかなか大きなブースを出していました:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubecon-japan-2025/images/sponsor_booth_hu_5b7025d879cac942.jpg" alt="LINEヤフー株式会社のブース" /&gt;
&lt;/p&gt;
&lt;p&gt;Job boardもあり、ペンが置いてあったので、コントリビューター募集のメッセージを書いておきました(&amp;ldquo;Job&amp;quot;ではないけど・・・):&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubecon-japan-2025/images/job_board_hu_13460ee6b943f455.jpg" alt="Job board" /&gt;
&lt;/p&gt;
&lt;p&gt;あんまりたくさんのセッションは聴かなかったのですが、一番面白かったのは初日の最後のコマに発表のあった、&lt;a href="https://kccncjpn2025.sched.com/event/1x716/2-node-kubernetes-a-reliable-and-compatible-solution-xin-zhang-guang-hu-microsoft?iframe=yes&amp;amp;w=100%25&amp;amp;sidebar=yes&amp;amp;bg=no" target="_blank" rel="noopener"&gt;2-Node Kubernetes&lt;/a&gt;
というセッションでした。
要するに、HA構成K8sが3ノード以上必要なのはetcdが3ノード必要だからで、etcdは3台あっても1台までしか落とせないので、ならば(leader electionさえなんとかすれば)耐故障性は3ノードと変わらないし、edgeでコストを落とすこともできてハッピーじゃん、という話でした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubecon-japan-2025/images/2-node_kubernetes_hu_48bc70affa2d7125.png" alt="2-Node Kubernetes" /&gt;
&lt;/p&gt;
&lt;p&gt;2日目の昼には、Kubernetes Upstream Training Japanの一員として、発表をすることもできました。
個人のプロポーザルは通らなかったんですけど、パネルディスカッションのプロポーザルが通って本当に良かった。&lt;/p&gt;</description></item><item><title>梅仕事2025</title><link>https://blog.web-apps.tech/ume-2025/</link><pubDate>Thu, 12 Jun 2025 21:13:00 +0900</pubDate><guid>https://blog.web-apps.tech/ume-2025/</guid><description>&lt;p&gt;今年も梅の季節がやってきました。
なんかスーパーで全然梅を見ないんですけど、いまどきの札幌の民は梅仕事はしないんですかね？
今年はちょっと変わった梅の実を使いたいなぁ、ということで、&lt;a href="https://www.satofull.jp/products/detail.php?product_id=1606090" target="_blank" rel="noopener"&gt;ふるさと納税で紫宝梅『ミスなでしこ(R)』&lt;/a&gt;
という、紫色の梅を手に入れました。
きれいなピンク色のシロップができるということで、楽しみですね。&lt;/p&gt;
&lt;p&gt;1kgで寄付金額8,000円、4kgで寄付金額20,000円ということで、どうせ2kgは使いますから、4kgの方を選びました。
一応説明に寄れば大玉(M〜L)ということなんですが、結構小ぶり(M?)の実が多い様に感じました。
まぁ例年スーパーで買う青梅はLLのものを買うため、余計にそう見えた、ということもあるかも知れませんが。&lt;/p&gt;
&lt;p&gt;スーパーで買うような物と比べて、かなり傷物が少なく、結局不安があってハネた実は1つという好成績でした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2025/images/ingredients_hu_c6162dc8851a3228.jpg" alt="梅以外の材料" /&gt;
&lt;/p&gt;
&lt;p&gt;今回使う梅以外の材料はこちら。梅の方に変化を入れたので、色がきれいにでそうな氷砂糖、上白糖、ホワイトリカーです。
梅酒を1瓶、梅シロップを2瓶作り、余った1kgは妹に分けてあげました。&lt;/p&gt;
&lt;p&gt;瓶はPET製の果実酒瓶を選びました。&lt;a href="https://blog.web-apps.tech/ume-2024/"&gt;昨年使ったモノ&lt;/a&gt;
とは違うんですけど、同じく角形で収納に便利そうです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2025/images/zoom_hu_b561f27062660048.jpg" alt="ズームアップ" /&gt;
&lt;/p&gt;
&lt;p&gt;実の形がまん丸ではなくて、すこしとがったような形をしています。&lt;/p&gt;
&lt;p&gt;作り方は例年通り、洗って、拭いて、ヘタを取って、砂糖と積み重ねて、梅酒の方には酒を入れる、というだけ。
店頭にあった瓶の在庫の都合で2日に分けて作業しました:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2025/images/day-1_hu_88034f52ae3f8db7.jpg" alt="Day1" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2025/images/day-2_hu_9e3e0be84c8e5d58.jpg" alt="Day2" /&gt;
&lt;/p&gt;
&lt;p&gt;例年、梅仕事をした後は以前に漬けた梅酒を味見しているので、今年も味見しておきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2025/images/shiwa_hu_14eaeb5b45f4da49.jpg" alt="しわしわ" /&gt;
&lt;/p&gt;
&lt;p&gt;昨年の梅酒は何の影響か、すごくしぼんだ状態ですね。
1年くらいだと、多少しわが入っていることは多くて、その後また酒を吸って膨らんでくるんですが、ここまでしぼんでしまってもまた膨らんでくるんでしょうか？&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2025/images/last_year_hu_6f284584b7c23bd5.jpg" alt="昨年の梅酒" /&gt;
&lt;/p&gt;
&lt;p&gt;ほんの少し水を足した、いわば水の梅酒割、くらいの割り方で割ってみました。
1年モノとは思えないくらい丸い感じで、コレはホワイトリカーが良かったのか、中ザラ糖が良かったのか、悩ましいところです。&lt;/p&gt;
&lt;p&gt;そして1年越しに気づいたんですが、昨年のラベルが1年間違っていました。
上からマッキーで訂正しておきました。&lt;/p&gt;
&lt;p&gt;また来年。&lt;/p&gt;</description></item><item><title>チカの南蛮漬け</title><link>https://blog.web-apps.tech/chika-namban/</link><pubDate>Tue, 04 Feb 2025 23:18:01 +0900</pubDate><guid>https://blog.web-apps.tech/chika-namban/</guid><description>&lt;p&gt;この季節一番美味い魚といえば、そう、チカですね。私はチカを見たら買わないではいられないという奇病にかかっているため、今シーズンは既に3〜4回購入しています。&lt;/p&gt;
&lt;p&gt;チカはワカサギを少し大きくしたような小型の魚で、今時期は比較的大型のものが安価に販売されています。
&lt;a href="https://ja.wikipedia.org/wiki/%E3%83%81%E3%82%AB" target="_blank" rel="noopener"&gt;Wikipedia&lt;/a&gt;
によるとチカは20cmほどに育つ、ということですが、今回買ったチカはおおよそ全長13cm程度でした。&lt;/p&gt;
&lt;p&gt;当然(?)チカは南蛮漬けにしていきます。&lt;/p&gt;
&lt;p&gt;材料はこちら:
&lt;img loading="lazy" src="https://blog.web-apps.tech/chika-namban/images/ingredients_hu_1d49f0daff0f2374.jpg" alt="チカの南蛮漬け材料" /&gt;
&lt;/p&gt;
&lt;p&gt;チカ、玉ねぎ、などです。今回は彩りに玉ねぎを入れました。パプリカは高いので、玉ねぎのみとすると経済的です。
我が家では地獄の様な量の玉ねぎを入れます。
今時期の札幌で販売されている玉ねぎは大変大きく、写真では玉ねぎ2.5個が映っていますが、実際のところ流石に多いな、と思ったので1つ減らしましたが、それでもかなりの量です。&lt;/p&gt;
&lt;p&gt;また、漬け地として、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;酢 1cup&lt;/li&gt;
&lt;li&gt;砂糖 大さじ6&lt;/li&gt;
&lt;li&gt;醤油 大さじ8&lt;/li&gt;
&lt;li&gt;出汁 2cup&lt;/li&gt;
&lt;li&gt;唐辛子小口切り 適量
を混ぜておきます。野菜の量を抑えれば半分でも良いです。
また、私は出汁パックをつかって出汁を引きますが、面倒であれば出汁の素を湯で溶いたものを使用しても良いと思います。
その場合、出汁の素は塩や砂糖が含まれている場合が多いと思いますので、適宜醤油や砂糖の量は調節してください。
面倒であれば気にしなくても誤差だとは思います。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;まずは野菜をスライスしていきます。以下は前回作ったときの玉ねぎスライス動画です:
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/O-PiiDexo40?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
この時は小ぶりな玉ねぎだったので、10個ほど投入した気がします。&lt;/p&gt;
&lt;p&gt;野菜スライスのコツは、包丁を十分に研いでおく、という点にあると思います。前の日までに研いでおいてください。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/chika-namban/images/sliced_hu_31f19dbe8408b6c4.jpg" alt="スライスした野菜" /&gt;
&lt;/p&gt;
&lt;p&gt;次にチカの処理をします。
流石にこのサイズになると&lt;a href="https://blog.web-apps.tech/tika-no-nanbanduke/"&gt;以前やったように&lt;/a&gt;
単に揚げてはい終わり、というわけにはいかず、うろこを取り、頭を取り、背から開いてワタと背骨を取ります。
Youtubeで調べると解説されている動画もあるので参考にすると良いと思います。
やはりコツは包丁をよく研いでおくということです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/chika-namban/images/opened_hu_9973c1dbf3febb9e.jpg" alt="開いたチカ" /&gt;
&lt;/p&gt;
&lt;p&gt;あとの手順は小さいチカやワカサギで南蛮漬けを作るのと同様です。&lt;/p&gt;
&lt;p&gt;片栗粉をつけて揚げて:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/chika-namban/images/fried_hu_1f30d714833000ee.jpg" alt="揚げる" /&gt;
&lt;/p&gt;
&lt;p&gt;漬け地に突っ込んで:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/chika-namban/images/soaked_hu_c5c902db489e87b1.jpg" alt="漬け地に浸す" /&gt;
&lt;/p&gt;
&lt;p&gt;野菜も入れて:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/chika-namban/images/soaked_all_hu_3d1479c7a97bbbcb.jpg" alt="野菜も浸す" /&gt;
&lt;/p&gt;
&lt;p&gt;適当な容器に入れて一晩冷蔵庫で寝かせます:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/chika-namban/images/stay_hu_f962bbc80ebfe80e.jpg" alt="一晩つける" /&gt;
&lt;/p&gt;
&lt;p&gt;この量だと、一人だと2~3日はこれを食べ続けることになります。ご注意ください。&lt;/p&gt;</description></item><item><title>ベトナムに行ってきた</title><link>https://blog.web-apps.tech/trip-to-vietnam/</link><pubDate>Sat, 21 Dec 2024 00:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/trip-to-vietnam/</guid><description>&lt;p&gt;標題の通り、ベトナムに行ってきました。主目的は学生時代からの付き合いであるところの&lt;a href="https://x.com/chamaharun" target="_blank" rel="noopener"&gt;@chamaharun&lt;/a&gt;
と&lt;a href="https://x.com/ne_saya" target="_blank" rel="noopener"&gt;@ne_saya&lt;/a&gt;
の結婚式ですが、ベトナムまで行ってそれだけというのもアレなので、多少観光もしてきました。&lt;/p&gt;
&lt;h2 id="0日目-札幌東京ホーチミン"&gt;0日目: 札幌→東京→ホーチミン&lt;/h2&gt;
&lt;p&gt;先日札幌に引っ越したため、結婚式会場のフーコック島までは、新千歳→羽田→ホーチミン→フーコックという経路でした。
乗り継ぎの都合なども勘案して、21:15新千歳発、深夜に羽田発、早朝ホーチミン着という計画としたため、せっかくなのでホーチミンで一泊することとしました。
新千歳をでるときはなんとなくおなかが空いていなかったので夕食抜いてしまおうか、と思ったのですが、なんだかんだ羽田で飛行機を待っていたらおなかが空いたので、お値段が手頃だったうどんを食べました:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/udon_haneda_hu_ef3fee521d2668ea.jpg" alt="羽田空港で食べた高級うどん1160円" /&gt;
&lt;/p&gt;
&lt;p&gt;国際線ではエコノミーでも酒が飲めるんだった、ということで、寝酒に梅酒をもらったのですが、十分にエアコンが効いてるし、と思ってストレートで頼んだら、結構多くて結局ちびちびやっていたら飲みきれませんでした:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/umeshu_hu_a090a5a7a935bb3.jpg" alt="梅酒ストレート" /&gt;
&lt;/p&gt;
&lt;p&gt;機内食で朝食、パンケーキですって声も聞こえていた気がしたけど、手元に来たのはフレンチトースト:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/in_flight_morning_hu_21bfe0edfde34721.jpg" alt="機内食モーニング" /&gt;
&lt;/p&gt;
&lt;h2 id="1日目-ホーチミン"&gt;1日目: ホーチミン&lt;/h2&gt;
&lt;p&gt;ホーチミンまではJAL便だったので、ギリギリまで日本語で楽ちんでした。&lt;/p&gt;
&lt;p&gt;ホーチミンに早朝について、ホテルのチェックインもできないので、フロントの人に「どうしたら良いと思う？」と聞いたところ、すぐ横にカフェがあるから、いったん休憩して、その辺散歩してきたら良い感じにホテルからのシャトルバスがでるから、それで観光行ってきたら良いんじゃない？ということだったので、それに従うことにしました。&lt;/p&gt;
&lt;p&gt;まずはすぐお隣のHIGHLANDS COFFEEで一発目のベトナムコーヒー:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/highlands_coffee_hu_f1898d01f3bc8e01.jpg" alt="HIGHLANDS COFFEE" /&gt;
&lt;/p&gt;
&lt;p&gt;HIGHLANDS COFFEEはチェーンで、ベトナムでは割とどこにでもあるというか、スタバのようなモノらしい。スタバはスタバで同様にその辺にあるけど。全然数が違う。日本で言うと、ドトールとかその辺かな、と思いました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/vietnam_coffee_with_condensed_milk_hu_634892b1ec22492c.jpg" alt="ベトナムコーヒー" /&gt;
&lt;/p&gt;
&lt;p&gt;35k VND==大体200円くらい。安い。氷がやばい。&lt;/p&gt;
&lt;p&gt;そして道路。噂に聞いていたベトナムの原付。やばい。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/bike_bike_bike_hu_82482fce32b85828.jpg" alt="大量の原付" /&gt;
&lt;/p&gt;
&lt;p&gt;散歩していたら見つけたミニストップ。おでん(という名前の多分別の食べ物)が売られていたけど、この気温で食べる奴おるんか、とは思いましたね:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/ministop_hu_a5599c6a5baa1807.jpg" alt="ミニストップ" /&gt;
&lt;/p&gt;
&lt;p&gt;そうこうしている間に良い感じの時間になったので、ホテルに戻ってシャトルバスに乗車。
行き先一覧に高島屋があって、安心感ありそうだったし、ユニクロとかが入っていて、現地限定のやつとかあるのかしら、と気になったのでいったん高島屋へ。
見慣れたロゴで安心感がすごい:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/uniqlo_hu_9554fbd0d93886c6.jpg" alt="ユニクロの看板" /&gt;
&lt;/p&gt;
&lt;p&gt;限定のTシャツはあったけど、日本でＴシャツ買うのと変わらない値段で悩んでいる間に買ってくるのを忘れました。&lt;/p&gt;
&lt;p&gt;高島屋は安心感がありまくって、ロイズがあったり:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/royce_hu_ebaa1adef5d758d3.jpg" alt="ROYCE&amp;rsquo;" /&gt;
&lt;/p&gt;
&lt;p&gt;白い恋人があったり:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/shiroi_koibito_hu_dc146d8eae4f589a.jpg" alt="白い恋人" /&gt;
&lt;/p&gt;
&lt;p&gt;で、ちょっと安心感がありすぎるくらいでした。&lt;/p&gt;
&lt;p&gt;一通り高島屋を見た後は徒歩で無印良品へ。株主なので。(特に関係ないけど)&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/muji_hu_a8cf84dec3b1fed0.jpg" alt="無印良品" /&gt;
&lt;/p&gt;
&lt;p&gt;無印では限定のトートバッグが売っていて、これは結構安かったので買いました:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/muji_tote_bag_hu_d27bf3fc0c7ccb43.jpg" alt="無印良品のトートバッグ" /&gt;
&lt;/p&gt;
&lt;p&gt;79k VNDなので、日本円だと500円弱くらい。&lt;/p&gt;
&lt;p&gt;他にもダイソーがありました:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/daiso_hu_7ee1bc691086bc89.jpg" alt="DAISO" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/daiso_ad_hu_426a62097201b6ba.jpg" alt="DAISOの店頭の商品紹介" /&gt;
&lt;/p&gt;
&lt;p&gt;店頭のポップ、日本語で書かれていたけど誰が読むのか。&lt;/p&gt;
&lt;p&gt;マツモトキヨシがあったり:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/matsukiyo_hu_5046c883c688d644.jpg" alt="マツモトキヨシ" /&gt;
&lt;/p&gt;
&lt;p&gt;焼き肉ライクがあったり:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/yakiniku_like_hu_88166ceaad1e66f2.jpg" alt="焼き肉ライク" /&gt;
&lt;/p&gt;
&lt;p&gt;ビアードパパがあったり:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/beard_papa_hu_8502f26dbc9c8a94.jpg" alt="ビアードパパ" /&gt;
&lt;/p&gt;
&lt;p&gt;日本のお店がそこここにあるので、気持ち的にはすごくなんか安心感(?)がありました。&lt;/p&gt;
&lt;p&gt;一発目のベトナム飯はコムタムという奴にしました。肉が美味そうだったので。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/com_tam_moc_hu_22e907547d7cc230.jpg" alt="COM TAM MOC" /&gt;
&lt;/p&gt;
&lt;p&gt;結果としてはあまり好みではなく、肉は固く、完食できませんでした。すまん。
お値段としては800円くらい？ベトナムの飯としてはちょい高めかもしれないですね。&lt;/p&gt;
&lt;p&gt;お口直しにスタバ。strawberry açaí with Lemonade 75k VND。まぁ、日本とあんまり変わらない値段設定ではありますね。普通に美味しい。安心。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/trip-to-vietnam/images/strawberry_acai_lemonade_hu_5cf27fcfeeb964ad.jpg" alt="strawberry açaí with Lemonade" /&gt;
&lt;/p&gt;</description></item><item><title>Kubernetes Upstream Training in Japan at CNDW2024</title><link>https://blog.web-apps.tech/kubernetes-upstream-training-in-japan-at-cndw2024/</link><pubDate>Mon, 02 Dec 2024 23:58:44 +0900</pubDate><guid>https://blog.web-apps.tech/kubernetes-upstream-training-in-japan-at-cndw2024/</guid><description>&lt;p&gt;最近イベントレポートばっかりですね？&lt;/p&gt;
&lt;p&gt;先日、&lt;a href="https://event.cloudnativedays.jp/cndw2024" target="_blank" rel="noopener"&gt;CloudNative Days Winter 2024&lt;/a&gt;
というイベントがございまして、私自身は結局いろいろの都合で参加しなかったのですが、これに合わせる形で&lt;a href="https://community.cncf.io/events/details/cncf-cloud-native-community-japan-presents-joint-meetup-kubernetes-upstream-training-in-japan-at-cndw2024/" target="_blank" rel="noopener"&gt;Kubernetes Upstream Training in Japan&lt;/a&gt;
をオンライン・オフラインハイブリッド形式でで実施しました。&lt;/p&gt;
&lt;p&gt;資料等は&lt;a href="https://github.com/kubernetes-sigs/contributor-playground/tree/master/japan/cndw-2024" target="_blank" rel="noopener"&gt;GitHub&lt;/a&gt;
にアップロードされています。&lt;/p&gt;
&lt;p&gt;Kubernetes Upstream Training in Japanは、&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
にコントリビュートをしてみたいけど何から始めれば良いのかわからないという人向けに、初めてコントリビュートをするまで、の解説をしたり、コントリビュート体験をしてもらったりするイベントです。実際に現役でKubernetes関連プロジェクトのメンテナー・コントリビューターが講師陣をしているという豪華なイベントです。&lt;/p&gt;
&lt;p&gt;今回は渋谷スクランブルスクエアにあるCyberAgentさんのセミナールームを借りて、オンライン・オフラインのハイブリッドで開催しました。&lt;/p&gt;
&lt;p&gt;引き続き&lt;a href="https://github.com/kubernetes/website" target="_blank" rel="noopener"&gt;kubernetes/website&lt;/a&gt;
にコントリビュートしたい方も募集しています。よろしくお願いします。&lt;/p&gt;</description></item><item><title>植物用のライトスタンドを作る</title><link>https://blog.web-apps.tech/light-stand-for-plants/</link><pubDate>Thu, 28 Nov 2024 23:39:00 +0900</pubDate><guid>https://blog.web-apps.tech/light-stand-for-plants/</guid><description>&lt;p&gt;最近園芸にハマっておりまして、鉢植えを本棚の上に置いているのですが、部屋の向きや、季節の都合で日当たりがあまり良くなく、ライトを設置したくなってきました。しかし、本棚の周りにはライトを設置できるような突起物はなく、賃貸であるため壁に穴を空けるのも避けたいところです。ならばスタンドを、というところですが、手頃な値段のモノはサイズが微妙であったり、あるいはオーダーメイドだとサイズはぴったりだけど高い、ということで、手頃な値段でぴったりのモノを手に入れたい、という意志の元、DIYでライトスタンドを作ることにしました。&lt;/p&gt;
&lt;p&gt;材料はこちら:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/light-stand-for-plants/images/material_hu_8922e8f5646c0081.jpg" alt="ライトスタンドの材料" /&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0199" target="_blank" rel="noopener"&gt;フレームS B 1000mm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0200" target="_blank" rel="noopener"&gt;フレーム S B 600mm&lt;/a&gt;
x2&lt;/li&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0202" target="_blank" rel="noopener"&gt;フレーム S B 300mm&lt;/a&gt;
x2&lt;/li&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0203" target="_blank" rel="noopener"&gt;フレーム S B 100mm&lt;/a&gt;
x2&lt;/li&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0263" target="_blank" rel="noopener"&gt;マルチコネクタインナーS B&lt;/a&gt;
x2&lt;/li&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0264" target="_blank" rel="noopener"&gt;マルチコネクタアウターS B&lt;/a&gt;
x2&lt;/li&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0216" target="_blank" rel="noopener"&gt;インナーキャップS B&lt;/a&gt;
x 6&lt;/li&gt;
&lt;li&gt;&lt;a href="https://g-fun.jp/products/detail.php?item=SGF-0163" target="_blank" rel="noopener"&gt;ストレートコネクタインナーS&lt;/a&gt;
x2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://g-fun.jp/" target="_blank" rel="noopener"&gt;G-Fun&lt;/a&gt;
という、アルミフレームの一種で、中空のアルミの棒をコネクタで繋ぐことでいろいろなモノを作れます、という商品です。簡単に組み立てられて、剛性もある、ということで何かと便利な奴です。強度データもすべて揃っており、すべり、引き抜き、モーメントなど、どれくらい耐えられるのかも分かるため、安心して荷重のかかるものを作ることもできます。&lt;/p&gt;
&lt;p&gt;総額は(近所のDCMで)4,387円でした。&lt;/p&gt;
&lt;p&gt;今回必要な工具は3mmと4mmのレンチとゴムハンマーです。&lt;/p&gt;
&lt;p&gt;今回は何十キロもあるものを乗せる訳ではないため、見た目優先で一番細いSシリーズを選択しました。&lt;/p&gt;
&lt;p&gt;本棚の天板サイズが幅1200mm、奥行き339mmなので、1000mm + ストレートコネクタ + 100mm + ストレートコネクタ + 100mmで概ね1200mmということにしました。将来組み替えたり、パーツを他のものに使い回したりする可能性を考慮して、ホームセンターでシュッと買える既製品で組める様にしましたが、よりぴったりサイズのものを作りたい人はG-Funオンラインストアでは切断してもらうこともできますし、専用カッターも販売されています。足は奥行きに合わせた長さ、高さは手元の植物にあわせて600mmとしました。高さは後で変更するかも。&lt;/p&gt;
&lt;p&gt;端が露出する部分はキャップをつけて・・・(ここでゴムハンマーを使う)&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/light-stand-for-plants/images/cap_hu_d2dec12cc78074c8.jpg" alt="キャップをつけた図" /&gt;
&lt;/p&gt;
&lt;p&gt;一番長い棒と短い棒を繋いで・・・(ここで3mmのレンチを使う)&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/light-stand-for-plants/images/straight_connect_hu_10030d4f827f3b0f.jpg" alt="ストレート" /&gt;
&lt;/p&gt;
&lt;p&gt;良い感じに組み立てて・・・完成！&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/light-stand-for-plants/images/completed_hu_2b9c22a826d948dd.jpg" alt="完成して設置したモノ" /&gt;
&lt;/p&gt;
&lt;p&gt;あまりにもぴったりすぎて、ちょっとずれただけで足が落ちてしまいそうなので、家にあった&lt;a href="https://amzn.to/3Z917Rt" target="_blank" rel="noopener"&gt;鬼ピタ&lt;/a&gt;
を小さく切って固定しました。ガッチリ張り付いて、かつ剥がしたいときにはきれいに剥がせるので一本持っておくのがオススメです。何かと便利。&lt;/p&gt;
&lt;p&gt;実際に電気をつけた様子がこちら:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/light-stand-for-plants/images/light_hu_4a40965b29b4dbbe.jpg" alt="電気をつけた状態" /&gt;
&lt;/p&gt;
&lt;p&gt;良い感じですね。Amazonでライティングレールやら何やらを買ったので、後でつけようと思っています。&lt;/p&gt;</description></item><item><title>札幌に引っ越した件</title><link>https://blog.web-apps.tech/move-to-sapporo/</link><pubDate>Fri, 08 Nov 2024 17:33:18 +0900</pubDate><guid>https://blog.web-apps.tech/move-to-sapporo/</guid><description>&lt;p&gt;標題の通りです。転職はしていません。&lt;/p&gt;
&lt;p&gt;札幌の人、かまってください。&lt;/p&gt;
&lt;p&gt;今のところ月に1回〜2回程度東京に行く予定があるので、関東の人もかまってください。&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>YAPC::Hakodate 2024</title><link>https://blog.web-apps.tech/yapc-hakodate-2024/</link><pubDate>Mon, 21 Oct 2024 10:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/yapc-hakodate-2024/</guid><description>&lt;p&gt;今月の頭に北海道は函館市で開催された&lt;a href="https://yapcjapan.org/2024hakodate/" target="_blank" rel="noopener"&gt;YAPC::Hokkaido&lt;/a&gt;
に参加してきました。&lt;/p&gt;
&lt;p&gt;YAPCはPerlのイベントで、“Yet Another Perl Conference&amp;quot;の略です。twitterハッシュタグは前回に引き続き&lt;a href="https://twitter.com/hashtag/yapcjapan" target="_blank" rel="noopener"&gt;#yapcjapan&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;前回の&lt;a href="https://blog.web-apps.tech/yapc-hiroshima-2024/"&gt;広島&lt;/a&gt;
に続いて、2024年二度目のYAPCで、北海道では&lt;a href="https://blog.web-apps.tech/yapc_hokkaido_2016/"&gt;2026年の札幌&lt;/a&gt;
以来の開催ですね。&lt;/p&gt;
&lt;p&gt;生まれ/親の実家が函館ということで個人的にはなじみのある土地で、いつも通り個人スポンサーで一般参加の予定だったんですが、&lt;a href="https://x.com/karupanerura" target="_blank" rel="noopener"&gt;@karupanerura&lt;/a&gt;
さんからお誘いを受けたので、まぁせっかくならということで、いつぶりか分からない、当日スタッフとしての参加でした。担当としては「広報」という名前ではあったものの、札幌からの参加(先月末に埼玉から札幌に引越をしました)で車があること、カンファレンススタッフ経験がありなんとなくで動けること、コアスタッフがバタバタしていて上手く役割分担ができなかったこと、などから実際には買い出しやら遊撃やらをするような感じのムーブをしました。&lt;/p&gt;
&lt;h2 id="前夜祭"&gt;前夜祭&lt;/h2&gt;
&lt;p&gt;前夜祭は函館市民会館での開催でした。久々にチラシのトートバッグ詰め作業をしたり、&lt;a href="https://x.com/__papix__" target="_blank" rel="noopener"&gt;@papix&lt;/a&gt;
さんとともに&lt;a href="https://www.hk-r.jp/" target="_blank" rel="noopener"&gt;寿司&lt;/a&gt;
や&lt;a href="https://www.hasesuto.co.jp/" target="_blank" rel="noopener"&gt;やきとり弁当&lt;/a&gt;
を受け取りに車で回ったり、ビールが足りなかったので買いに行ったり。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-hakodate-2024/images/beer_hu_6435adaa8211de1b.jpg" alt="買いに行ったビール" /&gt;
&lt;/p&gt;
&lt;p&gt;皆さん寿司は食べることができましたか。私は食べられませんでした。割とこういう場面ではメシが余っている印象がありますが、即完売でしたね。。。&lt;/p&gt;
&lt;p&gt;スタッフでも腹を空かせている人がそこそこいたようで、追い出し後にピザを注文するなどの一幕もありました。以下は治安の悪い顔でピザとビールを摂取するカメラマンの様子です:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-hakodate-2024/images/yagi_hu_1ed9f5f5a3eee514.jpg" alt="ピザビール" /&gt;
&lt;/p&gt;
&lt;h2 id="本祭"&gt;本祭&lt;/h2&gt;
&lt;p&gt;本祭ははこだて未来大学で開催され、参加者の皆さんは専用のバスがチャーターされたようです。はこだて未来大学は車がないと厳しいですからね・・・&lt;/p&gt;
&lt;p&gt;当日スタッフとしては朝はスポンサーブース設営手伝い、受付手伝い、うろうろしてブースの写真を撮ってDiscordに流す、ゴミ袋やスケッチブックを買いに行く、問題がありそうなところの報告や、人手が足りないところの手伝いをする、などをしました。&lt;/p&gt;
&lt;p&gt;トークプロポーザルは残念ながら通らなかったのですが、それをそのまま突っ込んだLTプロポーザルは通り、それなりにウケたので大変良かったですね。&lt;/p&gt;
&lt;iframe class="speakerdeck-iframe" style="border: 0px; background: rgba(0, 0, 0, 0.1) padding-box; margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 100%; height: auto; aspect-ratio: 560 / 315;" frameborder="0" src="https://speakerdeck.com/player/07ecbdcb9e4341e4a7f310ab52d9d23b" title="e-book title normalization" allowfullscreen="true" data-ratio="1.7777777777777777"&gt;&lt;/iframe&gt;
&lt;p&gt;終わった後は最終居残り組として残って、余ったノベルティを懇親会場に運ぶ、ということで車を積極活用しました。&lt;/p&gt;
&lt;h2 id="懇親会"&gt;懇親会&lt;/h2&gt;
&lt;p&gt;車を運転して懇親会場に向かいましたが、&lt;a href="https://japan.perlassociation.org/" target="_blank" rel="noopener"&gt;JPA&lt;/a&gt;
が運転代行代を持ってくれるということで、懇親会でビールなどを摂取することができました。助かりますね。&lt;/p&gt;
&lt;p&gt;運転代行って初めて使ったんですが、なかなか面白い経験でした。&lt;/p&gt;
&lt;p&gt;懇親会後、案の定(?)papixさんはベロベロでした:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-hakodate-2024/images/papix_hu_87237ceceb8c59c9.jpg" alt="papix" /&gt;
&lt;/p&gt;
&lt;p&gt;風物詩という感じがしてわびさび(?)ですね(?)&lt;/p&gt;
&lt;p&gt;当日スタッフは大変久々ではありましたが、たのしかったですね。&lt;/p&gt;</description></item><item><title>Tech Rock Festival 2024.09</title><link>https://blog.web-apps.tech/tech-rock-festival-2024-09/</link><pubDate>Mon, 09 Sep 2024 23:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/tech-rock-festival-2024-09/</guid><description>&lt;p&gt;2024年9月8日に新宿SUNFACEで開催されたITエンジニアによるITエンジニアのためのロックイベントTech Rock Festival 2024.09に参加してきました。&lt;/p&gt;
&lt;p&gt;イベント自体の開催経緯は&lt;a href="https://blog.web-apps.tech/tech-rock-festival-2023/"&gt;昨年のレポート&lt;/a&gt;
を参照のこと。&lt;/p&gt;
&lt;p&gt;実は今年の開催は7月にもあり、7月は観客として参加する予定だったのですが、ちょうど開催タイミングに新型コロナウイルス感染症に感染し、参加することができず、9月の回のみの参加と相成りました。&lt;/p&gt;
&lt;h2 id="機材"&gt;機材&lt;/h2&gt;
&lt;p&gt;ギターは昨年に引き続き&lt;a href="https://jp.yamaha.com/products/musical_instruments/guitars_basses/el_guitars/pacifica/pac_100.html" target="_blank" rel="noopener"&gt;YAMAHA PACIFICA 112V&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;弦も変わらずElixir Optiweb 09-42です。今シーズン(?)は弦もいろいろ試しはしたんですが、やはり一番保つのはElixirですね・・・それでも月に一度は換えていますが。他に良い弦があれば教えてください。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tech-rock-festival-2024-09/images/effector_board_hu_62f1f117dcc80712.jpg" alt="エフェクターボード" /&gt;
&lt;/p&gt;
&lt;p&gt;エフェクターは昨年使用したZOOM G1 FOURをメルカリで売却し、代わりにGT-1000Coreを導入しました。G1 FOURは同時使用できるエフェクトが5コだったのでかなり縛りがある感じだったんですが、GT-1000Coreは(値段も高いですが)かなり自由に音を作れて楽しいですね。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.boss.info/jp/products/gt-1000/" target="_blank" rel="noopener"&gt;GT-1000&lt;/a&gt;
はBluetoothも搭載しており、iOSアプリでパッチの編集ができる様なのですが、GT-1000Coreはできず、とはいえこの小さい画面ですべてをいじるのは大変だな、ということで調査をしたところ、MIDIでパッチをいじることができる、しかも&lt;a href="https://www.soundhouse.co.jp/products/detail/item/289772/" target="_blank" rel="noopener"&gt;BleutoothでワイヤレスでMIDIをいじれるようにするアイテムもある&lt;/a&gt;
ということが分かったため、基本的にはこれを使ってiPad miniのGT-1000用アプリでパッチの編集をしていました。&lt;/p&gt;
&lt;p&gt;また、クラウドファンディングで入手した&lt;a href="https://www.casio.com/jp/dimensiontripper/" target="_blank" rel="noopener"&gt;CASIOのDIMENSION TRIPPER&lt;/a&gt;
も投入しました。元々&lt;a href="https://www.soundhouse.co.jp/products/detail/item/170995/" target="_blank" rel="noopener"&gt;ワイヤレス+チューナー+小型マルチでぴったりサイズのボード&lt;/a&gt;
を使っていたのでDIMENSION TRIPPERを乗せることができなかったため、&lt;a href="https://www.soundhouse.co.jp/products/detail/item/302589/" target="_blank" rel="noopener"&gt;ボード自体&lt;/a&gt;
も新調しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tech-rock-festival-2024-09/images/dimension_tripper_extend_hu_cac3ab252830fe99.jpg" alt="トランスミッターの延長部" /&gt;
&lt;/p&gt;
&lt;p&gt;DIMENSION TRIPPERの個人的不満点として、トランスミッターのギターとの接続部がプラスチックで取り付けにくい、傷などが不安という点があります。これを解消するために、部屋のその辺に転がっていたレザーの端切れと適当な金具を使って延長パーツのようなモノを作って接続部としました。便利。&lt;/p&gt;
&lt;p&gt;コレをつかって変な音を出そうと画策もしたのですが、結局いい音ができず、これはただの拡張スイッチの様な形式で使用しました。&lt;/p&gt;
&lt;p&gt;チューナーはまっすぐ貼り付けたハズだったのに何故か気づいたら曲がっていました。一度直したのに、また曲がったので、こいつは性根が曲がっているのだと思います。もちろんチューナーとしても使っていますが、ミュートスイッチとしても便利に活用しています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tech-rock-festival-2024-09/images/plug_hu_f4e750471d4d4cdc.jpg" alt="OYAIDEのめっちゃ小さいプラグ" /&gt;
&lt;/p&gt;
&lt;p&gt;パッチケーブルは引き続き&lt;a href="https://www.soundhouse.co.jp/products/detail/item/263398/" target="_blank" rel="noopener"&gt;OYAIDEのソルダーレス&lt;/a&gt;
ですが、最近は&lt;a href="https://shop.oyaide.com/products/p-63l_6mm.html" target="_blank" rel="noopener"&gt;OAYIDE P-6.3L&lt;/a&gt;
/&lt;a href="https://shop.oyaide.com/products/p-63tl_6mm.html" target="_blank" rel="noopener"&gt;OYAIDE P-6.3TL&lt;/a&gt;
という奴が頭が極小で最高なのでコレを使いたいと思って、DIMENTION TRIPPERの接続はコレを使っています。制御信号なので別にこんなに良いプラグを使わなくても良いのですが、小さいボードとしては小さい頭のプラグは正義です。&lt;/p&gt;
&lt;p&gt;パワーサプライは引き続き&lt;a href="https://www.soundhouse.co.jp/products/detail/item/329785/" target="_blank" rel="noopener"&gt;VITAL AUDIO VA-05 MkII&lt;/a&gt;
。GT-1000Coreをメルカリで買った時に&lt;a href="https://shop.oyaide.com/products/dc-3398_current_doubler_cable.html" target="_blank" rel="noopener"&gt;OYAIDEのカレントダブラーケーブル&lt;/a&gt;
が付属していた(正直単体で買うにはたっけえケーブルですね)ので、これを使っていますが問題無く動いています。若干短いので長いものが欲しい気もするんですが、高いので困っています。&lt;/p&gt;
&lt;p&gt;エフェクターボードからアンプまではやはり引き続き&lt;a href="https://www.soundhouse.co.jp/products/detail/item/23263/" target="_blank" rel="noopener"&gt;CANARE LC03&lt;/a&gt;
だったか&lt;a href="https://www.soundhouse.co.jp/products/detail/item/23269/" target="_blank" rel="noopener"&gt;CANARE LC05&lt;/a&gt;
だったか(長さが違うだけ)を使いました。&lt;/p&gt;
&lt;p&gt;アンプは今回は(他のバンドとの兼ね合いを考慮して)JCM2000でした。今回はGT-1000Coreに音の良いアンプシミュレータが入っているためリターン挿しでアンプに依存しない安定したサウンドを目指しました(というほどがっちり音作りしたわけではないけど)。&lt;/p&gt;
&lt;p&gt;ピックは&lt;a href="https://www.soundhouse.co.jp/products/detail/item/277561/" target="_blank" rel="noopener"&gt;MASTER 8 JAPAN INFINIX-U JAZZ type with Hard Grip 0.88mm&lt;/a&gt;
と&lt;a href="https://www.yodobashi.com/product/100000001003269103/" target="_blank" rel="noopener"&gt;PlanetWaves by D&amp;rsquo;Addario Medium&lt;/a&gt;
を使いました。後者は昔Black ICEという名称で売っていて、すごく好きなんですよね。最近全然手に入らなくて困っていたのですが、秋葉原のヨドバシに何故か在庫があり、購入することができました。&lt;/p&gt;</description></item><item><title>builderscon 2024</title><link>https://blog.web-apps.tech/builderscon-2024/</link><pubDate>Tue, 13 Aug 2024 18:53:37 +0900</pubDate><guid>https://blog.web-apps.tech/builderscon-2024/</guid><description>&lt;p&gt;builderscon 2019が終わった後、牧さんからbuildersconを引き継ぎ、&lt;a href="https://blog.web-apps.tech/builderscon-tokyo-2020"&gt;builderscon tokyo 2020をやるぞ！と言ってから&lt;/a&gt;
新型コロナウイルス感染症が流行り、そして&lt;a href="https://blog.builderscon.io/entry/cancel-tokyo-2020" target="_blank" rel="noopener"&gt;開催を見送り&lt;/a&gt;
、数年が経ち、そして今年、ようやく、buildersconを開催することができました。&lt;/p&gt;
&lt;p&gt;公式ブログで記事を書いているときにも気持ちを書こうとはしたんですが、なんかもういろんな気持ちがぐっちゃぐちゃになってて、文章にまとまらないんですよね。ということで飲み会に誘ってください。
ちょっとしばらくはバタバタする見込みになっており、必ず行きます！とは言えない状況なのですが、できるだけ行きます。&lt;/p&gt;</description></item><item><title>大吉祥寺.pm</title><link>https://blog.web-apps.tech/dai-kichijoji-pm/</link><pubDate>Tue, 16 Jul 2024 13:18:40 +0900</pubDate><guid>https://blog.web-apps.tech/dai-kichijoji-pm/</guid><description>&lt;p&gt;東京都は吉祥寺で開催されているイベント、吉祥寺.pmの10周年記念イベントとして&lt;a href="https://kichijojipm.connpass.com/event/314917/" target="_blank" rel="noopener"&gt;大吉祥寺.pm&lt;/a&gt;
が2024年7月13日に開催されたので、参加してきました。
参加者がたくさんいることももちろんそうですが、10周年というのは本当にすごいですね。&lt;/p&gt;
&lt;p&gt;受付をしたら名札とおみくじをもらいました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/dai-kichijoji-pm/images/omikuji_hu_f1edcd52a7ca8707.jpg" alt="おみくじ" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/dai-kichijoji-pm/images/name_tag_hu_d513c59c2adf74e3.jpg" alt="名札" /&gt;
&lt;/p&gt;
&lt;p&gt;ランチに食べたいものを書いておくことで、スタッフの方でよしなにグルーピングをしてくれるそうでした。こういうイベントではなんだかんだ知り合いと話をしてしまいがちなので、新しいコミュニケーションが促進される企画は大変良いモノですね。&lt;/p&gt;
&lt;p&gt;全体の内容としては、テーマが「いままでと、これから」ということもあってか、技術をゴリゴリというよりはコミュニケーションやキャリア、歴史といったモノが中心でした。
トークとしては一定のコンテキストで、という感じではあったものの、より広く適用できそうと言うか、上手にコミュニケーションをしていくのが大切ですね、という内容で納得感のあるものでした。&lt;/p&gt;
&lt;p&gt;昼ご飯は和牛油そばという奴を食べたんですが、すごく味が濃くて多かったです:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/dai-kichijoji-pm/images/lunch_hu_7dfd0cac7e0f02b7.jpg" alt="油そば和牛マシ" /&gt;
&lt;/p&gt;
&lt;p&gt;私が現在住んでいる埼玉県朝霞市から吉祥寺は電車だといったん新宿まで出て(右下のほう)、その後吉祥寺に向かう(左)というルートを取る必要があり面倒だったので車で行ったのですが、車だと結構近いですね。
駐車場は多少高いようにも思えますが、上限のある駐車場が結構たくさんあるので、駐める場所にも困りませんでした。
朝から一日大吉祥寺.pmに参加し、懇親会に出て、二次会で深夜まで駐めていても2,500円ということで、終電を気にしたり、暑い中乗り換えをしたり・・・ということを考えれば全然安いかな、と思いました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/dai-kichijoji-pm/images/fee_hu_dd55d4e2f7562a11.jpg" alt="駐車料金" /&gt;
&lt;/p&gt;
&lt;p&gt;というわけで改めて、10年続いているイベントはすごい！&lt;/p&gt;</description></item><item><title>OSC 2024 Hokkaido</title><link>https://blog.web-apps.tech/osc-2024-hokkaido/</link><pubDate>Tue, 16 Jul 2024 12:45:17 +0900</pubDate><guid>https://blog.web-apps.tech/osc-2024-hokkaido/</guid><description>&lt;p&gt;2024年6月29日に開催された&lt;a href="https://event.ospn.jp/osc2024-do/" target="_blank" rel="noopener"&gt;Open Source Conference 2024 Hokkaido&lt;/a&gt;
に行ってきました。&lt;/p&gt;
&lt;p&gt;例年参加しているので概ねいつも通り、という感じではあるので一応レポートを残しておきます。&lt;/p&gt;
&lt;p&gt;今回は諸諸の都合により前日の日中に札幌入りして、土曜日は本祭、日曜日の昼の便で帰るという弾丸ツアーでした。&lt;/p&gt;
&lt;p&gt;金曜日の夜は関係者前夜祭で石鍋亭へ。変わらず美味しいですね&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/osc-2024-hokkaido/images/ishinabe_hu_99337748969778af.jpg" alt="石鍋亭" /&gt;
&lt;/p&gt;
&lt;p&gt;石鍋亭へ向かう途中見てしまったダイコクドラッグの閉店のお知らせ。札幌駅は工事の関係もあってどんどんいろんな店が閉店していてさみしいですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/osc-2024-hokkaido/images/daikoku_close_hu_81ed530cb3ad099.jpg" alt="閉店のお知らせ" /&gt;
&lt;/p&gt;
&lt;p&gt;当日のブースの様子はこんな感じです。一応Kubernetes SIG Docs Japanese Localization teamとしての参加ということにしてありましたのでスライドを流すなどしていましたが、冷房直撃でちょっと寒かったので、あまりここには座っておらず、その辺をふらふらしていました。
ステッカーの類くらいは作っても良かったかな、と(毎年)思っています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/osc-2024-hokkaido/images/booth_hu_7f3cfb9600c05649.jpg" alt="ブースの様子" /&gt;
&lt;/p&gt;
&lt;p&gt;昼ご飯は特に決めていなかったのでカレーカンファレンスに。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/osc-2024-hokkaido/images/curry_hu_6f9161a21da652de.jpg" alt="カレー" /&gt;
&lt;/p&gt;
&lt;p&gt;道警さんのブースで投資詐欺に注意！というチラシも配っていました&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/osc-2024-hokkaido/images/hokkaido_police_hu_7e8a235709d7945b.jpg" alt="チラシ" /&gt;
&lt;/p&gt;
&lt;p&gt;最後は新千歳空港でかま栄のかまぼこを買って帰りました。本当は大丸で買いたいんだけど、今回は時間が無かったので。。。札幌、あるいは小樽にに行く人は是非買って下さい。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/osc-2024-hokkaido/images/kamaei_hu_f54a9bc3330373c4.jpg" alt="かま栄のかまぼこ" /&gt;
&lt;/p&gt;</description></item><item><title>Expression Knob</title><link>https://blog.web-apps.tech/expression-knob/</link><pubDate>Mon, 17 Jun 2024 00:52:00 +0900</pubDate><guid>https://blog.web-apps.tech/expression-knob/</guid><description>&lt;p&gt;エクスプレッションペダル、というものがありますね。ギター用のエフェクターやその他電子楽器等のボリュームやらパラメータやらを足で操作するためのペダルですが、その中身は非常に単純です。とはいえペダルとして作るには上手く駆動部分を作る必要があって簡単にはいかないのと、足で操作せずとも、マルチエフェクターのフットボリューム機能を使えるとエフェクトループの任意の場所でボリュームを調整できると便利ということがあり、より単純な形として「エクスプレッションノブ」を作成したので記録しておきます。&lt;/p&gt;
&lt;p&gt;使った材料は次の通り:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://akizukidenshi.com/catalog/g/g115219/" target="_blank" rel="noopener"&gt;可変抵抗/ボリューム (10kΩ/Bカーブ)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://akizukidenshi.com/catalog/g/g100253/" target="_blank" rel="noopener"&gt;ボリューム用ツマミ&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://akizukidenshi.com/catalog/g/g113305/" target="_blank" rel="noopener"&gt;3.5mmステレオミニジャック&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://akizukidenshi.com/catalog/g/g117121/" target="_blank" rel="noopener"&gt;プラスチックケース (30mm x 40mm x 20mm)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;秋月電子で揃えれば260円+送料程度で済みます。後で紹介する既製品だと安くても4,000円程度はしますから激安ですね。&lt;/p&gt;
&lt;p&gt;操作対象のエフェクターは&lt;a href="https://www.boss.info/jp/products/gt-1000core/" target="_blank" rel="noopener"&gt;BOSS GT-1000CORE&lt;/a&gt;
です。聞いたところによるとHX STOMPとかはエクスプレッションペダルの仕様が違うようなので注意。&lt;/p&gt;
&lt;p&gt;ボリュームは10kΩBのモノであれば多少サイズが違ったりスライドボリュームだったりしても大丈夫なはずですが、端子の仕様が違ったり(多分大体同じですが・・・)、対応しているツマミが違ったりすると思いますので、適宜調整してください。ツマミはお好みのモノを選んでください。&lt;/p&gt;
&lt;p&gt;今回は気分で3.5mmのミニジャックを使用しましたが、これもステレオであれば任意のジャックで良いはずです。エフェクター側は基本的に6.3mmの標準プラグだと思うので、6.3mmのジャックだとケーブルが手に入りやすくて便利かも知れません。今回は隙間に突っ込みたかったので小さい端子を選びました。どうせパッチケーブルは自分で作りますし。&lt;/p&gt;
&lt;p&gt;ケースも任意のモノで問題ないでしょう。サイズが良い感じだったのと、コントロール信号が通るだけなら良いか、ということで今回はプラスチックケースにしました。&lt;/p&gt;
&lt;p&gt;回路図は次の通り:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/expression-knob/images/circuit_diagram_hu_ed16cc2168e070.png" alt="回路図" /&gt;
&lt;/p&gt;
&lt;p&gt;実体配線図としてはこんな感じ:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/expression-knob/images/circuit_wiring_hu_8389d3c9d3a67981.png" alt="実体配線図" /&gt;
&lt;/p&gt;
&lt;p&gt;その辺にあった適当なケーブルで配線をして、適当にケースに穴をあけ、パーツを組み込んで完成です。穴は適当な細いドリルで下穴を開けた後にステップドリルなどを使ってちょうど良い大きさになるまで穴を拡張するときれいに空けることができます。プラケースなら電動ドリルを買わなくても、手で十分空けることができます。&lt;/p&gt;
&lt;p&gt;あとは手頃なステレオケーブル(ヘッドホン用とかがその辺に転がっていますね？ソレを使ってテストをしましょう)でエフェクターと接続して、動作確認をすれば良いでしょう。&lt;/p&gt;
&lt;p&gt;まだエフェクターボードには組み込んでいませんが、便利に活躍してくれることを祈っています。&lt;/p&gt;
&lt;p&gt;なお、作るのは面倒だけどほしい！という人は既製品も販売されているようです:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lep-international.jp/products/el-garatge-expression-knob" target="_blank" rel="noopener"&gt;El Garatge&lt;/a&gt;
(5,573円)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lagoonsound.com/expv-p/" target="_blank" rel="noopener"&gt;LAGOON SOUND&lt;/a&gt;
(3,800円)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/335349/" target="_blank" rel="noopener"&gt;electro-harmonix&lt;/a&gt;
(コンパクトエフェクタータイプ 7,680円)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/279762/" target="_blank" rel="noopener"&gt;Old Blood Noise Endeavors&lt;/a&gt;
(スライダータイプ 8,250円)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>梅仕事2024</title><link>https://blog.web-apps.tech/ume-2024/</link><pubDate>Mon, 03 Jun 2024 12:18:34 +0900</pubDate><guid>https://blog.web-apps.tech/ume-2024/</guid><description>&lt;p&gt;6月ですよ！今年も梅酒を漬けましたので記録をしておきます。&lt;/p&gt;
&lt;p&gt;今年の材料は以下の通り:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2024/images/ingredients_hu_7fd2d8a7556d79e3.jpg" alt="材料" /&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;梅: ヤオコー和光丸山台店で売っていた南高梅1袋。多分1kgくらい。&lt;/li&gt;
&lt;li&gt;砂糖: 日新製糖の中ザラ糖1kg。中ザラ糖でつけるのは2020年以来ですね。&lt;/li&gt;
&lt;li&gt;酒: 美峰酒類製造、酔仙酒造販売のホワイトリカー「果実の泉」1.8L&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2024/images/white_liquor_hu_b13dd164e9e7b690.jpg" alt="果実の泉" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2024/images/bottling_hu_d06888a63e97db52.jpg" alt="梅と砂糖を積んだ様子" /&gt;
&lt;/p&gt;
&lt;p&gt;今年はカインズで&lt;a href="https://www.p-life-house.jp/goods_HB-6936.html" target="_blank" rel="noopener"&gt;PET製の果実酒瓶&lt;/a&gt;
が売っていたので、そちらを使用しました。丸いガラス瓶は「ぽい」んですけど、割れそうで気を遣うし、床面効率も良くないんですよね。&lt;/p&gt;
&lt;p&gt;最後にテプラでレシピを記録。これまで買っていたガラス瓶はだいたい説明書にメモを書いておく欄があって、それを切って使っていたのですが、今回はなかったのでテプラでメモをすることにしました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2024/images/recipe_hu_2345ab8ac353eb5a.jpg" alt="レシピメモ" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.web-apps.tech/ume-2023"&gt;昨年の梅酒&lt;/a&gt;
はこんな感じになっていました:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2024/images/ume-2023_hu_ccb2457afc67c098.jpg" alt="梅酒2023" /&gt;
&lt;/p&gt;
&lt;p&gt;昨年はホワイトリカーに氷砂糖という、かなり標準的なレシピで作りましたので、ザ・梅酒という感じのスッキリとした味でした。&lt;/p&gt;
&lt;p&gt;また来年お会いしましょう！&lt;/p&gt;</description></item><item><title>git-gutter to diff-hl</title><link>https://blog.web-apps.tech/git-gutter-to-diff-hl/</link><pubDate>Sun, 26 May 2024 11:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/git-gutter-to-diff-hl/</guid><description>&lt;p&gt;これまで、emacs上で行ごとの変更状況を表示するのに、&lt;a href="https://github.com/emacsorphanage/git-gutter" target="_blank" rel="noopener"&gt;git-gutter.el&lt;/a&gt;
を使用してきました。&lt;a href="https://github.com/nasa9084/dotfiles/commit/5aa3c33a095a40e80332607f1f84a71e15761623" target="_blank" rel="noopener"&gt;約4年前&lt;/a&gt;
から使用しており、今現在でも問題なく動いているため特に不満はなかったのですが、emacs-jpで&lt;a href="https://github.com/dgutov/diff-hl" target="_blank" rel="noopener"&gt;diff-hl&lt;/a&gt;
の話を聞き、見た目が良いな、と思ったのでdiff-hlに移行しました。&lt;/p&gt;
&lt;p&gt;git-gutterの見た目:
&lt;img loading="lazy" src="https://blog.web-apps.tech/git-gutter-to-diff-hl/images/git-gutter_hu_628204324883c09.png" alt="git-gutter" /&gt;
&lt;/p&gt;
&lt;p&gt;diff-hlの見た目:
&lt;img loading="lazy" src="https://blog.web-apps.tech/git-gutter-to-diff-hl/images/diff-hl-mode_hu_e81cc8fa6d05477a.png" alt="diff-hl" /&gt;
&lt;/p&gt;
&lt;p&gt;fringeを使用するようになったことでフレームが少しスッキリしました。&lt;/p&gt;
&lt;p&gt;問題が一点だけあって、私は普段macOS上で&lt;a href="https://bitbucket.org/mituharu/emacs-mac" target="_blank" rel="noopener"&gt;emacs-mac&lt;/a&gt;
を使用しているのですが、frameを複数に分割したとき、一番左のwindowでは問題なく表示されたのですが、右側のwindowでは縦フチが表示されませんでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/git-gutter-to-diff-hl/images/right-window_hu_82bda2de4ff187bf.png" alt="右側のwindowで縦フチが表示されない問題" /&gt;
&lt;/p&gt;
&lt;p&gt;emacsを起動した後に手動で&lt;code&gt;(fringe-mode '(9 . 8))&lt;/code&gt;などとしてfringeの幅を広げると上手く表示される一方、&lt;code&gt;default-frame-alist&lt;/code&gt;に広げた幅を入れても何故か上手く表示がされない状態で起動してきたため、diff-hl-modeを有効化した後に幅を広げないと上手く調整がきかないのか、と思ったので、次のように&lt;code&gt;diff-hl-mode&lt;/code&gt;を呼び出して&lt;code&gt;set-frame-parameter&lt;/code&gt;する形で解消しました:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; show git diff parameter on fringe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;diff-hl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;:ensure&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;:diminish&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;:hook&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;magit-post-refresh&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;diff-hl-magit-post-refresh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;:init&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;global-diff-hl-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; somehow the left line is not drawn well without setting left-fringe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;;; parameter after diff-hl-mode is enabled&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;diff-hl-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;set-frame-parameter&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;left-fringe&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;diff-hl-flydiff-mode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;正直イマイチ感がすごいので、良い解決方法をご存じの方がいたら教えてください。&lt;/p&gt;</description></item><item><title>Kubernetes Upstream Training Japan 2024-03</title><link>https://blog.web-apps.tech/kubernetes-upstream-training-japan-2024-03/</link><pubDate>Mon, 01 Apr 2024 23:20:00 +0900</pubDate><guid>https://blog.web-apps.tech/kubernetes-upstream-training-japan-2024-03/</guid><description>&lt;p&gt;かれこれ半月ほど経ってしまったのですが。&lt;/p&gt;
&lt;p&gt;昨年末にCloud Native Computing Foundationの日本チャプターとしてCloud Native Community Japanが発足しまして、そのサブチャプターとしてKubernetes Upstream Training Japanが立ち上がり、第一回のイベントとして&lt;a href="https://community.cncf.io/events/details/cncf-cloud-native-community-japan-presents-cncj-kubernetes-upstream-training-japan-2024-03/" target="_blank" rel="noopener"&gt;Kubernetes Upstream Training Japn 2024-03&lt;/a&gt;
を実施しました。&lt;/p&gt;
&lt;p&gt;資料などは&lt;a href="https://github.com/kubernetes-sigs/contributor-playground/tree/master/japan/cncj-202403" target="_blank" rel="noopener"&gt;GitHubのリポジトリ&lt;/a&gt;
に上がっているので見ていただくと良いのですが、要するに&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
にコントリビュートをしてみたいけど何から始めれば良いのかわからない・・・という人向けに、Kubernetesコミュニティではどのように普段コミュニケーションをとっていて、どういう手順でコントリビュートをすれば良いのか、という解説をしたり、実際にコントリビュート体験をしてもらったりするイベントでした。&lt;/p&gt;
&lt;p&gt;なにせKubernetesというのは世界中で使われている大きなソフトウェアで、英語がさらっと読める人は良いのですが、日本人としてはやはり英語が苦手だという人も多いですし、まして技術力が求められ(そうに見え)るところに飛び込んでいくというのはなかなか勇気が要るモノです。そんな人の背中を押して、日本のKubernetesコミュニティをもっと盛り上げていこう、というのがこのイベントの目的であるわけです。&lt;/p&gt;
&lt;p&gt;次回開催はいつになるか不明ではありますが、Kubernetes(特に&lt;a href="https://github.com/kubernetes/website" target="_blank" rel="noopener"&gt;kubernetes/website&lt;/a&gt;
)にコントリビュートしたい！という人は積極的にサポートしていく所存でありますのでお気軽にご連絡ください。&lt;/p&gt;</description></item><item><title>情報認識学研究室 工藤先生の最終講義に行ってきました</title><link>https://blog.web-apps.tech/prml-prof-kudo-retirement/</link><pubDate>Tue, 12 Mar 2024 13:30:00 +0900</pubDate><guid>https://blog.web-apps.tech/prml-prof-kudo-retirement/</guid><description>&lt;p&gt;大学時代の恩師であるところの工藤峰一教授が退官なさるということで、最終講義と祝賀会に行ってきました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://prml.main.ist.hokudai.ac.jp/info/%e5%b7%a5%e8%97%a4%e6%95%99%e6%8e%88%e3%81%8c%e6%9c%80%e7%b5%82%e8%ac%9b%e7%be%a9%e3%82%92%e8%a1%8c%e3%81%84%e3%81%be%e3%81%97%e3%81%9f%e3%80%82/" target="_blank" rel="noopener"&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/prml-prof-kudo-retirement/images/news_hu_1ff032cbddb7de0d.png" alt="" /&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;4月からは新しい方が着任なさるという話ですが、研究室の名前も変わるかも知れませんし、PRMLくんももう見られなくなるかもしれないですね&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/prml-prof-kudo-retirement/images/prmlStar_hu_28a4cbc0e15ecf7b.png" alt="PRMLくん" /&gt;
&lt;/p&gt;</description></item><item><title>PNGの仕様を眺める</title><link>https://blog.web-apps.tech/png-spec/</link><pubDate>Fri, 16 Feb 2024 21:40:00 +0900</pubDate><guid>https://blog.web-apps.tech/png-spec/</guid><description>&lt;p&gt;このブログは現在、&lt;a href="https://gohugo.io" target="_blank" rel="noopener"&gt;Hugo&lt;/a&gt;
という静的サイトジェネレータを使用してページを生成しているのですが、このHugoには多くの便利機能があり、そのうちの一つが&lt;a href="https://gohugo.io/content-management/image-processing" target="_blank" rel="noopener"&gt;Image processing&lt;/a&gt;
です。&lt;/p&gt;
&lt;p&gt;テンプレートの中で、ほんの数行のコードを書くだけで、画像のサイズを調整したり、切り抜いたり、あるいはぼかしたりすることもできます。これまでのところ、このブログでは画像のサイズは結構適当で、場合によっては表示の幅が変わってしまって見栄えが良くないということが(たまに)ありました。&lt;/p&gt;
&lt;p&gt;そこで今回、HugoのImage processing機能のうち、Resizeを使用して、実際にサイトが表示されるときの画像を良い感じにしようと思ったのですが、サイト全体の画像描画部分にhookをかけたところ、エラーが出てビルドができなくなってしまいました。エラーメッセージの大半はファイルパスで、今回は本筋ではない上に長いので端折るとして、重要そうなところを抜き出すと次の様な感じ:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;execute of template failed at &amp;lt;$image.Resize&amp;gt;: error calling Resize:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;: resize : png: invalid format: invalid checksum
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;要するに、Resizeしようとしたときに、checksumが合わないので対象のpng画像ファイルがおかしい、ということらしいんですよね。しかしこれまでこのブログを更新してきて、(パスとかが間違っていない場合に)画像が表示されなくて困ったこともないし、そもそもpngファイルにchecksumがあるなんてことも知らないし・・・&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/golang/go/issues/43382" target="_blank" rel="noopener"&gt;golang/go#43382&lt;/a&gt;
での会話を見たところによるとどうやら、pngファイルには「チャンク」と呼ばれるモノが存在して、これが無視できることも多い(特に実際に表示する時には不要なモノが多い)けれど、Goのimage/pngは今のところはそれらを無視せず、エラーを吐くことになっている、ということらしい。&lt;/p&gt;
&lt;p&gt;エラーの対象となったファイルを、issueの説明に書かれているようにpngcheckにかけてみると次のようにCRCエラーがあることが分かりました:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; pngcheck -v arch-1.png
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;File: arch-1.png (272304 bytes)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; chunk IHDR at offset 0x0000c, length 13
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; 1082 x 778 image, 32-bit RGB+alpha, non-interlaced
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; chunk zTXt at offset 0x00025, length 188903, keyword: mxGraphModel
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; CRC error in chunk zTXt (computed c3f0b5f1, expected 1ce878d9)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;ERRORS DETECTED in arch-1.png
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;なるほど、zTXtというチャンクがあって、そこのCRCが間違っている、ということらしいですね。キーワードはmxGraphModelということで、分からないけど多分グラフに関連したモノが入っているのでしょう。確かにこのファイルはdraw.ioで書き出したもので、書き出しの時に編集情報のようなものを埋め込むオプションを有効にした気がするので、それがどこかのタイミングで壊れ、今回のエラーにつながった、という流れの様です。&lt;/p&gt;</description></item><item><title>Introduce Tree Sitter to Emacs</title><link>https://blog.web-apps.tech/introduce-tree-sitter/</link><pubDate>Wed, 14 Feb 2024 23:20:00 +0900</pubDate><guid>https://blog.web-apps.tech/introduce-tree-sitter/</guid><description>&lt;p&gt;近年、テキストエディタ/IDEの機能はますます複雑となり、プログラミング言語の数は増え、その組み合わせは膨大なものとなっています。元来テキストエディタはそれぞれがそれぞれの実装でそれらの組み合わせを実現してきましたが、自動補完、定義ジャンプ、ドキュメントの表示など、概ねその基本的な機能は同じであるにもかかわらず、すべてのエディタ開発者はそれぞれが車輪の再発明を行う必要があったのです。その問題を解決するために設計開発されたのがLanguage Server Protocol(LSP)であり、ここ数年で多くのテキストエディタが採用したことにより名前くらいは知っているという人も多いのではないでしょうか。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tree-sitter.github.io/tree-sitter/" target="_blank" rel="noopener"&gt;Tree-sitter&lt;/a&gt;
はある意味でLSPあるいはLanguage Serverと呼ばれるものに似ています。Tree-sitterは、プログラミング言語の文法から構文解析器を自動生成するパーサージェネレーターツールであり、またそれを使用した構文解析ライブラリです。&lt;/p&gt;
&lt;p&gt;Tree-sitterは任意の言語を解析できる汎用的なツールで、動作が速く、依存が少ないツールです。2018年にGitHubからリリースされ、emacs 29.1ではbuilt-inの機能として使えるようになりました。&lt;/p&gt;
&lt;h2 id="emacs-x-tree-sitterの仕組みと導入"&gt;Emacs x Tree-sitterの仕組みと導入&lt;/h2&gt;
&lt;p&gt;emacsでTree-sitterを使うには、2つの条件があります:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用したい言語のパーサーが実装されている&lt;/li&gt;
&lt;li&gt;Tree-sitterに対応したmajor modeが実装されている&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="使用したい言語のパーサーが実装されている"&gt;使用したい言語のパーサーが実装されている&lt;/h3&gt;
&lt;p&gt;当然のことながら、Tree-sitter用に文法が定義されている必要があります。使用したい言語のパーサーが既に誰かによって実装されているかは、&lt;a href="https://tree-sitter.github.io/tree-sitter/#available-parsers" target="_blank" rel="noopener"&gt;available-parsers&lt;/a&gt;
のリストを参照すると良いでしょう。概ね、メジャーどころの言語は実装されておりほとんどの場合困ることはないと思います。各言語の文法定義(grammar)はJavaScriptで定義し、tree-sitter CLIを使用してC言語のソースコードに変換し、最終的にはそれをコンパイルして使用します。&lt;/p&gt;
&lt;p&gt;emacsの場合、&lt;code&gt;~/.emacs.d/tree-sitter/&lt;/code&gt;ディレクトリにコンパイルされたダイナミックリンクライブラリを置くことで読み込むことができます。予めコンパイルされたものを置く、でも良いのですが、&lt;code&gt;treesit-install-language-grammar&lt;/code&gt;を使用すると文法をダウンロードしてきて配置してくれるため簡単です。&lt;code&gt;treesit-install-language-grammar&lt;/code&gt;を使用するには、まず&lt;code&gt;treesit-language-source-alist&lt;/code&gt;に言語とgitリポジトリのペアを定義します。その後&lt;code&gt;treesit-install-language-grammar&lt;/code&gt;に言語を渡すことでgit cloneからコンパイル、配置まで行ってくれます。&lt;/p&gt;
&lt;p&gt;例えば、YAML用の文法を導入するには次の様に定義します:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;treesit-language-source-alist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;yaml&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;https://github.com/ikatyang/tree-sitter-yaml&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;そして、&lt;code&gt;(treesit-install-language-grammar yaml)&lt;/code&gt;(もちろんM-xでやっても良いと思います)とするとYAML用の文法がインストールされます。私はこの手のものはemacsの起動時に自動で導入されてほしいので、次の様にしました:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;treesit-language-source-alist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;yaml&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;https://github.com/ikatyang/tree-sitter-yaml&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;dolist&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;element&lt;/span&gt; &lt;span class="nv"&gt;treesit-language-source-alist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;let*&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;lang&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;car&lt;/span&gt; &lt;span class="nv"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;treesit-language-available-p&lt;/span&gt; &lt;span class="nv"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;tree-sistter: %s is already installed&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;message&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;tree-sitter: %s is not installed&amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;treesit-install-language-grammar&lt;/span&gt; &lt;span class="nv"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="tree-sitterに対応したmajor-modeが実装されている"&gt;Tree-sitterに対応したmajor modeが実装されている&lt;/h3&gt;
&lt;p&gt;emacsでTree-sitterを使用したい場合、残念ながら、LSPを使用するときのように、単純にパッケージを追加すればすべての言語でよしなに動く・・・という風にはなりません。emacsでは今までのところ、major modeがシンタックスハイライトを提供するためには主に正規表現などが使用されてきました。正規表現を利用したシンタックスハイライトと、Tree-sitterを使用したシンタックスハイライトは大きく違うため、ほとんどのmajor modeではそのままTree-sitterを採用する形にはならず、Tree-sitter専用のmajor modeが提供される形になっています。emacs29ではメジャーどころの言語に対するTree-sitter対応モードが&lt;a href="https://github.com/emacs-mirror/emacs/blob/master/etc/NEWS.29#L3016-L3089" target="_blank" rel="noopener"&gt;提供されています&lt;/a&gt;
。&lt;/p&gt;
&lt;p&gt;手動でこれらのモードを拡張子ごとに設定しても良いのですが、&lt;code&gt;major-mode-remap-alist&lt;/code&gt;を設定することで、従来のmajor modeをそのままTree-sitter対応のモードに切り替えることができます。&lt;/p&gt;
&lt;p&gt;例えば、yaml-modeの代わりにyaml-ts-modeを使用する場合次の様に設定します:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-to-list&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;major-mode-remap-alist&lt;/span&gt; &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;yaml-mode&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;yaml-ts-mode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;setq&lt;/span&gt; &lt;span class="nv"&gt;major-mode-remap-alist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;yaml-mode&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;yaml-ts-mode&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;この設定によって、yaml-modeでバッファが開かれる場面ではすべてyaml-ts-modeが使用されるようになります。今のところ、hookなどの設定は移行されないため、これらは個別に設定を移行する必要があります。&lt;/p&gt;</description></item><item><title>YAPC::Hiroshima 2024</title><link>https://blog.web-apps.tech/yapc-hiroshima-2024/</link><pubDate>Mon, 12 Feb 2024 02:51:00 +0900</pubDate><guid>https://blog.web-apps.tech/yapc-hiroshima-2024/</guid><description>&lt;p&gt;2024年最初のテックカンファレンスとして、&lt;a href="https://yapcjapan.org/2024hiroshima/" target="_blank" rel="noopener"&gt;YAPC::Hiroshima 2024&lt;/a&gt;
に参加してきました。&lt;/p&gt;
&lt;p&gt;YAPCはPerlのイベントで、“Yet Another Perl Conference&amp;quot;の略です。twitterハッシュタグは前回に引き続き&lt;a href="https://twitter.com/hashtag/yapcjapan" target="_blank" rel="noopener"&gt;#yapcjapan&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;広島に来たのは2017年に&lt;a href="https://www.ospn.jp/osc2017-hiroshima/" target="_blank" rel="noopener"&gt;OSC2017 Hiroshima&lt;/a&gt;
以来2度目です。前夜祭、アフターイベントがあるうえ三連休に絡んでいるということで、木曜日の午後に広島入りして、月曜の夜に帰るという4泊5日という計画としました。なお、弊チームではPerlを使用していないため業務ではなく趣味なのですべて自費です。&lt;/p&gt;
&lt;h2 id="前夜祭"&gt;前夜祭&lt;/h2&gt;
&lt;p&gt;前夜祭は本編と同じ会場で、2本のトーク(?)と番宣リレーという企画がありました。以下ハイライトです:&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;妻から連絡が来たが「登壇中です」のみを返す実績を解除しました。&lt;/p&gt;&amp;mdash; そーだい@初代ALF (@soudai1025) &lt;a href="https://x.com/soudai1025/status/1755897918861742335?ref_src=twsrc%5Etfw"&gt;February 9, 2024&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;登壇しながら明日のLTの資料作ってる &lt;a href="https://x.com/hashtag/yapcjapan?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yapcjapan&lt;/a&gt;&lt;/p&gt;&amp;mdash; そーだい@初代ALF (@soudai1025) &lt;a href="https://x.com/soudai1025/status/1755898703737667871?ref_src=twsrc%5Etfw"&gt;February 9, 2024&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;そーだいさんクラスになると登壇しながら資料を書ける、学びですね(?)&lt;/p&gt;
&lt;h2 id="本編"&gt;本編&lt;/h2&gt;
&lt;p&gt;本編は3トラックで開催されました。次のセッションを聞きました:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コミュニティと共に生きる - キャリアの螺旋と人生を変えた瞬間&lt;/li&gt;
&lt;li&gt;(再演) 関数型プログラミングと型システムのメンタルモデル&lt;/li&gt;
&lt;li&gt;Blogを作り、育み、慈しむ - Blog Hacks 2024&lt;/li&gt;
&lt;li&gt;非同期な開発体制を支えるドキュメント文化&lt;/li&gt;
&lt;li&gt;PerlでつくるフルスクラッチWebAuthn/パスキー認証&lt;/li&gt;
&lt;li&gt;平成のエンジニアから令和のエンジニアへの遺言〜技術情報を伝達する手段の変遷〜&lt;/li&gt;
&lt;li&gt;ライトニングトーク&lt;/li&gt;
&lt;li&gt;キーノート&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;どのセッションももちろん最高だったんですけど、やはり最高of最高はとほほさんによるキーノートでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-hiroshima-2024/images/tohoho_perl_hu_ecddca59bfc4109e.jpeg" alt="とほほさん" /&gt;
&lt;/p&gt;
&lt;p&gt;正直これまでカンファレンスで話を聞いたどのレジェンドよりも「実在の人物だったんだ・・・」感がありました。いやまぁそりゃ、実在の人物でしょうけれども。&lt;/p&gt;
&lt;p&gt;個人スポンサーノベルティはこてでした。SmartHRさんもこてを配っていたのでもらいました。右手と左手で、ひっくり返すのに便利かとおもったので。この時はまさかあんなことになるとは思ってもいなかった・・・！&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-hiroshima-2024/images/kote_hu_9fb1139511c05a6e.jpeg" alt="おこのみやきこて" /&gt;
&lt;/p&gt;
&lt;h3 id="懇親会"&gt;懇親会&lt;/h3&gt;
&lt;p&gt;今回はなんと懇親会あり。YAPCとしては実に5年ぶりの懇親会だそうです。永遠に時間が足りないですね。困った。&lt;/p&gt;
&lt;h3 id="二次会"&gt;二次会&lt;/h3&gt;
&lt;p&gt;各社による半公式二次会があるのも知ってたんですが、なんとなくまぁ申し込みをしないでおいたんですよね。野良二次会やりたくて。なので野良二次会をやりまして、同じ会社の人と実質初めましてですね、Slackではお世話になってます的な話をするなどしました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-hiroshima-2024/images/strawberry_sour_hu_e385e9225b0e3f4b.jpeg" alt="イチゴサワー" /&gt;
&lt;/p&gt;
&lt;h2 id="yayapchiroshima"&gt;YAYAPC::Hiroshima&lt;/h2&gt;
&lt;p&gt;アフターイベントとして&lt;a href="https://connpass.com/event/300500/" target="_blank" rel="noopener"&gt;YAYAPC::Hiroshima&lt;/a&gt;
にも参加しました。なんだかんだ三日間。すごい。&lt;/p&gt;
&lt;p&gt;テーマは&amp;quot;What you live&amp;quot;ということで、オフラインだからこそ話せること、ということで、まぁTwitterを見てもらうとわかるのですが、インターネットで共有はできないものの、みんなわかる・・・！という感じで、うめき声みたいなツイートが発生していました。&lt;/p&gt;
&lt;p&gt;ぼーっとしている間にLT枠が埋まってしまっていたので、応募すればよかったかな〜などと思っていたのですが、当日、タイムテーブルミスったからLT枠がある、ということで飛び入りで怪しい話をさせていただき、なんと賞まで頂戴いたしまして、結果的に個人スポンサーノベルティのこてが2本と相成りました。いやー、これにはびっくり。大変ありがたいことです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc-hiroshima-2024/images/kote2_hu_841c5a712f3e01e4.jpeg" alt="個人スポンサーのこてが2本" /&gt;
&lt;/p&gt;
&lt;p&gt;終わった後は12人ほどで飲みに繰り出しまして(17時頃)、途中人が多少入れ替わりつつ飲み続け、23:30頃に解散しました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;これは死んでる &lt;a href="https://x.com/songmu?ref_src=twsrc%5Etfw"&gt;@songmu&lt;/a&gt; san &lt;a href="https://x.com/hashtag/yayapc?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yayapc&lt;/a&gt; &lt;a href="https://x.com/hashtag/yapcjapan?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yapcjapan&lt;/a&gt; &lt;a href="https://t.co/vFajihV2vC"&gt;pic.twitter.com/vFajihV2vC&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/1756686929075347708?ref_src=twsrc%5Etfw"&gt;February 11, 2024&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;そして解散した後は深夜だというのに一人でお好み焼きを食べるなどしました。お好み焼き美味しい。&lt;/p&gt;</description></item><item><title>Tall Titlebar Issue on macOS Sonoma</title><link>https://blog.web-apps.tech/tall-titlebar-issue-on-macos-sonoma/</link><pubDate>Tue, 06 Feb 2024 01:45:02 +0900</pubDate><guid>https://blog.web-apps.tech/tall-titlebar-issue-on-macos-sonoma/</guid><description>&lt;p&gt;私は普段、&lt;a href="https://github.com/railwaycat/homebrew-emacsmacport" target="_blank" rel="noopener"&gt;railwaycat/emacsmacport&lt;/a&gt;
を使ってインストールした&lt;a href="https://bitbucket.org/mituharu/emacs-mac/src/master/" target="_blank" rel="noopener"&gt;emacs-mac&lt;/a&gt;
を使用しているのですが、何故かmacOSをSonomaにアップグレードしたらタイトルバーが太くなりました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://note.com/5mingame2/n/ne5cb599c0684" target="_blank" rel="noopener"&gt;macOS SonomaにしたらEmacsのタイトルバーが太くなった&amp;hellip;！&lt;/a&gt;
によると、次の設定を入れるとなおるようです:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;tool-bar-mode&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;tool-bar-mode&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tall-titlebar-issue-on-macos-sonoma/images/titlebar-normal_hu_59093f92c7c708c5.png" alt="なおりました" /&gt;
&lt;/p&gt;
&lt;p&gt;うーん、起動も遅くなったっぽいし、workaround感がすごい。わかんないですけどなんかフレームの初期化に失敗しているとかそういう感じなんでしょうか。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bitbucket.org/mituharu/emacs-mac/commits/5f6c306095c825eb01708e336f9d03c15271dfe9" target="_blank" rel="noopener"&gt;emacs-macの方で修正を入れてくれている様子&lt;/a&gt;
なので、リリースされるまではこのworkaroundでしのいでおくくらいしかできなさそうです。&lt;/p&gt;</description></item><item><title>THEO解約レポート</title><link>https://blog.web-apps.tech/theo-report/</link><pubDate>Mon, 05 Feb 2024 22:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/theo-report/</guid><description>&lt;p&gt;2024年、新NISAが始まりましたので、手数料が高いTHEOを解約して新NISAに移すことにしました。&lt;a href="https://blog.web-apps.tech/line-security-report/"&gt;LINE証券&lt;/a&gt;
と同様、記録を残しておきます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2018年9月3日: THEO登録、10,000円/月で積み立て設定&lt;/li&gt;
&lt;li&gt;2018年10月15日: 初回入金&lt;/li&gt;
&lt;li&gt;2020年2月20日: 20,000円/月に積み立て設定変更&lt;/li&gt;
&lt;li&gt;2022年3月28日: 10,000円/月に積み立て設定変更&lt;/li&gt;
&lt;li&gt;2023年12月29日: 最後の積み立てが終了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;総積立額は880,000円、トータルリターンは330,325円 (+37.54%)でした。&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>LINE証券解約レポート</title><link>https://blog.web-apps.tech/line-security-report/</link><pubDate>Wed, 31 Jan 2024 21:15:00 +0900</pubDate><guid>https://blog.web-apps.tech/line-security-report/</guid><description>&lt;p&gt;あけましておめでとうございます。本年もよろしくお願いいたします。世間では新NISAが話題ですが皆さんいかがお過ごしでしょうか。&lt;/p&gt;
&lt;p&gt;扨、LINE証券がサービス終了ということで、LINE証券で積み立てていた投資信託をメインの証券口座に移管して、新NISAに突っ込むべく売却したのでレポートとして記録に残しておきます。&lt;/p&gt;
&lt;p&gt;銘柄はeMAXIS Slim米国株式(S&amp;amp;P500)、タイムラインは次の通り:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2022年5月: 積み立て開始、積立額は17,000円/月&lt;/li&gt;
&lt;li&gt;2022年12月: 積立額を27,000円/月に増額&lt;/li&gt;
&lt;li&gt;2023年11月: 最後の積み立てが終了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;保有数は215,920口、積立総額は443,000円、本日(2024年1月31日)時点で概算評価額は561,607円、評価損益は+118,583円、評価損益率は+26.76%でした。&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>ワイヤレス送信機用延長シールドを作る</title><link>https://blog.web-apps.tech/make-extension-cable-for-wireless/</link><pubDate>Thu, 28 Dec 2023 01:47:40 +0900</pubDate><guid>https://blog.web-apps.tech/make-extension-cable-for-wireless/</guid><description>&lt;p&gt;現在、ギターを練習するとき、有線でケーブルをつなぐとイスで踏んでしまったり、あちこちに引っかかってしまったりして不便なので、&lt;a href="https://line6.jp/products/relay-wireless/g10-g10s.html" target="_blank" rel="noopener"&gt;LINE6 Relay G10TII&lt;/a&gt;
というワイヤレス送信機を使っています。&lt;/p&gt;
&lt;p&gt;今使用しているギターは&lt;a href="https://jp.yamaha.com/products/musical_instruments/guitars_basses/el_guitars/pacifica/pac_100.html" target="_blank" rel="noopener"&gt;YAMAHA PACIFICA 112V&lt;/a&gt;
なんですが、このギター、サイドにジャックがあるんですよね。そうすると、ワイヤレスの送信機、特にG10TIIや&lt;a href="https://www.boss.info/jp/products/wl-20_wl-20l/" target="_blank" rel="noopener"&gt;BOSS WL-20&lt;/a&gt;
の様な四角いタイプの送信機を挿すとかなり飛び出る格好になってしまい、オフィスチェアに座って練習をしていると(単にオフィスチェアとギター練習の相性が悪い、という点はさておき)ぶつけて折ってしまいそうで不安になります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/guitar_wireless_hu_7416de34f8d9a80a.jpg" alt="ギターからワイヤレス送信機がはみ出るの図" /&gt;
&lt;/p&gt;
&lt;p&gt;一応L字のアダプタは付属していたような気もしますけれど、丸みのあるギターの側面にL字アダプタを挿しても、結局違う方向にはみ出るのはあまり変わらないな、ということでL字プラグに短いケーブルがついている、いわば「延長ケーブル」を作りました。&lt;/p&gt;
&lt;p&gt;なお、何故ライブ前に作らなかったのか、という問いには答えられません。&lt;/p&gt;
&lt;h2 id="材料"&gt;材料&lt;/h2&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/material_hu_5256b67736ff78f2.jpg" alt="材料の写真" /&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;任意のL字プラグ
&lt;ul&gt;
&lt;li&gt;今回は&lt;a href="https://shop.oyaide.com/products/p-63l_6mm.html" target="_blank" rel="noopener"&gt;オヤイデの超小型な奴&lt;/a&gt;
。使ってみたかったので。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;任意のフォンジャック
&lt;ul&gt;
&lt;li&gt;今回は&lt;a href="https://www.soundhouse.co.jp/products/detail/item/132656/" target="_blank" rel="noopener"&gt;TOMOCA JS-504&lt;/a&gt;
。見た目が良かったので。&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sengoku.co.jp/mod/sgk_cart/search.php?cid=3414" target="_blank" rel="noopener"&gt;千石電商&lt;/a&gt;
とかでもっと安いのも買えるけど、送料がかかるので通販だと実質TOMOCA JS-504一択。秋葉原によく行く人は&lt;a href="https://www.sengoku.co.jp/shop_01.html" target="_blank" rel="noopener"&gt;千石電商秋葉原本店&lt;/a&gt;
の2階か、ラジオ会館の&lt;a href="https://www.tomoca.co.jp/shop/proshop/" target="_blank" rel="noopener"&gt;トモカ電気プロショップ&lt;/a&gt;
に行くとソレっぽいモノが売っています。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;任意の単芯シールドケーブル
&lt;ul&gt;
&lt;li&gt;今回は&lt;a href="https://www.soundhouse.co.jp/products/detail/item/22872/" target="_blank" rel="noopener"&gt;CANARE GS-6&lt;/a&gt;
。ど定番だし、たまたま安く売ってたので。&lt;/li&gt;
&lt;li&gt;PACIFICA 112Vの場合は25cm位用意すればちょうどよさそう&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;何か絶縁する奴
&lt;ul&gt;
&lt;li&gt;無くても良い。&lt;a href="https://shop.oyaide.com/asf-110_5.html" target="_blank" rel="noopener"&gt;フッ素テープ&lt;/a&gt;
とか熱収縮チューブとか。ホームセンターとかで買ってきても良いし、ご家庭に在庫している適当な熱収縮チューブを使っても良い。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;任意の半田
&lt;ul&gt;
&lt;li&gt;材料というか工具というか？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="工具"&gt;工具&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;任意の半田ごて&lt;/li&gt;
&lt;li&gt;半田吸い取り線
&lt;ul&gt;
&lt;li&gt;無くても良いけど、ミスした場合を考えると持っていた方が良い。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;任意のニッパーまたはカッターまたはまたはワイヤーストリッパー&lt;/li&gt;
&lt;li&gt;テスター
&lt;ul&gt;
&lt;li&gt;無くても良いけど導通チェックはした方が安心&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(オヤイデのSuperSlimシリーズを使う場合)任意のプラスチック/ゴムハンマー&lt;/li&gt;
&lt;li&gt;(熱収縮チューブを使う場合)任意のヒートガン
&lt;ul&gt;
&lt;li&gt;ドライヤーなどでも代用できるけど、あった方が便利&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ツールクリップ
&lt;ul&gt;
&lt;li&gt;土台に腕とクリップがついていて、はんだ付けする対象を固定できるやつ&lt;/li&gt;
&lt;li&gt;これもなくても良いけど、ケーブルのはんだ付けは細かいし、ケーブルは意外とのたうち回ってはんだ付けが難しいのであった方が良い。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="作成手順"&gt;作成手順&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;目算で外側の被覆を剥く
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/wire_hu_9f34e19b2a12614e.jpg" alt="被覆を剥いた線" /&gt;
&lt;/li&gt;
&lt;li&gt;シールド線をほぐす
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/shield_hu_586b37627c599424.jpg" alt="シールド線をほぐした線" /&gt;
&lt;/li&gt;
&lt;li&gt;L字プラグをつける (以下オヤイデSuperSlimの場合)
&lt;ol&gt;
&lt;li&gt;シールド線をざっくり二つに分けて芯線に巻く
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/shield_2_hu_cde737977609bcde.jpg" alt="芯線にシールド線を巻いた線" /&gt;
&lt;/li&gt;
&lt;li&gt;芯線を剥く
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/core_hu_2f8cb6a397cde7fb.jpg" alt="芯線を剥いた線" /&gt;
&lt;/li&gt;
&lt;li&gt;カバー？ハウジング？をはずしたオヤイデSueprSlimに差し込みTIP(+)にはんだ付けする
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/soldering_1_hu_32b50d33bb4f2c0e.jpg" alt="TIPにはんだ付け" /&gt;
&lt;/li&gt;
&lt;li&gt;クランプ側面の穴からはんだを流し込む
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/soldering_2_hu_cdc6c75fdefb0544.jpg" alt="クランプ穴にはんだを流し込む" /&gt;
&lt;/li&gt;
&lt;li&gt;導通チェックをする&lt;/li&gt;
&lt;li&gt;熱収縮チューブを差し込んで加熱して収縮させる
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/heat_shrink_tube_hu_c7db34335b195bb4.jpg" alt="熱収縮チューブをつけた図" /&gt;
&lt;/li&gt;
&lt;li&gt;カバーをつける&lt;/li&gt;
&lt;li&gt;樹脂キャップを乗せてプラスチックハンマー/ゴムハンマーで叩いてはめ込む&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;フォンジャックをつける (以下TOMOCA JS-504の場合)
&lt;ol&gt;
&lt;li&gt;フォンジャックのカバーを差し込む (これを忘れてはんだ付けするとやり直しになるので注意。私はやり直しました)&lt;/li&gt;
&lt;li&gt;シールド線を適当にまとめる&lt;/li&gt;
&lt;li&gt;芯線を剥いて二つに分ける
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/wire_for_jack_hu_de33d5ab0dd4bcf0.jpg" alt="フォンジャック用の線" /&gt;
&lt;/li&gt;
&lt;li&gt;シールド線、芯線の順にはんだ付けをする (フッ素テープやビニールテープなど絶縁するモノの用意があれば絶縁しておくと安心)
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/soldering_3_hu_5f6d19e32681b9dc.jpg" alt="フォンジャックをはんだ付けした図" /&gt;
&lt;/li&gt;
&lt;li&gt;カバーをつける&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;完成!
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/wireless_extension_cable_hu_371a95ec4c51b69e.jpg" alt="完成品" /&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="実際にギターに挿す"&gt;実際にギターに挿す&lt;/h2&gt;
&lt;p&gt;実際にギターに挿すとこんな感じ:
&lt;img loading="lazy" src="https://blog.web-apps.tech/make-extension-cable-for-wireless/images/with_guitar_hu_7b6f480260fab571.jpg" alt="実際にギターに挿した図" /&gt;
&lt;/p&gt;</description></item><item><title>Tech Rock Festival 2023</title><link>https://blog.web-apps.tech/tech-rock-festival-2023/</link><pubDate>Mon, 25 Dec 2023 23:32:00 +0900</pubDate><guid>https://blog.web-apps.tech/tech-rock-festival-2023/</guid><description>&lt;p&gt;2023年12月23日に新宿SUNFACEで開催されたITエンジニアによるITエンジニアのためのロックイベントTech Rock Festival 2023に参加してきました。&lt;/p&gt;
&lt;h2 id="経緯"&gt;経緯&lt;/h2&gt;
&lt;p&gt;事の発端は某GAFA社長であるところの&lt;a href="https://twitter.com/jyoshise" target="_blank" rel="noopener"&gt;@jyoshise&lt;/a&gt;
sanによる次のツイートでした:
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;エンジニア界隈で楽器やってる人、秋ぐらいにライブやりませんかー！？&lt;/p&gt;&amp;mdash; jyoshise (@jyoshise) &lt;a href="https://x.com/jyoshise/status/1671887548791287811?ref_src=twsrc%5Etfw"&gt;June 22, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;どうやら、エンジニア界隈、結構音楽やっている奴いるぞ、ということで立ち上がったプロジェクトですが、翌日にはGitHub Repositoryが立てられ:&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;Repo立てましたー！&lt;a href="https://t.co/4OqYjugBBr"&gt;https://t.co/4OqYjugBBr&lt;/a&gt; &lt;a href="https://t.co/ncT3tKxWDG"&gt;https://t.co/ncT3tKxWDG&lt;/a&gt;&lt;/p&gt;&amp;mdash; jyoshise (@jyoshise) &lt;a href="https://x.com/jyoshise/status/1672093299732250624?ref_src=twsrc%5Etfw"&gt;June 23, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;7月の頭には申し込み締切、13日にはバンド振り分けが終わり、会場も決まり、練習を進めて、先週の土曜日ついに開催となりました。
演者がエンジニアという都合上、大きめのテックカンファレンスとかぶらないようにしなければいけないということで調整の結果、12月末は目立ったテックカンファレンスもないだろうということで12月23日の開催となりました。&lt;/p&gt;
&lt;p&gt;概ね演者だけで会場は一杯だったのですが、&lt;a href="https://trf.connpass.com/event/293949/" target="_blank" rel="noopener"&gt;一般オーディエンスも募集していました&lt;/a&gt;
。&lt;/p&gt;
&lt;h2 id="バンドと演目"&gt;バンドと演目&lt;/h2&gt;
&lt;p&gt;私たちのバンドは3-way handshakeという名前で、当初バンドに振られた連番が3であったことから、3に関連する技術っぽい言葉でバンド名っぽくもある、というところでこの名前になりました。&lt;/p&gt;
&lt;p&gt;面子は以下の通り:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vo: &lt;a href="https://twitter.com/tsukaman" target="_blank" rel="noopener"&gt;tsukaman&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Gt: &lt;a href="https://twitter.com/yoshiyama_hana" target="_blank" rel="noopener"&gt;じゅんじゅん&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Gt: &lt;a href="https://twitter.com/nasa9084" target="_blank" rel="noopener"&gt;nasa9084&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ba: &lt;a href="https://twitter.com/karupanerura" target="_blank" rel="noopener"&gt;karupanerura&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Key: &lt;a href="https://twitter.com/yb300k" target="_blank" rel="noopener"&gt;harak&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Dr: &lt;a href="https://twitter.com/r315dr" target="_blank" rel="noopener"&gt;皮しばき&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;そして曲目は次の通りでした:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;深夜高速 / フラワーカンパニーズ&lt;/li&gt;
&lt;li&gt;ばらの花 / くるり&lt;/li&gt;
&lt;li&gt;歩いて帰ろう / 斉藤和義&lt;/li&gt;
&lt;li&gt;群青日和 / 東京事変&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="機材"&gt;機材&lt;/h2&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tech-rock-festival-2023/images/guitar_hu_ca5d79bd8c9e0cfe.jpg" alt="YAMAHA PACIFICA 112V" /&gt;
&lt;/p&gt;
&lt;p&gt;ギターは&lt;a href="https://jp.yamaha.com/products/musical_instruments/guitars_basses/el_guitars/pacifica/pac_100.html" target="_blank" rel="noopener"&gt;YAMAHA PACIFICA 112V&lt;/a&gt;
です。&lt;/p&gt;
&lt;p&gt;正直に言うと、当初600シリーズを買おうと思ったけど某アニメの影響で全然買えなくて、妥協で買ったギターではありますが、良いギターだと思います。&lt;/p&gt;
&lt;p&gt;弦はElixir Optiweb 09-42です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tech-rock-festival-2023/images/effector_hu_5dc42f42be04b435.jpg" alt="エフェクターボード" /&gt;
&lt;/p&gt;
&lt;p&gt;エフェクターは&lt;a href="https://zoomcorp.com/ja/jp/multi-effects/guitar-effects/g1-four-g1x-four/" target="_blank" rel="noopener"&gt;ZOOM G1 FOUR&lt;/a&gt;
ですべてを済ませました。練習では&lt;a href="https://jp.yamaha.com/products/musical_instruments/guitars_basses/amps_accessories/thr-ii/index.html" target="_blank" rel="noopener"&gt;THR10II Wireless&lt;/a&gt;
に無線で繋いでいるので、有線でやるのはやだな〜と思って、&lt;a href="https://line6.jp/products/accessory/#G10SR" target="_blank" rel="noopener"&gt;LINE6 Relay G10SR&lt;/a&gt;
を購入してエフェクターボードでも無線で接続できるようにしました。&lt;/p&gt;
&lt;p&gt;チューナーはG1 FOURにもついてはいるんですが、手前に専用のモノを用意した方が見やすいし、ミュートもできて便利だな、と思ったので&lt;a href="https://www.tcelectronic.com/product.html?modelCode=P0CM0" target="_blank" rel="noopener"&gt;tc electronic POLYTUNE3&lt;/a&gt;
を入れました。miniだと黒があってよかったんですが、シュッと手に入らなかったので普通のサイズにしました。&lt;/p&gt;</description></item><item><title>2023年買って良かったモノ</title><link>https://blog.web-apps.tech/2023-must-buy/</link><pubDate>Sat, 16 Dec 2023 02:09:00 +0900</pubDate><guid>https://blog.web-apps.tech/2023-must-buy/</guid><description>&lt;p&gt;もう2023年も終わりますね。&lt;a href="https://blog.web-apps.tech/2022-must-buy/" target="_blank" rel="noopener"&gt;2022年の記事&lt;/a&gt;
は主に車とアクアリウムでした。今年は主に喫茶系とギターですね。&lt;/p&gt;
&lt;h2 id="喫茶系"&gt;喫茶系&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kigu.coffee/products/ode-brew-grinder-gen2" target="_blank" rel="noopener"&gt;Fellow ODE Gen2&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;正直クソ高いけど、使いやすいしはやく安定した挽き目で弾いてくれるのでとても良いです。家庭用には珍しくノッカーがついているのも良いところ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nitori-net.jp/ec/product/8944234s/" target="_blank" rel="noopener"&gt;ニトリ ドリップカップ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;小さくて取り回し抜群。1杯分を入れるには全然困らない。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.hario.com/product/tea/teadripper/CDB.html" target="_blank" rel="noopener"&gt;HARIO 茶茶ドリッパー・ブーケ サーバーセット&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;茶の類いのモノを淹れるのにめっちゃ便利。サーバーはアイスではとても便利だけど、ホットは熱くて持てなくなるので注意。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/46VT1xE" target="_blank" rel="noopener"&gt;サーモス 真空断熱ティーポット&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;温かい飲物が美味しい季節になったので買ってみた。保温性能はもちろんマグカップよりは圧倒的にいい(1時間そこそこは保温してくれる)けど、それよりもコーヒーサーバーとして使える小型の断熱ポット、というモノが便利。調べた感じではこれが唯一解。なおティーストレーナーは要らないと思います。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.loveramics.com/collections/james-hoffmann/products/champions-signature-set-of-2-beans-dosing-trays" target="_blank" rel="noopener"&gt;LOVERAMICS BEANS DOSING TRAYS&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;James Hoffmannコラボの、コーヒー豆を計るためだけの器。絶対必要なモノではないけど、かわいいしテンションが上がるのでオススメ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ギター関連"&gt;ギター関連&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jp.yamaha.com/products/musical_instruments/guitars_basses/el_guitars/pacifica/pac_100.html" target="_blank" rel="noopener"&gt;YAMAHA PACIFICA112V&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ぼざろ影響で600シリーズが在庫無くて112Vにしたけど、ちょっと弾くくらいならこれで全然十分。600シリーズ欲しくなってきてるけど。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/262563/" target="_blank" rel="noopener"&gt;G7th Performance 3 ART Capo Black&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ちょっとカポとしてはお高いけど、かなり使いやすいです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/296867/" target="_blank" rel="noopener"&gt;ねこだまり工房/自家製クリア蜜蝋ワックス 陽だまりの香り &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;好みの香りだった。限定品らしくsoundhouseではもう販売終了しているけど、ネット通販ではまだ手に入るところがありそう。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/245586/" target="_blank" rel="noopener"&gt;MASTER 8 JAPAN INFINIX JAZZ TYPE HARD GRIP&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;このシリーズは全部揃えてみたけど、HARD GRIPタイプがグリップ感が強くて良い。薄さはお好みで。INFINIX-Uでもよい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/170995/" target="_blank" rel="noopener"&gt;PEDALTRAIN NANO&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;超小型エフェクターボード。&lt;a href="https://www.soundhouse.co.jp/products/detail/item/301481/" target="_blank" rel="noopener"&gt;G10SR&lt;/a&gt;
、&lt;a href="https://www.soundhouse.co.jp/products/detail/item/236578/" target="_blank" rel="noopener"&gt;Polytune3&lt;/a&gt;
、&lt;a href="https://www.soundhouse.co.jp/products/detail/item/260949/" target="_blank" rel="noopener"&gt;G1 FOUR&lt;/a&gt;
でぴったり、という感じの構成。電源は&lt;a href="https://www.soundhouse.co.jp/products/detail/item/329785/" target="_blank" rel="noopener"&gt;VITAL AUDIO POWER CARRIER VA-05 MkII&lt;/a&gt;
が良いサイズ。マルチはGT1000-coreを買うか検討中。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/254283/" target="_blank" rel="noopener"&gt;アルトベンリ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ちょっとサイズが合わないのでティッシュを詰めて使っている。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.soundhouse.co.jp/products/detail/item/255864/" target="_blank" rel="noopener"&gt;HERCULES GS414B PLUS&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;安定感抜群。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="日用品など"&gt;日用品など&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3Rb8lQU" target="_blank" rel="noopener"&gt;コクヨ マスキングテープ テープカッター カルカット クリップタイプ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;一般的な用途としてはおしゃれマスキングテープ用のカッターとして使んだと思うけれども、普通の黄色いマスキングテープにつけて使っている。手で切るとぐちゃっとなってしまうこともあるのでとても便利。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3uVqniL" target="_blank" rel="noopener"&gt;[RLJ] 引き出し ミニ サイズ (後付けタイプ) ミニ引き出し&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;正直コスパはどうなのか、という感じはある。作りはチープだし、有機溶剤っぽい匂いが永遠に取れない。が、まぁ便利は便利。私が買った時より値上がりしていてコスパは更に悪化してそう。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3tfruJD" target="_blank" rel="noopener"&gt;鬼ピタ 魔法のテープ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;めっちゃ強力。きれいに剥がせるといううたい文句に嘘はないけど、貼り付け面が弱ければ壊れてしまいそうな位には強力。ギターのエフェクターをエフェクターボードにつけるのにも使っている。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3REH2QL" target="_blank" rel="noopener"&gt;uxcell 丸平頭 ローレット つまみ M2x8mm ハンドクランプねじ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;手で回せるねじ。無線化しているErgodashの背面プレートを開けたり閉めたりするのが簡単になった。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3Tg4fK8" target="_blank" rel="noopener"&gt;[PureSino] アームバンド&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;カーディガンなどの袖を止めるのに便利。基本的に袖まくりしているので。1セット持っていたハズなんだけど、行方不明だったので買ったが、やはり便利。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3uW3RGA" target="_blank" rel="noopener"&gt;ラムマウント(RAM MOUNTS) MagSafeマウント&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;便利ではあるけど、高いMagSafe充電器を追加で買う必要があるのはコスト的に結構厳しめかもしれない。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3GGd20y" target="_blank" rel="noopener"&gt;SwitchBot カーテン 第3世代&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;SwitchBot カーテンからの買い換え。一世代しかしらないけど、何故か第3世代らしい。従来品よりはやいし、静かに動かすこともできるし、取り付け、取り外しも簡単になっている(構造としては変わらないけど、作りが改善されている)し、位置調整がメチャクチャ簡単になっている。従来品(Amazonによると第2世代)より2,000円高いけど、こっちを買った方が良いです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/48aKqbi" target="_blank" rel="noopener"&gt;BREENHILL テーブルマット 100x40cm&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ほんとは120x40とかがほしいんだけど、無かったので妥協した。100x40でも珍しいです。マウスパッドとして良いかどうかは分からないけど、トラックパッドを使っていて、ただ何か敷物が欲しいくらいの人にはお勧めできる。裏面に滑り止めがついているけど、これは余り期待しない方が良い。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="書籍"&gt;書籍&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/41jWWmH" target="_blank" rel="noopener"&gt;あかね噺&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;買った時はまだ4冊だったのに今は9巻まで出ている。ジャンプは続きが出るのがはやくて良いですね。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/4auksSj" target="_blank" rel="noopener"&gt;江戸前エルフ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;アニメ化もされた。アニメも良いです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/48apd1c" target="_blank" rel="noopener"&gt;お前、タヌキにならねーか？&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;タヌキになりたい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3Nj09gE" target="_blank" rel="noopener"&gt;Dr.STONE&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;セールで50%ポイント還元だったので買った。理系の人ないし理系っぽいテーマが好きな人は好きだと思う。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3uW3ID2" target="_blank" rel="noopener"&gt;ボボボーボ・ボーボボ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;同じく50%ポイント還元だったので。なんか最近ボーボボ見る機会多い気がするんだけどなんで?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3NpRatT" target="_blank" rel="noopener"&gt;葬送のフリーレン&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;紙をkindleに買い換え。特に言うことは無いです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>すごい味噌汁</title><link>https://blog.web-apps.tech/super_miso_soup/</link><pubDate>Tue, 05 Dec 2023 18:47:06 +0900</pubDate><guid>https://blog.web-apps.tech/super_miso_soup/</guid><description>&lt;p&gt;いつからか、風邪の時に作る謎の味噌汁がある。少なくとも、実家で作っていたモノではなくて、関東に引っ越してきてから作り始めた。どういうきっかけだったかは不明で、多分妹がどこかから聞いてきたモノを魔改造して完成した。&lt;/p&gt;
&lt;p&gt;レシピは次の通り。&lt;/p&gt;
&lt;h2 id="材料"&gt;材料&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;出汁&lt;/li&gt;
&lt;li&gt;味噌&lt;/li&gt;
&lt;li&gt;ニンニク&lt;/li&gt;
&lt;li&gt;生姜&lt;/li&gt;
&lt;li&gt;ピーマン&lt;/li&gt;
&lt;li&gt;たまご&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なお分量はすべて「適量」である。ニンニクは一かけ、生姜はニンニクと同じくらいの量、ピーマン一つ、たまご一つ、といった感じ。出汁は出汁の素の類でかまわないし、ニンニクと生姜はそれぞれチューブでも良い。生のモノを使うともちろんより美味しい。&lt;/p&gt;
&lt;p&gt;個人的には出汁の素は大体入れるが、気にならなければ出汁入りの味噌を使っても良い。生姜とニンニクが十分に強いので、なんなら出汁がなくても気にならないかもしれない。&lt;/p&gt;
&lt;h2 id="調理手順"&gt;調理手順&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;湯を沸かし、出汁を取る、乃至出汁の素を溶かす&lt;/li&gt;
&lt;li&gt;味噌を溶かす&lt;/li&gt;
&lt;li&gt;ニンニクと生姜をすりおろして入れる&lt;/li&gt;
&lt;li&gt;溶きたまごを回し入れる&lt;/li&gt;
&lt;li&gt;ピーマンを入れる&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ピーマンに火が通ったな、と思ったら完成。ピーマンは食感が残る程度でも美味しいし、クタクタになってもそれはそれで美味しい。細切りにしても良いし、写真のように輪切り？にしても良い。ワタを取ることを考えると、細切りの方が簡単。&lt;/p&gt;
&lt;p&gt;溶きたまごを回し入れるときは、(味噌汁的/出汁的には良くないかもしれないが、生姜とニンニクがそもそも最強なので気にしないこととする)汁が沸騰している状態で少しずつ入れると、ふわふわの良い感じになる。たまごは十分に溶いてあっても良いし、雑にやってもそれはそれで美味しい。白身のごろっとした塊とか美味しいですね？そういうことです。&lt;/p&gt;
&lt;p&gt;生姜とニンニクが入っているので、食べ終わる頃にはポカポカしてきて、元気になる。気がする。「味噌汁」と呼ぶには強い味がするけれど、美味しいのでヨシ。&lt;/p&gt;</description></item><item><title>UCC Cafe@Home</title><link>https://blog.web-apps.tech/ucc-cafe-at-home/</link><pubDate>Fri, 06 Oct 2023 00:45:18 +0900</pubDate><guid>https://blog.web-apps.tech/ucc-cafe-at-home/</guid><description>&lt;p&gt;先日、&lt;a href="https://scajconference.jp/" target="_blank" rel="noopener"&gt;SCAJ&lt;/a&gt;
というでかいコーヒーのイベントに行ってきました。
面白かったモノをいくらか買ってきたのですが、そのうちの一つがUCCのCAFE@HOMEです。&lt;/p&gt;
&lt;p&gt;どうやらインターネットで調べた感じでは現在の形でのCAFE@HOME自体は5年くらい前に発売されたものでそんなに新しい商品という感じではなさそうなのですが、&lt;a href="https://www.ucc.co.jp/company/news/2023/rel230314.html" target="_blank" rel="noopener"&gt;今年の3月に同シリーズから新しいデカフェのものがでた&lt;/a&gt;
ということで大きく宣伝していた、ということのようです。&lt;/p&gt;
&lt;p&gt;CAFE@HOMEはレギュラーコーヒーの粉を1杯分ごとに真空パックすることで美味しくコーヒーを飲める、という趣旨のシリーズのようです。カップに乗せて使うタイプのフィルターも付属しているので(コーヒーを淹れる道具がない人でも)気軽に美味しいコーヒーを淹れられる、小洒落たデザインで贈り物にもぴったり、という感じですね。&lt;/p&gt;
&lt;p&gt;私は現状普通のコーヒー豆は十分すぎるほどにあるので(ちょっと消費が追いついてないくらい、サブスク加入しているため月一で追加補給される)、今回は3種類のデカフェを2つずつ、合計6個のセットを購入しました。&lt;/p&gt;
&lt;p&gt;内容はこんな感じ:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ucc-cafe-at-home/images/contents_hu_73da35b5060706a5.jpeg" alt="内容物" /&gt;
&lt;/p&gt;
&lt;p&gt;コーヒーの他、前述の様にフィルターが付属しているのと、説明書も入っていました。&lt;/p&gt;
&lt;p&gt;開封してフィルターをセットするとこんな感じです:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ucc-cafe-at-home/images/dripper_hu_bdceb7777a56ccb5.jpeg" alt="filter" /&gt;
&lt;/p&gt;
&lt;p&gt;一般的にコンビニやらスーパーやらで購入できるドリップバッグと比べるとしっかりとしたフィルターで、普通の台形フィルターに似た感じで使えそうな気がしました。真空パックで香りを閉じ込めている、というだけあって、安いドリップバッグのようにフィルター部分がカップの中のお湯に浸かるような構造ではないですね。&lt;/p&gt;
&lt;p&gt;説明書にはフィルターをカップにセットし、コーヒーを手で開封して粉を入れる、という形で書いてありますし、実際カップにセットしないと流石に安定しなさそうなので手順としてはあっているとは思うのですが、粉末が入った袋が真空パックされているということで説明書のように立てに袋を割いてきれいにフィルターに粉を入れる、というのは少し難しいように感じました。私は粉を少しカップの中にこぼしました。基本的にハサミで切った方が良さそうです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ucc-cafe-at-home/images/powder_hu_41f4dc2680c6bd4b.jpeg" alt="コーヒーの粉" /&gt;
&lt;/p&gt;
&lt;p&gt;粉は中〜粗挽きくらいでしょうか。開けた瞬間良い香りがしたので、香りを閉じ込めている、というのが実際に感じられました。普段私が挽いているのよりはちょっと粗目かな、と感じました(普段はV60とかを使っているので、細めに挽いています)が、台形フィルター用の粉としては特別粗いということもないと思います。
ドリップバッグはあまり買ったことがないのですが、かすかな記憶に残るドリップバッグの粉よりも粗目に思えるので、そういう意味でも自信のようなものが感じられます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ucc-cafe-at-home/images/pour_hu_62f2c210ce2afa1f.jpeg" alt="お湯を注いだ様子" /&gt;
&lt;/p&gt;
&lt;p&gt;お湯を注ぐと、まぁもちろんふくらむというほどのことはないです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ucc-cafe-at-home/images/result_hu_7d919e5f3760de05.jpeg" alt="淹れたコーヒー" /&gt;
&lt;/p&gt;
&lt;p&gt;できあがりはこんな感じ。今回淹れた黄色い奴はカフェオレでも美味しい、ということなので牛乳を入れる予定で100mLのお湯で多分できあがりが80mL位だと思いますが、結構濃いめに見えますね。牛乳を入れても良い感じの色です。香りはまぁ、もちろん挽き立てに匹敵するとかそういうことは無いんですが、それでも牛乳を入れてもまだちゃんとコーヒーの味・香りがする感じで、悪くないと思います。&lt;/p&gt;
&lt;p&gt;デカフェのコーヒーは正直そんなに美味しいものは多くない(香りがない、よりは、デカフェだな、という味がする)という印象がありますが、少なくとも牛乳を入れて飲んだ感じは割と悪くないです。&lt;/p&gt;
&lt;p&gt;10g260円なので100g2600円と日常使いのコーヒーとしては高いですが、ドリッパー付きで手軽にコーヒーが淹れられるし、パッケージはおしゃれだし、という点も含めて、贈り物としてはアリだと思います。興味がある人は横浜か吉祥寺の店舗、または&lt;a href="https://coffeestyle.jp/products/cah0104059?_pos=7&amp;amp;_sid=2cae5a4d9&amp;amp;_ss=r" target="_blank" rel="noopener"&gt;COFFEE STYLE UCC ONLINE SHOP&lt;/a&gt;
で買えるようです。&lt;/p&gt;</description></item><item><title>所属がLINEヤフー株式会社になりました</title><link>https://blog.web-apps.tech/line-to-lineyahoo/</link><pubDate>Sun, 01 Oct 2023 23:10:05 +0900</pubDate><guid>https://blog.web-apps.tech/line-to-lineyahoo/</guid><description>&lt;p&gt;&lt;a href="https://blog.web-apps.tech/tags/%e8%bb%a2%e8%81%b7"&gt;転職タグ&lt;/a&gt;
はつけたものの転職ではないです。&lt;/p&gt;
&lt;p&gt;2023-10-01を以て所属がLINE株式会社からLINEヤフー株式会社に変わりました。&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>y-or-n for kill modified buffer</title><link>https://blog.web-apps.tech/y-or-n-for-kill-modified-buffer/</link><pubDate>Tue, 26 Sep 2023 23:13:06 +0900</pubDate><guid>https://blog.web-apps.tech/y-or-n-for-kill-modified-buffer/</guid><description>&lt;p&gt;emacs 29.1はuse-packageやeglotの同梱、tree-sitterのネイティブサポートなどが大きな変更として話題ですが、他にも非常に多くの変更があります。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://git.savannah.gnu.org/cgit/emacs.git/tree/etc/NEWS?h=emacs-29#n664" target="_blank" rel="noopener"&gt;そのうちの一つ&lt;/a&gt;
が、変更が加えられた後保存されていないbufferをkillしようとしたときの質問です。これまで、編集があるbufferのkillはyesまたはnoの二択でしたが、第三の選択肢、&lt;code&gt;save and then kill&lt;/code&gt;が加えられました。&lt;/p&gt;
&lt;p&gt;もともと&lt;code&gt;(fset 'yes-or-no-p 'y-or-n-p)&lt;/code&gt;として&lt;code&gt;y&lt;/code&gt;または&lt;code&gt;n&lt;/code&gt;で返事をすることが記憶された私の体はこれに順応することができず、毎回&lt;code&gt;y&lt;/code&gt;で止まってしまいます。そこでこれを再びy-or-nに置き換える方法を探したのですが、まだまだみんなemacs 29.1を使っていないのか、情報が全然ありませんでした。しかし(多分)唯一の記事として、&lt;a href="https://christiantietze.de/posts/2023/09/kill-unsaved-buffer-ux-action-labels/" target="_blank" rel="noopener"&gt;Kill Unsaved Emacs Buffers UX: Replacing Yes/No/Save with Meaningful Options&lt;/a&gt;
というブログ記事を見つけました。この記事は単純にy-or-nにするのではなく、もう少し踏み込んでいるのですが、それはさておき、これによると&lt;a href="https://github.com/emacs-mirror/emacs/blob/emacs-29.1/lisp/simple.el#L10837" target="_blank" rel="noopener"&gt;&lt;code&gt;kill-buffer--possibly-save&lt;/code&gt;&lt;/a&gt;
という関数で実装されているようです。
adviceをしても良いけれど、できれば関数全体をコピペして置き換えるみたいなことはやりたくないがどうしたモノか、と思っていたところ、&lt;code&gt;use-short-answers&lt;/code&gt;という、何やらよさげな変数名が目に入りました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;describe-variable&lt;/code&gt;で説明を見てみると、non-nilの時に&lt;code&gt;yes-or-no-p&lt;/code&gt;の代わりに&lt;code&gt;y-or-n-p&lt;/code&gt;を使うための変数、ということらしいということが分かりました(どうやら28.1で導入された様子。知らなかった)。&lt;code&gt;(setq use-short-answers t)&lt;/code&gt;として試したところ、上手い具合にy/n/sで確定できるようになりましたので、正解だったようです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;yes-or-no-p&lt;/code&gt;の説明を確認してみても、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If the ‘use-short-answers’ variable is non-nil, instead of asking for
&amp;ldquo;yes&amp;rdquo; or &amp;ldquo;no&amp;rdquo;, this function will ask for &amp;ldquo;y&amp;rdquo; or &amp;ldquo;n&amp;rdquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;と書いてありました。&lt;/p&gt;
&lt;p&gt;というわけで、&lt;code&gt;(fset 'yes-or-no-p 'y-or-n-p)&lt;/code&gt;を&lt;code&gt;(setq use-short-answers t)&lt;/code&gt;に置き換えて解決、という感じでした。めでたしめでたし。&lt;/p&gt;</description></item><item><title>Exa to Eza</title><link>https://blog.web-apps.tech/exa-to-eza/</link><pubDate>Mon, 18 Sep 2023 21:26:50 +0900</pubDate><guid>https://blog.web-apps.tech/exa-to-eza/</guid><description>&lt;p&gt;&lt;a href="https://blog.web-apps.tech/replacing-ls-with-exa/"&gt;2020年に&lt;code&gt;exa&lt;/code&gt;をインストールして&lt;/a&gt;
から、3年半弱&lt;code&gt;ls&lt;/code&gt;の代わりとして&lt;code&gt;exa&lt;/code&gt;を使用してきました。
設定としては以下のような感じで、&lt;code&gt;exa&lt;/code&gt;に何やらオプションを足した奴を&lt;code&gt;ls&lt;/code&gt;のエイリアスとして、追加で&lt;code&gt;ll&lt;/code&gt;、&lt;code&gt;la&lt;/code&gt;、&lt;code&gt;lla&lt;/code&gt;を設定している感じです:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;exa -Fgh --git --time-style=long-iso&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;la&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ls -a&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;ll&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ls -l&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;lla&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ls -la&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;で、不定期でやってるローカルのツール更新というか、&lt;code&gt;brew update &amp;amp;&amp;amp; brew outdated&lt;/code&gt;をしたところ、&lt;code&gt;exa&lt;/code&gt;のバージョンが(なんかよく分からない感じで)上がっていたので更新内容をチェックしに行ったところ、&lt;a href="https://github.com/ogham/exa/commit/fb05c421ae98e076989eb6e8b1bcf42c07c1d0fe" target="_blank" rel="noopener"&gt;exa is unmaintained, please use the active fork eza instead&lt;/a&gt;
というコミットが打たれていて、&lt;a href="https://github.com/eza-community/eza" target="_blank" rel="noopener"&gt;eza&lt;/a&gt;
を見に行ったら実際活発に開発されていて、7月末からすでに10回のリリースが行われているようでした。
個人的には&lt;code&gt;exa&lt;/code&gt;で困ってはいなかったモノの、2年以上リリースが打たれていないのも事実ですし、&lt;code&gt;eza&lt;/code&gt;のリリースノートを見る限りセキュリティフィックスなどもあるようなので、置き換えをしました。&lt;/p&gt;
&lt;h2 id="手順"&gt;手順&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;brew install eza&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sed -ie 's/exa/eza/' .zshrc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;brew uninstall exa&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;今のところ特に使用感は変わった感じはしないですが、一つだけ気づいたのは&lt;a href="https://github.com/eza-community/eza/pull/42" target="_blank" rel="noopener"&gt;symlinkのサイズ表示が変わった&lt;/a&gt;
くらいですかね。&lt;/p&gt;</description></item><item><title>Migrate Helm to Vertico Stack</title><link>https://blog.web-apps.tech/migrate-helm-to-vertico-stack/</link><pubDate>Sun, 10 Sep 2023 19:48:46 +0900</pubDate><guid>https://blog.web-apps.tech/migrate-helm-to-vertico-stack/</guid><description>&lt;p&gt;世の流れ的には、Helmといえば&lt;a href="https://helm.sh" target="_blank" rel="noopener"&gt;Kubernetes用のパッケージマネージャー&lt;/a&gt;
を思い浮かべる人が多いと思いますが、私にとってはHelmといえばやはり&lt;a href="https://github.com/emacs-helm/helm" target="_blank" rel="noopener"&gt;emacsのパッケージ&lt;/a&gt;
を思い浮かべます。emacs-helm(以下helm)は所謂fuzzy finder的なモノの一種で、emacsを使っていない人は雑にfzfとかpecoみたいな絞り込みをemacsでできるようにするやつ、と思えば想像しやすいと思います。&lt;/p&gt;
&lt;p&gt;helmはなかなか歴史の長いパッケージで、2012年5月15日にanything.elからForkをしたという&lt;a href="https://github.com/emacs-helm/helm/commit/b016418949e60bc5e9cb4f135a17d129b2b2f28a" target="_blank" rel="noopener"&gt;コミット&lt;/a&gt;
が打たれています。私個人としては2015年7月にhelmを導入したっぽい記録(&lt;a href="https://github.com/nasa9084/dotfiles/commit/c256d97362af972c724fbc35dc7fd701fe35ead6" target="_blank" rel="noopener"&gt;commit&lt;/a&gt;
/&lt;a href="https://twitter.com/nasa9084/status/619565563744923648" target="_blank" rel="noopener"&gt;tweet&lt;/a&gt;
)が残っています。そこから数日前まで、かれこれ8年余りの期間にわたってhelmを使ってきました。使ってきた、とは言っても導入したときに多少使い勝手の調整をして以来、ほとんど設定は変えておらず、機能的にも&lt;code&gt;helm-M-x&lt;/code&gt;、&lt;code&gt;helm-find-files&lt;/code&gt;、&lt;code&gt;helm-show-kill-ring&lt;/code&gt;、&lt;code&gt;helm-buffers-list&lt;/code&gt;くらいしか使っていませんでした。基本的にはMELPAからインストールされる最新版を使っていたのですが、8年使っていてもアップデートで壊れた記憶は多分1回くらいしかなくて、かなりの頻度でコミットが打たれているのに安定していた、という印象があります。&lt;/p&gt;
&lt;p&gt;8年の間にも、&lt;a href="https://github.com/abo-abo/swiper" target="_blank" rel="noopener"&gt;Ivy/Counsel&lt;/a&gt;
が話題になったり、icomplete-vertical-mode/fido-vertical-modeという補完UIが標準に追加されたりと、いろいろと流行が変わっていたのは認識はしていたのですが、まぁなんやかんやあり8年間helmを使い続けてきました。&lt;/p&gt;
&lt;p&gt;そうこうしていたところ、最近emacs 29.1がリリースされ、同じく長らく使用してきた&lt;a href="https://github.com/jwiegley/use-package" target="_blank" rel="noopener"&gt;use-package&lt;/a&gt;
(どのタイミングで導入したのかは不明ですが、GitHub上での&lt;a href="https://github.com/nasa9084/dotfiles/commit/897277d5f5a1b434c9c06d359c3a909227714312" target="_blank" rel="noopener"&gt;first commit&lt;/a&gt;
で既に導入済みだったっぽいのでhelmより長く使っていることになります)がemacs標準搭載となりました。use-package以外のパッケージに関する設定はuse-packageを使ってやっていて、他のパッケージがインストールされていないときにインストールするというのもuse-packageでやっていて、という感じなのですが、そうなるとuse-packageは誰が入れてくれるんだ、ということになり結局use-packageだけは&lt;code&gt;package-install&lt;/code&gt;を&lt;a href="https://github.com/nasa9084/dotfiles/commit/ee6aa1b313ed896719ed2040f3f88d2f47e8b330" target="_blank" rel="noopener"&gt;直接呼び出すことでインストールしていた&lt;/a&gt;
のですが、use-packageがbuilt-inとなったことで、晴れて&lt;code&gt;package-install&lt;/code&gt;の直接呼び出しも&lt;a href="https://github.com/nasa9084/dotfiles/commit/13e938297a813111e316fc62189a17357c54d63a" target="_blank" rel="noopener"&gt;不要となりました&lt;/a&gt;
。その変更ついでに、いろいろと設定を見直したりとか、ローカルでのみ設定されていた諸諸をGitHubにpushしたりとか、そんなことをやったのですが、その一環として(?)helmから&lt;a href="https://github.com/minad/vertico" target="_blank" rel="noopener"&gt;vertico&lt;/a&gt;
に乗り換えてみました。&lt;/p&gt;
&lt;p&gt;helmからverticoに移行して一番の大きな違いは、helmはそれ自体が巨大パッケージで、いろいろなモノがhelmでまかなわれていましたが、verticoはそれ自体はかなり小さく保たれていて、いろいろなパッケージを組み合わせることで同じような機能を実現する、というところです。個人的にはでかいフレームワークより小さいライブラリ類を組み合わせてアプリを書く方が好きなので、そういった意味でもverticoは好きになることができそうです。&lt;/p&gt;
&lt;p&gt;今のところ組み合わせているものは&lt;a href="https://github.com/minad/marginalia" target="_blank" rel="noopener"&gt;marginalia&lt;/a&gt;
と&lt;a href="https://github.com/oantolin/orderless" target="_blank" rel="noopener"&gt;orderless&lt;/a&gt;
の二つ。&lt;/p&gt;
&lt;p&gt;marginaliaはminibuffer completionに何やら情報を足すやつで&lt;code&gt;M-x&lt;/code&gt;でコマンドの簡単な説明が見られたり、&lt;code&gt;find-file&lt;/code&gt;でファイルのパーミッションやら最終更新時間やらが見られるようになります。インストールしただけでも情報が見れるようになって便利なのですが、そのままだとファイルの更新時間が&lt;code&gt;2023 Sep 10&lt;/code&gt;みたいなかんじで月名を使った表示になっており、分からなくはないんですけど日本人としてはやはり&lt;code&gt;2023-09-10&lt;/code&gt;と数字を使って表現してくれた方がぱっと見でわかりやすいので、次の様にadviceで&lt;code&gt;marginalia--time-absolute&lt;/code&gt;を置き換えることで数字表記に修正しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-emacs-lisp" data-lang="emacs-lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;marginalia--time-absolute--month-number&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;Format TIME as an absolute age but use month number instead of month name.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;let&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;system-time-locale&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;C&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;format-time-string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;decoded-time-year&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;decode-time&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;current-time&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;decoded-time-year&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;decode-time&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34; %Y-%m-%d&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;%m-%d %H:%M&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;advice-add&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;marginalia--time-absolute&lt;/span&gt; &lt;span class="nb"&gt;:override&lt;/span&gt; &lt;span class="nf"&gt;#&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;marginalia--time-absolute--month-number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;orderlessは候補の絞り込みをするときに、完全一致や前方一致だけでなく、fuzzy matchをしてくれるようになるやつで、たとえば&lt;code&gt;abc&lt;/code&gt;と入力すると&lt;code&gt;a.*b.*c.*&lt;/code&gt;にマッチする奴を返してくれるようになります(多分これは触らないと便利さはわかりにくい・・・)。&lt;/p&gt;</description></item><item><title>梅仕事2023</title><link>https://blog.web-apps.tech/ume-2023/</link><pubDate>Mon, 12 Jun 2023 14:14:25 +0900</pubDate><guid>https://blog.web-apps.tech/ume-2023/</guid><description>&lt;p&gt;皆さん、6月です。6月と言えば、そう、梅の季節ですね。今年もあちこちで梅が売られており、例に漏れず買ってきて梅酒を漬けました。
今年はちょっと面倒な気持ちになったので、梅シロップは作らない予定です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2023/images/IMG_2529_hu_450a941812872ab7.jpg" alt="去年の梅酒" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.web-apps.tech/ume-2022"&gt;昨年の梅酒&lt;/a&gt;
はこんな感じです。昨年は黒糖を使って漬けたため、色がすごいことになっています。味見をしたところ、もう少し熟成感というか、まろやかになるといいな、という感じでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2023/images/IMG_2531_hu_c60ff285f56455ea.jpg" alt="今年の梅酒" /&gt;
&lt;/p&gt;
&lt;p&gt;今年は見てのとおり透明です。ここ数年は日本酒を使ったり、泡盛を使ったり、黒糖を使ったりと変わり種の梅酒を漬け続けていましたので、今年はホワイトリカー、氷砂糖という至って普通のレシピで作りました。&lt;/p&gt;
&lt;p&gt;また来年お会いしましょう&lt;/p&gt;</description></item><item><title>Fellow Ode Gen2を買った</title><link>https://blog.web-apps.tech/fellow-ode-gen2/</link><pubDate>Thu, 11 May 2023 22:00:00 +0900</pubDate><guid>https://blog.web-apps.tech/fellow-ode-gen2/</guid><description>&lt;p&gt;みなさん、コーヒーは好きですか。私は豆でコーヒーを買ってくる位には好きで、ミルで豆を挽いてコーヒーメーカーで雑に淹れる、という感じでやっております。&lt;/p&gt;
&lt;p&gt;扨、そんな私ですがこれまでコーヒーミルはメリタのパーフェクトタッチIIという電動ミルを使っていました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fellow-ode-gen2/images/melita-perfect-touch-ii_hu_16f5e4e6c02c3428.png" alt="メリタ パーフェクトタッチII" /&gt;
&lt;/p&gt;
&lt;p&gt;これは大学生の時に買ったやつで、掃除もろくにしないで雑に使っていたため、かなりひどい見た目になっていますね。定価は多分12,000円くらい？で、当時ビックカメラあたりで5,000円くらいで購入しました。電動ミルとしてはかなり手頃な値段で買える割にプロペラ式ではない(プロペラ式のミルは安いけど引いた後の粉の粒度が安定しない)ミルということで、私のコーヒー生活をかなり豊かにしてくれたと思っています。&lt;/p&gt;
&lt;p&gt;とはいえ値段なりの問題はいくつかあって、最大の問題は微粉と静電気でした。すごく微粉が出るし(微粉が多いと雑味が多くなる、と言われている)、粉受けがプラスチックなので静電気で粉受けの内側にくっつく、ダマになる、挙げ句粉受けの外も粉だらけになるという感じでした。エントリーモデルとしては最高だと思うんですけどね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fellow-ode-gen2/images/melita-tray_hu_b150a3f2fc1e4268.png" alt="パーフェクトタッチの粉受け" /&gt;
&lt;/p&gt;
&lt;p&gt;まぁそんなわけで毎回キッチンをコーヒーだらけにするのがストレスだなー、良いミルが欲しいなー、と思っていたところ、Fellowという会社からの最新ミルであるODE Gen2というミルが日本でも発売になるということで予約して購入しました。値段は61,600円。高いですね。私はちょうどボーナスが出たので高いなーと思いながらポチりました。&lt;/p&gt;
&lt;p&gt;参考にしたレビュー動画はこちらです:&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/3f8dv72Ex6U?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;このミルの何が一番良いかというと、静電気防止機能とノッカーがついているところで、前述の通り静電気が主なストレスの原因だったのと、粉を落としきるためにパーフェクトタッチを叩いていたので、ノッカーがあるのはすごくいいと感じました。&lt;/p&gt;
&lt;p&gt;販売ページはこちら: &lt;a href="https://kigu.coffee/products/ode-brew-grinder-gen2" target="_blank" rel="noopener"&gt;Fellow ODE Brew Grinder Gen 2&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;届いたモノがこちら:
&lt;img loading="lazy" src="https://blog.web-apps.tech/fellow-ode-gen2/images/fellow-ode-gen2_hu_ed9b62f26e4adde2.png" alt="Fellow ODE Gen 2" /&gt;
&lt;/p&gt;
&lt;p&gt;まず、デザインが良いですよね。安っぽさを感じさせないですし、大きなダイヤルが使いやすそうです。&lt;/p&gt;
&lt;p&gt;挽いた粉を比較してみましょう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fellow-ode-gen2/images/coffee-powder-perfect-touch_hu_e5f173d8cc2be5c.png" alt="パーフェクトタッチIIで挽いた粉" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fellow-ode-gen2/images/coffee-powder-ode-gen2_hu_31b22e83af368af1.png" alt="ODE Gen2で挽いた粉" /&gt;
&lt;/p&gt;
&lt;p&gt;黄色い皿に入っている方がパーフェクトタッチIIで挽いた粉です。微粉が静電気でダマになっているのが見て取れますし、静電気で皿の壁面に細かい粉がついてしまっています。一方ODE Gen2で挽いた粉は粒度が一定で、静電気もひどくありません。まぁ、(定価ベースで)値段が6倍くらい違うので、同じ結果では困るのですが・・・&lt;/p&gt;
&lt;p&gt;粉受けも見てみましょう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fellow-ode-gen2/images/ode-gen2-tray_hu_c537677cc0890f54.png" alt="ODE Gen2の粉受け" /&gt;
&lt;/p&gt;
&lt;p&gt;粉受けにもほとんど粉が残っていません。良いですね。&lt;/p&gt;
&lt;p&gt;スペック的には、フレンチプレスで使えるくらいの粗い挽き目から、マキネッタ用にもなんとか使えるかな、位の範囲で挽けるようです。&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>YAPC::Kyoto 2023に参加してきた</title><link>https://blog.web-apps.tech/yapc-kyoto-2023/</link><pubDate>Tue, 21 Mar 2023 00:54:00 +0900</pubDate><guid>https://blog.web-apps.tech/yapc-kyoto-2023/</guid><description>&lt;p&gt;COVID-19の影響を受け多くのテックカンファレンスがオンラインのみの開催となり、数年ぶりにオフラインのテックカンファレンス、&lt;a href="https://yapcjapan.org/2023kyoto/" target="_blank" rel="noopener"&gt;YAPC::Kyoto 2023&lt;/a&gt;
に参加しました。
YAPC::Kyotoは2020年に開催予定だったものの、COVID-19の影響で開催を延期していましたが、今年ようやく、YAPC::Kyoto 2023として開催されました。&lt;/p&gt;
&lt;p&gt;YAPCはPerlのイベントで、“Yet Another Perl Conference&amp;quot;の略です。twitterハッシュタグは前回に引き続き&lt;a href="https://twitter.com/hashtag/yapcjapan" target="_blank"&gt;#yapcjapan&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;京都はおそらく&lt;a href="https://www.ospn.jp/osc2018-kyoto/" target="_blank" rel="noopener"&gt;OSC 2018 Kyoto&lt;/a&gt;
以来で、約5年ぶりに京都に来た、という感じです。今回はちゃんと会場であるKRP近くの東横イン(東横イン京都五条大宮)を確保することに成功し、前日祭の前日夜に京都に着き、本祭の翌日夜に東京に帰るというスケジュールでした。&lt;/p&gt;
&lt;p&gt;初日は到着が遅かったこともあり、深夜に&lt;a href="https://twitter.com/hashtag/yapcramen" target="_blank"&gt;#yapcramen&lt;/a&gt;
することとなりました。
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="qme" dir="ltr"&gt;&lt;a href="https://x.com/hashtag/yapcjapan?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yapcjapan&lt;/a&gt; &lt;a href="https://x.com/hashtag/yapcramen?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yapcramen&lt;/a&gt; &lt;a href="https://t.co/xjNb09VCXW"&gt;https://t.co/xjNb09VCXW&lt;/a&gt; &lt;a href="https://t.co/uAcIisYkGG"&gt;pic.twitter.com/uAcIisYkGG&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/1636754821641392131?ref_src=twsrc%5Etfw"&gt;March 17, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;h1 id="yapckyoto-2023-前日祭"&gt;YAPC::Kyoto 2023 前日祭&lt;/h1&gt;
&lt;p&gt;マスクの着用は当人の判断に委ねる、という発表が政府からあったものの、まだまだ感染が気になる今日この頃、今回のYAPCでは前夜祭ではなく前日祭という形で前日イベントが開催されました。ボケボケしていたらチケットがすべてはけてしまっており、当日になってもキャンセルがなかったので仕方ないから京都観光でもするか、と京都駅〜四条付近をうろついていたら参加率的に補欠全員繰り上げ、という連絡が運営からあったため途中からではあるものの前日祭に参加しました。&lt;/p&gt;
&lt;p&gt;なお昼ご飯は&lt;a href="https://yoshimura-gr.com/sobanomi/" target="_blank" rel="noopener"&gt;蕎麦の実 よしむら&lt;/a&gt;
でそばづくし膳とそば茶クリームプリンを食べました。&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="zxx" dir="ltr"&gt;&lt;a href="https://t.co/nbEJmygDYb"&gt;pic.twitter.com/nbEJmygDYb&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/1636934422955184128?ref_src=twsrc%5Etfw"&gt;March 18, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;客単価あげていこうな &lt;a href="https://t.co/6zKjaRyFqK"&gt;pic.twitter.com/6zKjaRyFqK&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/1636937803090251778?ref_src=twsrc%5Etfw"&gt;March 18, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;参加したのは東西対抗LTマッチからだったんですが、LTというモノを見るのも久々でしたし、LTは初めてという人が多数LTをしていてなかなか良かったですね。LTでも容赦なく&lt;a href="https://twitter.com/dankogai" target="_blank"&gt;@dankogai&lt;/a&gt;
sanからコメントが入るのはこれがオフラインのYAPCだ！！という感じでした。&lt;/p&gt;
&lt;p&gt;心に残った一言は「数の暴力にはオートスケールは無意味」です。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;「数の暴力にはオートスケールは無意味」わかる &lt;a href="https://x.com/hashtag/yapcjapan?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yapcjapan&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/1636993563459477504?ref_src=twsrc%5Etfw"&gt;March 18, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;終わった後は&lt;a href="https://twitter.com/gomaaburamax" target="_blank"&gt;@gomaaburamax&lt;/a&gt;
や&lt;a href="https://twitter.com/tomio2480" target="_blank"&gt;@tomio2480&lt;/a&gt;
、学生たちと飲みに行ったり、さらにははしご酒で&lt;a href="https://twitter.com/sweet_potato_hs" target="_blank"&gt;@sweet_potato_hs&lt;/a&gt;
と飲みに行ったりしました。&lt;/p&gt;
&lt;h1 id="yapckyoto-2023"&gt;YAPC::Kyoto 2023&lt;/h1&gt;
&lt;p&gt;今回はなんと(!)寝坊をしなかったためオープニングから参加することができました。めでたし、めでたし。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="qme" dir="ltr"&gt;&lt;a href="https://x.com/hashtag/yapcramen?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yapcramen&lt;/a&gt; &lt;a href="https://t.co/GLVTpUlqcH"&gt;pic.twitter.com/GLVTpUlqcH&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/1637318340657176576?ref_src=twsrc%5Etfw"&gt;March 19, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;やはり印象に残ったトークは&lt;a href="https://twitter.com/moznion" target="_blank"&gt;@moznion&lt;/a&gt;
sanの&lt;a href="https://yapcjapan.org/2023kyoto/timetable.html#talk-4" target="_blank" rel="noopener"&gt;ソフトウェアエンジニアリングサバイバルガイド: 廃墟を直す、廃墟を出る、廃墟を壊す、あるいは廃墟に暮らす、廃墟に死す &lt;/a&gt;
ですね。ゲストトークなためベストトークに投票できなかったのが残念です・・・。特に、「そして人類は廃墟を越える遺跡に出会っていくのであるが・・・」という話の後に&lt;a href="https://twitter.com/uzulla" target="_blank"&gt;@uzulla&lt;/a&gt;
sanから「古墳はどうですか」などという質問が上がっていたのは面白かったです。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;「古代文明の古墳はどうですか」「古墳は無理ですね、作り直しましょう」「なるほどありがとうございます！！！」&lt;a href="https://x.com/hashtag/yapcjapan?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#yapcjapan&lt;/a&gt;&lt;/p&gt;&amp;mdash; uzulla (@uzulla) &lt;a href="https://x.com/uzulla/status/1637331563158605826?ref_src=twsrc%5Etfw"&gt;March 19, 2023&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;皆さん金の弾丸で廃墟をなんとかしていきましょう。&lt;/p&gt;</description></item><item><title>Air Bangle</title><link>https://blog.web-apps.tech/apple-watch-air-bangle/</link><pubDate>Tue, 21 Feb 2023 23:00:06 +0900</pubDate><guid>https://blog.web-apps.tech/apple-watch-air-bangle/</guid><description>&lt;p&gt;あけましておめでとうございます。11月頃にMakuakeで応援購入したApple watch用のバングルが届いたので開封しました。&lt;/p&gt;
&lt;p&gt;購入したのは&lt;a href="https://www.makuake.com/project/air-bangle02/" target="_blank" rel="noopener"&gt;Air bangle&lt;/a&gt;
のべっ甲カラーです。
Air bangleはその名の通り、世にも珍しい(?)バングル型のApple watchバンドです。
鯖江のメガネ作りの技術で作られているそうです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/box_hu_d6a2adcb860e3616.jpeg" alt="箱" /&gt;
&lt;/p&gt;
&lt;p&gt;箱はこんな感じで、思っていたよりも高級感があります。クラウドファンディングで作られたモノはもっとがさつな袋に入ってくるものだと思っていたのですが、そうでもないようです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/contents_hu_e21653f8c882b0fb.jpeg" alt="中身" /&gt;
&lt;/p&gt;
&lt;p&gt;中にはアダプタと本体、取扱説明書が入っていました。取説の内容はほとんどQRコードで、Apple watchへの装着方法や着け心地の調整方法などは動画で確認することができます。
保証も一年ついていて安心です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/color_hu_9d84a5ceb0014403.jpeg" alt="色味" /&gt;
&lt;/p&gt;
&lt;p&gt;色はこんな感じ。Makuakeのページ上で見たイメージよりは濃い色に見えます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/size_hu_a0aaefda858b8351.jpeg" alt="サイズ" /&gt;
&lt;/p&gt;
&lt;p&gt;購入したのはApple watch 38/40/41mm用のサイズ4(17〜18.5cm)です。これまではソロループのサイズ9や、ブレイデッドソロループのサイズ8がちょうどいい、と思っていた位の腕の太さです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/stand_hu_4b265dc538ce787b.jpeg" alt="スタンド" /&gt;
&lt;/p&gt;
&lt;p&gt;おまけ(?)として専用のスタンドもついています。簡単な作りではありますが木製で悪くないです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/stand_rev_hu_1beb3995d1f55876.jpeg" alt="スタンド裏" /&gt;
&lt;/p&gt;
&lt;p&gt;表から見ると木目が良い感じですが、実際は突板で、裏から見るとMDF材まんまなので表からだけ見ましょう。(makuakeのページを見るとチェリー突板/MDF材、とのことです)&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/plate_hu_bbce70f6291f36a0.jpeg" alt="ベータチタンプレート" /&gt;
&lt;/p&gt;
&lt;p&gt;Apple watchに固定するプレート部分もきれいです。安モノだとこういう部分があまりきれいではなかったりするんですよね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/adapter_hu_8b39d22ec7806734.jpeg" alt="アダプタ" /&gt;
&lt;/p&gt;
&lt;p&gt;実際にApple watchに装着する際はこのアダプタを使用します。アダプタは購入時に黒かシルバーから選ぶことができますが、私のApple watchはミッドナイトカラーなので黒にしました。
もちろん、きちんとロック部分も実装されています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/apple-watch-air-bangle/images/charge_hu_3f552cdec775c0ad.jpeg" alt="充電スタンド" /&gt;
&lt;/p&gt;
&lt;p&gt;平置きタイプのドックなどは使えないと思いますが、&lt;a href="https://amzn.to/3ILbUdT" target="_blank" rel="noopener"&gt;Amazonで売っている安価な横置きタイプの充電スタンド&lt;/a&gt;
であれば問題無く使用できます。&lt;/p&gt;
&lt;p&gt;今回購入したべっ甲カラーはまだ正式には発売前なのでクラウドファンディングが終了した現在は購入することができませんが、第一弾で販売された3色は&lt;a href="https://airbangle.com/" target="_blank" rel="noopener"&gt;公式サイト&lt;/a&gt;
から購入できるようなので、気になった人は購入してみてください。
サイズは38/40/41mm Apple watch用と42/44/45mm Apple watch用でそれぞれ5サイズ展開、届いた後にサイズが合わなかった場合も無償で交換してくれるそうです。&lt;/p&gt;
&lt;p&gt;なお、予想していたことではありますがキーボード操作をするときは邪魔になりますので、キーボード操作をするときはソロループ、外出時はAir bangleといった使い分けが必要そうです。&lt;/p&gt;</description></item><item><title>2022年買って良かったモノ</title><link>https://blog.web-apps.tech/2022-must-buy/</link><pubDate>Sat, 17 Dec 2022 00:15:00 +0900</pubDate><guid>https://blog.web-apps.tech/2022-must-buy/</guid><description>&lt;p&gt;まぁ定番のネタですが、今年もいろいろ買ったので見ていきましょう。&lt;/p&gt;
&lt;h2 id="車関連"&gt;車関連&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Honda N-ONE
&lt;ul&gt;
&lt;li&gt;思ったより乗っているので、次に買い換えるときはもっとお金を掛けても良いな、という気持ち&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3V4uUXm" target="_blank" rel="noopener"&gt;Anker PowerDrive III Duo&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;最近はカーチャージャーもUSB-Cのが有るんですね&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3uThdA2" target="_blank" rel="noopener"&gt;Anker PowerLine Ⅲ Flow USB-C &amp;amp; ライトニング ケーブル&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;車関連ではないけど車で使っているので。絡まない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3FUSAJF" target="_blank" rel="noopener"&gt;サムライプロデュース 超吸水 サムライタオル 大判 Lサイズ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;洗車後はこれでほぼ一発&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3Yof4dn" target="_blank" rel="noopener"&gt;クロックス スウィフトウォーター エクスペディション&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;永遠にサンダルを履いている。これは運転用です&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="アクアリウム"&gt;アクアリウム&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://item.rakuten.co.jp/chanet/13287/" target="_blank" rel="noopener"&gt;ミナミヌマエビ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/63_HyRkiVp8?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://item.rakuten.co.jp/chanet/239232/" target="_blank" rel="noopener"&gt;GEX グラステリアフィット 200LOW&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3jaEDOB" target="_blank" rel="noopener"&gt;コトブキ工芸 ミニフィットフィルターMF&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;寝室で一晩中動かしてても平気なくらい静か&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3hBgOz5" target="_blank" rel="noopener"&gt;GEX クリアLED ピテラ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;小さくて明るくて可愛い。神。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ゲーム"&gt;ゲーム&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3PusH6J" target="_blank" rel="noopener"&gt;Pokémon LEGENDS アルセウス&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3Yusm7T" target="_blank" rel="noopener"&gt;Nintendo Switch Proコントローラー&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;勝手に動かないコントローラー、快適・・・&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ガジェット類"&gt;ガジェット類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3FCi4Kk" target="_blank" rel="noopener"&gt;グリーンハウス iPhone巻取り式充電ケーブル USB Type-C ライトニングケーブル&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;鞄に入れておくケーブルは巻き取り式派なんですよね&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3V5Vwau" target="_blank" rel="noopener"&gt;グランサンク ブルーハムハム i select iPhoneケース&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ガジェットかどうかは微妙。ブルーハムハム可愛いですね&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3WjNVq0" target="_blank" rel="noopener"&gt;TALENANA for Apple Watch フィルム&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;柔らかくないタイプのフィルム&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3BFT0kz" target="_blank" rel="noopener"&gt;SwitchBot 温湿度計プラス&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;APIの検証用に買っただけだったんだけど、プラスじゃない奴と比べて圧倒的に見やすい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="日用品など"&gt;日用品など&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3UZZ7XH" target="_blank" rel="noopener"&gt;ビホウマスク AG抗菌+ダブルフィルタ 横ワイドまっ白なやさしいマスク(個包装) 30枚入 &lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;別にこれ自体とかAG抗菌とかダブルフィルタとかに特別こだわりがあるわけではないけど、大きいサイズのマスクはきつくなくて良い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3FwH2uJ" target="_blank" rel="noopener"&gt;アイリスオーヤマ 家具転倒防止伸縮棒ML ホワイト&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;今年、地震多かったですね。本棚が全然揺れなくなった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3PBJIvQ" target="_blank" rel="noopener"&gt;ジョイ ジェルタブ 食洗機用洗剤&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;継続購入ではあるけれど、他の洗剤も使ってみてやっぱりこれが良くて戻ってきた&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3uXROFi" target="_blank" rel="noopener"&gt;レノア リセット 柔軟剤&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;完全に、ではないけど明らかにしわが少ないと思う&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3HHOjKY" target="_blank" rel="noopener"&gt;バルクオム シャンプー&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;高いけど匂いが好き。だけど高い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="書籍"&gt;書籍&lt;/h2&gt;
&lt;p&gt;以前から継続的に購入している続き物のコミック・小説などは除く&lt;/p&gt;</description></item><item><title>二つのファイルの共通行(または共通しない行)を得る</title><link>https://blog.web-apps.tech/use-comm-command-to-get-common-line/</link><pubDate>Wed, 28 Sep 2022 23:59:17 +0900</pubDate><guid>https://blog.web-apps.tech/use-comm-command-to-get-common-line/</guid><description>&lt;p&gt;例えば、サービスAでは登録されているけれどもサービスBには登録されていないユーザの一覧を得たい、という様な場合。もちろん&lt;code&gt;diff&lt;/code&gt;でよしなにやることもできますが、&lt;code&gt;comm&lt;/code&gt;も便利です。&lt;/p&gt;
&lt;p&gt;例えば次の様にリストがあるとします。&lt;/p&gt;
&lt;p&gt;サービスAのユーザーリスト(users_a.txt):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;charlie
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dave
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;oscar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;サービスBのユーザーリスト(users_b.txt):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;charlie
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;isaac
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;justin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mallory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;oscar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;これらに対して&lt;code&gt;comm&lt;/code&gt;を使うと次の出力が得られます:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ comm users_a.txt users_b.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; charlie
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dave
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; isaac
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; justin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; mallory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; oscar
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;TABで揃えられた列がそれぞれ左から、Aにだけ存在する行、Bにだけ存在する行、Cにだけ存在する行、となっています。これだけだと別にそれほど便利ではないんですが、&lt;code&gt;comm&lt;/code&gt;はそれぞれの行を非表示にする事もできます。それぞれ、非表示にしたい行を&lt;code&gt;-1&lt;/code&gt; &lt;code&gt;-2&lt;/code&gt; &lt;code&gt;-3&lt;/code&gt;で指定します。&lt;/p&gt;
&lt;p&gt;Aだけに存在する行を表示する:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ comm -23 users_a.txt users_b.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;alice
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bob
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dave
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;両方に存在する行を表示する:&lt;/p&gt;</description></item><item><title>RenovateでGitHub Actionsで使っているHugoを更新する</title><link>https://blog.web-apps.tech/renovate-hugo-version/</link><pubDate>Tue, 27 Sep 2022 01:53:45 +0900</pubDate><guid>https://blog.web-apps.tech/renovate-hugo-version/</guid><description>&lt;p&gt;GitHub ActionsとHugoを使用して静的サイト生成を行う場合、&lt;a href="https://github.com/peaceiris/actions-hugo" target="_blank" rel="noopener"&gt;peaceiris/actions-hugo&lt;/a&gt;
を使用するか、自分で適当にHugoをインストールするかのいずれかが一般的だと思います。このブログでは、セットアップ当初はpeaceiris/actions-hugoを使っていたのですが、最近debパッケージを自分でインストールする方式に切り替えました。
&lt;a href="https://github.com/gohugoio/hugo/releases" target="_blank" rel="noopener"&gt;gohugoio/hugoのreleases&lt;/a&gt;
から直接debパッケージを持ってきているので、peaceiris/actions-hugoとは違い&lt;code&gt;latest&lt;/code&gt;指定をする事ができず、Hugoの更新を手動で行う必要があり、ちょっと面倒だな〜と感じていました(しかもHugoは結構開発が活発で、更新もはやいんですよね)。&lt;/p&gt;
&lt;p&gt;仕事のリポジトリでは最近renovateがどんどん導入されているので、これを機にrenovateを導入することにしました。&lt;/p&gt;
&lt;p&gt;Hugoのバージョンは&lt;a href="https://github.com/nasa9084/blog.web-apps.tech/blob/7d285d9448d11cdfb09369748229f35b63f836cc/.github/workflows/gh-pages.yml#L31-L32" target="_blank" rel="noopener"&gt;GitHub ActionsのWorkflowファイル内にenvで指定されていて&lt;/a&gt;
、もちろん標準状態のrenovateはこれを検知・更新してくれません。これに対応するには、&lt;a href="https://docs.renovatebot.com/configuration-options/#regexmanagers" target="_blank" rel="noopener"&gt;regexManagers&lt;/a&gt;
を使用します。&lt;/p&gt;
&lt;p&gt;regexManagersは正規表現でバージョン番号を引っかけて更新してくれる&lt;a href="https://docs.renovatebot.com/modules/manager/" target="_blank" rel="noopener"&gt;manager&lt;/a&gt;
で、&lt;code&gt;fileMatch&lt;/code&gt;と&lt;code&gt;matchStrings&lt;/code&gt;という二つの正規表現を書くことで使う事ができます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fileMatch&lt;/code&gt;はその名の通り、どのファイルを監視するかを指定する正規表現で、今回はGitHub Actionsの設定ファイルを監視して欲しいので、デフォルトの&lt;code&gt;github-actions&lt;/code&gt; managerが監視する正規表現をそのままコピーしてきて使用しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;#34;fileMatch&amp;#34;: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;^(workflow-templates|\.github\/workflows)\/[^/]+\.ya?ml$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(^|\/)action\.ya?ml$&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;matchStrings&lt;/code&gt;はバージョンを引っかけるための正規表現で、&lt;code&gt;datasource&lt;/code&gt;、&lt;code&gt;depName&lt;/code&gt;、&lt;code&gt;currentValue&lt;/code&gt;の三つの値をキャプチャするか、&lt;code&gt;datasourceTemplate&lt;/code&gt;、&lt;code&gt;depNameTemplate&lt;/code&gt;、&lt;code&gt;currentValueTemplate&lt;/code&gt;で値を指定する必要があります。&lt;code&gt;datasource&lt;/code&gt;(&lt;code&gt;datasourceTemplate&lt;/code&gt;)と&lt;code&gt;depName&lt;/code&gt;(&lt;code&gt;depNameTemplate&lt;/code&gt;)はバージョンを比較するためのデータソースと依存の名称で、今回はGitHub上にあるgohugoio/hugoリポジトリのリリースと比較をしたいため、&lt;code&gt;datasourceTemplate&lt;/code&gt;に&lt;code&gt;github-releases&lt;/code&gt;を、&lt;code&gt;depNameTemplate&lt;/code&gt;に&lt;code&gt;gohugoio/hugo&lt;/code&gt;を指定しました。&lt;code&gt;currentValue&lt;/code&gt;(&lt;code&gt;currentValueTemplate&lt;/code&gt;)は現在のバージョン番号を表す値で、これはGitHub Actionsの設定ファイルに書かれている値なので、&lt;code&gt;matchStrings&lt;/code&gt;で引っかけてキャプチャします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;#34;matchStrings&amp;#34;: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HUGO_VERSION: (?&amp;lt;currentValue&amp;gt;.*)&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;#34;datasourceTemplate&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;github-releases&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;#34;depNameTemplate&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;gohugoio/hugo&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;設定ファイル全体としては次の様になります:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;$schema&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://docs.renovatebot.com/renovate-schema.json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;extends&amp;#34;: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;config:base&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;regexManagers&amp;#34;: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;{&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;fileMatch&amp;#34;: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;^(workflow-templates|\.github\/workflows)\/[^/]+\.ya?ml$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;(^|\/)action\.ya?ml$&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;matchStrings&amp;#34;: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;HUGO_VERSION: (?&amp;lt;currentValue&amp;gt;.*)&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;datasourceTemplate&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;github-releases&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;depNameTemplate&amp;#34;: &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;gohugoio/hugo&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;これで無事&lt;a href="https://github.com/nasa9084/blog.web-apps.tech/pull/11" target="_blank" rel="noopener"&gt;renovateがHugoのバージョンをチェックしてくれる&lt;/a&gt;
様になりました。めでたしめでたし。&lt;/p&gt;</description></item><item><title>GitHub PagesをActionsからデプロイする形式に変更した</title><link>https://blog.web-apps.tech/use-pages-with-actions/</link><pubDate>Thu, 01 Sep 2022 01:58:19 +0900</pubDate><guid>https://blog.web-apps.tech/use-pages-with-actions/</guid><description>&lt;p&gt;2022年9月1日現在、このブログはmarkdownファイルからHugoを使って静的サイトを生成し、GitHub Pagesで公開しています。元々GitHub Pagesにページをデプロイするには、生成済みページを入れた専用のブランチ(一般に&lt;code&gt;gh-pages&lt;/code&gt;)を用意するか、生成済みページを入れたディレクトリを用意するか、という二択で、いずれにせよページを生成してから生成されたページをGitHubにpushする必要がありました。前者の場合&lt;code&gt;gh-pages&lt;/code&gt;ブランチは&lt;code&gt;main&lt;/code&gt;ないし&lt;code&gt;master&lt;/code&gt;ブランチとは一切関係の無いコミット履歴となり、ぱっと見よく分からないですし、後者の場合gitのcommit logにサイト生成のコミットが入ってしまいきれいではありませんし、CIでbuild/pushをしている場合ローカルに毎回pullする必要も発生します。当サイトでも&lt;code&gt;gh-pages&lt;/code&gt;ブランチに生成済みページをpushする運用となっていました。&lt;/p&gt;
&lt;p&gt;ところが最近、&lt;a href="https://github.blog/changelog/2022-07-27-github-pages-custom-github-actions-workflows-beta/" target="_blank" rel="noopener"&gt;GitHub Actionsから直接GitHub Pagesにページをデプロイできる様になった&lt;/a&gt;
というではないですか。これは試してみるしかない、ということで設定を変更してみました。&lt;/p&gt;
&lt;p&gt;まず、リポジトリのSettings &amp;gt; Pagesから、SourceをGitHub Actionsに変更します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/use-pages-with-actions/images/gh-pages-config_hu_3e477d109debc165.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;次に、GitHub Actionsのworkflow設定を&lt;a href="https://github.com/actions/starter-workflows/tree/main/pages" target="_blank" rel="noopener"&gt;actions/starter-workflows&lt;/a&gt;
を参考に書き換えます。重要なのは2点で、&lt;code&gt;actions/upload-pages-artifact&lt;/code&gt;を使って生成済みページをartifactとしてアップロードする点と、&lt;code&gt;actions/deploy-pages&lt;/code&gt;を使ってGitHub Pagesにデプロイをすることです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Upload artifact&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/upload-pages-artifact@v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./public&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Grant GITHUB_TOKEN the permissions required to make a Pages deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;write &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# to deploy to Pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id-token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;write &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# to verify the deployment originates from an appropriate source&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;github-pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ steps.deployment.outputs.page_url }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deploy to GitHub Pages&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/deploy-pages@v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;多分artifactのアップロードとページのデプロイは同じJob内で実施しても問題無く動くとは思いますが、&lt;a href="https://github.com/actions/deploy-pages" target="_blank" rel="noopener"&gt;actions/deploy-pagesのREADME&lt;/a&gt;
によると専用のJobに分けることが推奨されているようです。&lt;/p&gt;</description></item><item><title>梅仕事2022</title><link>https://blog.web-apps.tech/ume-2022/</link><pubDate>Sun, 05 Jun 2022 19:45:00 +0900</pubDate><guid>https://blog.web-apps.tech/ume-2022/</guid><description>&lt;p&gt;皆さん、6月です。6月と言えば、そう、梅の季節ですね。今年も近所の西友で梅やらでかい瓶やらが店頭に並んでいたので買ってきました。このブログでは2020年からしか記録をつけていないのですが、成人してから毎年梅酒と梅シロップを漬けており、梅酒はほぼ手を付けていないので4L瓶が実家にも現在の家にも並んでいます。そろそろ一升瓶を入手して瓶詰めでもしようか、などと考えています。&lt;/p&gt;
&lt;p&gt;扨、もちろん今年も梅酒/梅シロップを漬けましたので記録しておきます。今年のレシピはこちらです:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1795_hu_c938c19e10c990ae.png" alt="梅酒の材料" /&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;梅: 近所の西友で購入した青梅一袋。多分1kgくらい(で売ってるのが普通のはず？)&lt;/li&gt;
&lt;li&gt;砂糖: 西表島産黒糖1kg&lt;/li&gt;
&lt;li&gt;酒: ホワイトタカラ 果実酒の季節 1.8L&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;昨年はかねてからやってみたかった、梅酒用の日本酒を手に入れて日本酒梅酒を漬ける、ということをやりましたので、今年は砂糖の方で変化を入れてみました。酒はこの季節どこにでも売っている果実酒用ホワイトリカーの定番、果実酒の季節です。度数は35%です。適当な焼酎で漬けても良いんですが、黒糖を使うこともあり度数が高めのモノを使った方が良いだろうと考え果実酒の季節を選びました。&lt;/p&gt;
&lt;p&gt;梅を洗って、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1796_hu_7c597202a2a32062.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;水分を拭き取りながらへたを取り、砂糖と交互に積み、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1802_hu_7f91249847e48b62.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;酒を注ぎます&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1804_hu_7f615b73b5c28365.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;余談ですがこの黒糖、カレールゥにしか見えないのは私だけでしょうか&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1803_hu_a42072467f5cbb4d.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;巷にあふれるレシピを見ると、へたのところに水分が残りやすいので注意とか、傷があったらそこから腐るので除けた方が良いとか書いてありますが、多少へたのところに水分が残ってたり傷があっても多分大丈夫です。大きな傷があるモノとか、傷のところが柔らかくなっているモノは除けておきましょう。今回は一袋の内1つだけ傷のところがすこし柔らかかったため除けました。&lt;/p&gt;
&lt;p&gt;梅は金気を嫌う、という話が有るので私はへた取りは爪楊枝でやっています。ボウルもプラかなんかの奴で、金属製じゃない奴です。まぁ金属のボウルに入れたところでどれだけ影響があるのか分からないですが。&lt;/p&gt;
&lt;p&gt;黒糖特有だと思うんですが、アクのようなモノが浮いてきました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1805_hu_d7d080a25d54bdd9.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;最後に、瓶に付属していたラベルに年月日とレシピを記録して貼り付けておきます&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1806_hu_94bd6c36db76e641.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;あとはしばらく数日ごとに瓶を揺すって、砂糖が溶けたら放置して3ヶ月くらい経ったら飲むことができます。1年くらい置くとなお良いでしょう。私は永遠に放置します。&lt;/p&gt;
&lt;p&gt;続いて梅シロップを漬けます。レシピはこちら:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1807_hu_276f1203bc1ff7c3.png" alt="梅シロップの材料" /&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;梅: 近所の西友で購入した青梅一袋。多分1kgだろうという想定。&lt;/li&gt;
&lt;li&gt;砂糖: カップ印の三温糖1kg&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;こちらも氷砂糖のレシピが一般的だと思いますが、今年は三温糖にしてみました。店頭で今年は三温糖にしようかな、と思って買ってきたのですが、&lt;a href="https://blog.web-apps.tech/ume-2021-1/"&gt;昨年も三温糖を使ったよう&lt;/a&gt;
です。まぁ良いでしょう。&lt;/p&gt;
&lt;p&gt;酢を入れるレシピもありますが、今年は酢を入れないでやってみることにしました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2022/images/IMG_1808_hu_6db4bb8cf27c6efc.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>N-ONEを買いました</title><link>https://blog.web-apps.tech/bought-n-one/</link><pubDate>Sat, 28 May 2022 23:57:21 +0900</pubDate><guid>https://blog.web-apps.tech/bought-n-one/</guid><description>&lt;p&gt;標題のとおりです。N-ONEを買いました。現行の新型N-ONEではなく、前期型のN-ONEです。グレードはツアラーで、ターボ、パドルシフト、クルーズコントロールなどがついています。納車時走行距離は46,710kmでした。&lt;/p&gt;
&lt;p&gt;5月21日(土)に納車、今日車祓をしてもらってきました。&lt;/p&gt;
&lt;p&gt;以上。&lt;/p&gt;</description></item><item><title>Kustomizeのimages transformerをCustomResourceでも使う</title><link>https://blog.web-apps.tech/kustomize-images-for-crds/</link><pubDate>Wed, 25 May 2022 18:19:05 +0900</pubDate><guid>https://blog.web-apps.tech/kustomize-images-for-crds/</guid><description>&lt;p&gt;皆さんはKustomizeのimages transformerは使っていますか？kustomization.yamlに書く、こういうやつです:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;kustomize.config.k8s.io/v1beta1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Kustomization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;deployment.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;old-image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;newName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;new-image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;newTag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1.0.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;kustomization.yamlにこの&lt;code&gt;images:&lt;/code&gt;というブロックを書くと、deployment.yamlで&lt;code&gt;image: old-image&lt;/code&gt;と書かれている部分が&lt;code&gt;image: new-image:v1.0.0&lt;/code&gt;に置き換えられます。これがimages transformerと呼ばれるもので、kustomizeのドキュメントでは&lt;a href="https://kubectl.docs.kubernetes.io/references/kustomize/builtins/#_imagetagtransformer_" target="_blank" rel="noopener"&gt;ImageTagTransformer&lt;/a&gt;
のところとか、&lt;a href="https://github.com/kubernetes-sigs/kustomize/blob/master/examples/transformerconfigs/README.md#images-transformer" target="_blank" rel="noopener"&gt;exampleのimages transformer&lt;/a&gt;
のところとかに説明が書いてあります。&lt;/p&gt;
&lt;p&gt;扨、Kubernetesの大きな強みの一つとして、CustomResourceDefinitionを使用して独自のリソースを作成することができる、というものがあります。世の中にはいろいろなOSS CRDがありますが、今回話題にしたいのはDeploymentなどのようにコンテナイメージを指定するタイプのCustomResourceです。例えば、Argo WorkflowsのWorkflowリソースでは次の様にイメージを指定します:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;argoproj.io/v1alpha1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Workflow&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;batchjob&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;entrypoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;templates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;old-image&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;しかしこの場合、kustomization.yamlでイメージを指定しても、&lt;code&gt;old-image&lt;/code&gt;を置き換えてくれません。&lt;/p&gt;</description></item><item><title>BlogカードShortcodeを実装した</title><link>https://blog.web-apps.tech/hugo-embed-web-shortcode/</link><pubDate>Fri, 29 Apr 2022 15:26:59 +0900</pubDate><guid>https://blog.web-apps.tech/hugo-embed-web-shortcode/</guid><description>&lt;p&gt;例えば、はてなブログだとブログカードと呼ばれるこういうの:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hugo-embed-web-shortcode/images/hatena-web-card_hu_ba2264e3e4b7624.png" alt="はてなブログのブログカード" /&gt;
&lt;/p&gt;
&lt;p&gt;が有ったり、wordpressだとプラグインでこういうの:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hugo-embed-web-shortcode/images/wordpress-linkcard_hu_c6c698f9317d3c89.png" alt="Wordpressのlinkcard" /&gt;
&lt;/p&gt;
&lt;p&gt;が有り、リンクをなんだか良い感じに表示してくれます。このブログでつい先日まで使っていたGhostでも、こういうの:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hugo-embed-web-shortcode/images/ghost-bookmark-card_hu_2cb7dcd7d010afa2.png" alt="Ghostのbookmark card" /&gt;
&lt;/p&gt;
&lt;p&gt;が有りました。&lt;/p&gt;
&lt;p&gt;一方、現在使っているHugoには標準機能でこういったものを表示する機能はありません(twitterとかYoutubeはあるんですけど・・・)。しかし、無ければ作れば良いじゃない、ができるのがHugoの良いところです。&lt;/p&gt;
&lt;p&gt;Hugoには&lt;a href="https://gohugo.io/content-management/shortcodes/" target="_blank" rel="noopener"&gt;shortcode&lt;/a&gt;
という機能があり、例えば標準のtwitter shortcodeだと、&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{{&amp;lt; tweet user=&amp;#34;nasa9084&amp;#34; id=&amp;#34;1519598305554362370&amp;#34; &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;と書くと&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;牛乳はさ、牛乳-like飲物よりうまいんだよな&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/1519598305554362370?ref_src=twsrc%5Etfw"&gt;April 28, 2022&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;の様に展開されます。なので今回は&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;{{&amp;lt; web-embed url=&amp;#34;https://example.com&amp;#34; &amp;gt;}}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;というshortcodeを作ってみようと思います。調べてみると同様の実装をしている人もいましたので、それを参考にしつつ実装していきます。&lt;/p&gt;
&lt;p&gt;まず、URLからデータを取得してくるにはHugoの&lt;a href="https://gohugo.io/templates/data-templates/#get-remote-data" target="_blank" rel="noopener"&gt;getJSON&lt;/a&gt;
を使うと良さそうです。残念ながらOGP情報などを取得する方法は用意されていないようなので、指定したURLからOGP情報をとってきてJSONとして返す様なプロキシ的なサーバが必要そうです。&lt;a href="https://seita.icu/post/hugo-shortcode-web-embed/" target="_blank" rel="noopener"&gt;cloud functions for firebase + javascript&lt;/a&gt;
で実装している人もいれば、&lt;a href="https://wada.page/post/0003-hugo-blogcard/" target="_blank" rel="noopener"&gt;Netlify Functions + javascript&lt;/a&gt;
でやっている人もいるという感じでしたが、やはり個人的にはGoがシュッと読み書きできて早いし、Cloud Functionsなどで常時稼働させておくには認証とかのことも考える必要がありありそう(まぁ無くてもいいっちゃいいけど、よくわからん踏み台にされても面白くない)で面倒だな、ということでちょっと困ったんですが、OGPプロキシサーバは特に状態を持っておらず、&lt;code&gt;hugo build&lt;/code&gt;する間だけ存在してくれればいいので、GitHub Actionsのサービスコンテナとしてプロキシを動かすことにしました。ローカルでテストビルドするときも&lt;code&gt;docker run&lt;/code&gt;すれば良いだけなので簡単です。&lt;/p&gt;
&lt;p&gt;ハンドラの実装は次の通りです:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`{&amp;#34;message&amp;#34;: &amp;#34;url parameter is required&amp;#34;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;request URL: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ogp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opengraph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{&amp;#34;message&amp;#34;: &amp;#34;error fetching OGP&amp;#34;, &amp;#34;error&amp;#34;: &amp;#34;%s&amp;#34;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ogp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToAbs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{&amp;#34;message&amp;#34;: &amp;#34;error converting relative URLs to absolute URLs&amp;#34;, &amp;#34;error&amp;#34;: &amp;#34;%s&amp;#34;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ogp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{&amp;#34;message&amp;#34;: &amp;#34;error encoding OGP info to JSON&amp;#34;, &amp;#34;error&amp;#34;: &amp;#34;%s&amp;#34;}`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;コード全体は&lt;a href="https://github.com/nasa9084/blog.web-apps.tech/blob/0eea2254f7650b5a682e568fdc55fbbb9679d913/getogp/main.go" target="_blank" rel="noopener"&gt;ここ&lt;/a&gt;
にあります。リポジトリを作ったときにhugo用のディレクトリをルートディレクトリではなく一段掘ったサブディレクトリにしておいたおかげで気軽にディレクトリを追加できたので良かったですね。&lt;/p&gt;</description></item><item><title>Migrate Ghost to Hugo</title><link>https://blog.web-apps.tech/migrate-ghost-to-hugo/</link><pubDate>Sat, 23 Apr 2022 02:52:34 +0900</pubDate><guid>https://blog.web-apps.tech/migrate-ghost-to-hugo/</guid><description>&lt;p&gt;いつの頃からだったか、もう記憶もあやふやではあるけれど、ブログプラットフォームとして&lt;a href="https://github.com/TryGhost/Ghost" target="_blank" rel="noopener"&gt;Ghost&lt;/a&gt;
を使っていた。&lt;a href="https://twitter.com/nasa9084/status/928539254304645121" target="_blank" rel="noopener"&gt;twitter&lt;/a&gt;
を見る限り、2017年の11月頃には既にGhostを使っていて、確かこの時はDockerでセットアップしていた様な記憶がある。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;Ghost、すごい勢いでアップデートされてってて結構アプデが手間&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1f) (@nasa9084) &lt;a href="https://x.com/nasa9084/status/928539254304645121?ref_src=twsrc%5Etfw"&gt;November 9, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.x.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;Ghostは結構更新が頻繁で、特にdocker-composeとかも使わずに運用していたので(使っても良かったんだけど、当時はDBもsqliteを使っていてコンテナ一つと永続ボリューム一つ、という単純な構成だったので使わなくて良いか、と思っていた)微妙にイメージの更新が面倒で、&lt;a href="https://blog.web-apps.tech/container-up/"&gt;container-up&lt;/a&gt;
というツールを書いてみたりもした。&lt;/p&gt;
&lt;p&gt;その後自宅にKubernetesクラスタをセットアップしてKubernetes管理になり、データベースもMySQLに切り替え、最終的にはGCPのfree tierを使ってon VMで運用していた。
Ghostを使い始めた頃はバージョンもまだ1系だったけど、今となっては4系になって、相も変わらず活発に開発され、admin UIも大分変化した。&lt;/p&gt;
&lt;p&gt;時代の流れとしては当然といえば当然なのだけれど、Ghost 5.0ではMySQL 8が必須となるということで、最近MySQLの更新をしたところ、頻繁に外形監視がfailする様になった。どうやらリソース不足でレスポンスを返せなくなっていたようだった。free tierのVMなのでe2-microインスタンスを使っているため、さもありなんといった感じ。&lt;/p&gt;
&lt;p&gt;もちろん多少のお金を払ってもう少し良いVMにしても良いのだけれど、それほど頻繁に書いているわけでもないブログを運用するためだけに月数千円の出費はいかがなものか、大して書いてもいないのだから静的ページ生成でも良いのではないか、静的ページ生成ならデータベースもいらないしGitHub pagesで配信できて無料ではないか、などと思い、&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;k8s.io&lt;/a&gt;
でも使っている&lt;a href="https://gohugo.io" target="_blank" rel="noopener"&gt;Hugo&lt;/a&gt;
に乗り換えることにした。&lt;/p&gt;
&lt;p&gt;参考にしたのは&lt;a href="https://dwmkerr.com/migrating-from-ghost-to-hugo/#the-migration-process" target="_blank" rel="noopener"&gt;このページ&lt;/a&gt;
。多少古い記事だけど多少調整すればなんとかなるだろう、と思い見切り発車した。結果なんとか移行はうまくいき、このページが表示されています。&lt;/p&gt;
&lt;h2 id="移行手順"&gt;移行手順&lt;/h2&gt;
&lt;p&gt;まず、&lt;a href="https://github.com/jbarone/ghostToHugo/" target="_blank" rel="noopener"&gt;ghostToHugo&lt;/a&gt;
をダウンロードして、Ghostから出力したjsonファイルをHugoにインポート。(ghostToHugoはDarwin_x86_64のバイナリを使ったけど、apple siliconのmacOSでもrosettaで普通に問題無く動いた)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ./ghostToHugo -p blog.web-apps.tech something-tech.ghost.2022-04-22-02-57-56.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Google Cloud Storageにアップロードしていたバックアップから画像ファイルを取り出してimagesディレクトリに配置した。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cp &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PATH_TO_BACKUP&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/content/images ./blog.web-apps.tech/images
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;イメージのパスをちょっと調整。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ find . -name &lt;span class="s1"&gt;&amp;#39;*.md&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs sed -ie &lt;span class="s1"&gt;&amp;#39;s/__GHOST_URL__//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ find . -name &lt;span class="s1"&gt;&amp;#39;*.md&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs sed -ie &lt;span class="s1"&gt;&amp;#39;s/\/content\/images\//\/images\//g&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;front-matterをYAMLに変更。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; blog.web-apps.tech
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ hugo convert toYAML
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; ../
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;そのままではすべての記事が年のディレクトリ以下にまとまって入っていて画像管理が大変そうなので次のスクリプトで構成変更。&lt;/p&gt;</description></item><item><title>GitHubがgit://を無効にした件</title><link>https://blog.web-apps.tech/github-disabled-git-protocol/</link><pubDate>Sun, 20 Mar 2022 14:14:15 +0000</pubDate><guid>https://blog.web-apps.tech/github-disabled-git-protocol/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;GitHubからgitプロトコル(&lt;code&gt;git://github.com&lt;/code&gt;で始まるURL)でgit cloneする設定になっている人が居たらSSHプロトコル(&lt;code&gt;git@github.com&lt;/code&gt;で始まるURL)を使うように設定変更しましょう&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;wez/weztermという端末エミュレータを知って、使ってみようかと思い、ドキュメントに従って&lt;code&gt;brew tap&lt;/code&gt;したときのことでした。次の様なエラーが発生して、tapできません。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ brew tap wez/wezterm
==&amp;gt; Tapping wez/wezterm
Cloning into &amp;#39;/opt/homebrew/Library/Taps/wez/homebrew-wezterm&amp;#39;...
fatal: remote error:
The unauthenticated git protocol on port 9418 is no longer supported.
Please see https://github.blog/2021-09-01-improving-git-protocol-security-github/ for more information.
Error: Failure while executing; `git clone https://github.com/wez/homebrew-wezterm /opt/homebrew/Library/Taps/wez/homebrew-wezterm --origin=origin --template=` exited with 128.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;a href="https://github.blog/2021-09-01-improving-git-protocol-security-github/" target="_blank" rel="noopener"&gt;指定された記事&lt;/a&gt;
を見てみると、&lt;code&gt;git://&lt;/code&gt;で始まるURLでのアクセス==gitプロトコルでのアクセスを無効化したようです。
&lt;a href="https://github.com/nasa9084/dotfiles/blob/2aa844041a6ec45ae08d73ba850ecedb68e0eb89/.gitconfig" target="_blank" rel="noopener"&gt;自分の&lt;code&gt;.gitconfig&lt;/code&gt;を見てみると&lt;/a&gt;
、確かに &lt;a href="https://github.com" target="_blank" rel="noopener"&gt;https://github.com&lt;/a&gt;
の代わりに git://github.com を使うという設定がされています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[url &amp;#34;git@github.com:&amp;#34;]
pushInsteadOf = git://github.com/
pushInsteadOf = https://github.com/
[url &amp;#34;git://github.com/&amp;#34;]
insteadOf = https://github.com/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;GitHubによるとこれまでもgitプロトコルでのアクセスは読み取り専用だったようですが、ご丁寧にpushInsteadOfで &lt;a href="mailto:git@github.com"&gt;git@github.com&lt;/a&gt;
を使用するという設定まで書かれているので、これまで問題無く使えてしまっていたようです。自分でもなぜこういう設定にしたのか記憶にないのですが、これは単にSSHプロトコルを使用すれば良いだけ、ということのようでしたので&lt;a href="https://github.com/nasa9084/dotfiles/blob/a55ab8c0d44bbda1d9fff398ac3e3a69a79be274/.gitconfig" target="_blank" rel="noopener"&gt;修正しました&lt;/a&gt;
。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[url &amp;#34;git@github.com:&amp;#34;]
insteadOf = https://github.com/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;GitHubの想定としてもどうせread-onlyだから使っている人なんてほとんどいないだろう、ということで引っかかる人も居ないでしょうが、メモとして残しておきます。&lt;/p&gt;</description></item><item><title>Retrospective: 2021</title><link>https://blog.web-apps.tech/retrospective-2021/</link><pubDate>Thu, 30 Dec 2021 02:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/retrospective-2021/</guid><description>&lt;h3 id="1月"&gt;1月&lt;/h3&gt;
&lt;p&gt;動画編集がちょっと楽しくなってきた頃で、毎日AmongUsの動画を作って上げてた。AmongUsやるDiscord鯖を作ったのもこのあたり。DaVinci Resolveでモーショングラフィックスやり始めてみてめっちゃ楽しかった。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;案外それっぽいモーショングラフィックスとか作れるもんだなーと思うなど &lt;a href="https://t.co/mhuQFVErv4"&gt;https://t.co/mhuQFVErv4&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1b) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1353003355040227330?ref_src=twsrc%5Etfw"&gt;January 23, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;この時期に買ったコミックスで&lt;a href="https://amzn.to/3FDx7SJ" target="_blank" rel="noopener"&gt;まどろみバーメイド&lt;/a&gt;
が面白いです。kindle unlimited加入者は5巻まで読めるので読んでください。特にお酒が好きな人。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nasa9084/broadcast-memo" target="_blank" rel="noopener"&gt;nasa9084/broadcast-memo&lt;/a&gt;
リポジトリを作った。&lt;/p&gt;
&lt;h3 id="2月"&gt;2月&lt;/h3&gt;
&lt;p&gt;Switchbot APIを発見したので&lt;a href="https://github.com/nasa9084/go-switchbot" target="_blank" rel="noopener"&gt;nasa9084/go-switchbot&lt;/a&gt;
を作った。相変わらず動画は毎日アップしてた。&lt;/p&gt;
&lt;p&gt;それ以外はまぁ特になし&lt;/p&gt;
&lt;h3 id="3月"&gt;3月&lt;/h3&gt;
&lt;p&gt;オフィス移転して、新宿から四谷になった。まぁ、目下リモートワークであんまり影響はなし。&lt;/p&gt;
&lt;p&gt;異動乃至転職をしよう、と割と真剣に考え始めた。チーム内で真面目にやろうとしてる人を見て面倒だなって感じてしまったので、チームから心が離れてるな、と強く自覚したのが理由。&lt;/p&gt;
&lt;p&gt;ergodash2台目(bluetooth化)を作った。今も使ってます。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nasa9084/switchbot-exporter" target="_blank" rel="noopener"&gt;nasa9084/switchbot-exporter&lt;/a&gt;
を書いたけど、あんまり見てない。&lt;/p&gt;
&lt;p&gt;この辺で動画投稿ペースは落ちてきた。&lt;/p&gt;
&lt;h3 id="4月"&gt;4月&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://amzn.to/3FDR643" target="_blank" rel="noopener"&gt;笑顔のたえない職場です&lt;/a&gt;
というコミックスが面白いです。&lt;/p&gt;
&lt;p&gt;スピーカーを買い、モニタを増設し、大体今のデスク環境が整ったのがこの辺。&lt;/p&gt;
&lt;h3 id="5月"&gt;5月&lt;/h3&gt;
&lt;p&gt;バイオリンを買った。結局練習は続いていません。Ankerの新製品であるところのwebカメラを買って、最近のwebカメラってこんなに画質いいんだ！と驚いたり。&lt;/p&gt;
&lt;p&gt;社でやったゴールデンウィーク自由研究発表会で良かった発表ランキング1位を獲得した。なお内容は各社の牛乳でヨーグルトを作って比較してみたという内容でした。&lt;/p&gt;
&lt;p&gt;LINE MOBILEからLINEMOに乗り換えた。メイン回線は変わらずiij mio。&lt;/p&gt;
&lt;h3 id="6月"&gt;6月&lt;/h3&gt;
&lt;p&gt;UNDERTALEめっちゃ面白かった。&lt;/p&gt;
&lt;h3 id="7月"&gt;7月&lt;/h3&gt;
&lt;p&gt;1回目の新型コロナウイルスワクチンを接種した。&lt;/p&gt;
&lt;h3 id="8月"&gt;8月&lt;/h3&gt;
&lt;p&gt;2回目の新型コロナウイルスワクチンを接種した。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://amzn.to/3JtM4sY" target="_blank" rel="noopener"&gt;異世界失格&lt;/a&gt;
が面白いです。&lt;/p&gt;
&lt;p&gt;Huawei Band 6を買って、割と満足はしてた。が、今はapple watchに乗り換えてしまったので使ってない。南無。プール行ったときだけ使ってます。&lt;/p&gt;
&lt;p&gt;なんだかんだ真面目に仕事をしてました。&lt;/p&gt;
&lt;h3 id="9月"&gt;9月&lt;/h3&gt;
&lt;p&gt;iPhone 13 miniとiPad miniを買いました。iPhoneは9年ぶりです。&lt;/p&gt;
&lt;h3 id="10月"&gt;10月&lt;/h3&gt;
&lt;p&gt;Engineering Infrastructure室からLINE Platform Developmentセンター1 Communication and Service Integration室のSREチームに異動しました。使ってる技術も、業務知識もガラッと変わったので何も分からなくなりました。今も何も分からん。&lt;/p&gt;
&lt;p&gt;社内のエンジニアレベルも上がり、昇給し、異動前にやってた業務がきちんと評価してもらえた事がわかりめでたしめでたし。&lt;/p&gt;
&lt;p&gt;あとはapple watch買いました。&lt;/p&gt;
&lt;h3 id="11月"&gt;11月&lt;/h3&gt;
&lt;p&gt;LINEスタンプを作り始めた。iPad Proはこのために買った(が1年放置してた)。皆さんスタンプ買って下さい。&lt;/p&gt;
&lt;figure class="kg-card kg-bookmark-card"&gt;
&lt;a href="https://store.line.me/stickershop/product/17346907/ja" class="kg-bookmark-container"&gt;
&lt;div class="kg-bookmark-content"&gt;
&lt;div class="kg-bookmark-title"&gt;かんたんないきもの - LINE スタンプ | LINE STORE&lt;/div&gt;
&lt;div class="kg-bookmark-description"&gt;たまに使えるかも知れない、ゆるふわかんたんな形の生き物(?)です&lt;/div&gt;
&lt;div class="kg-bookmark-metadata"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="kg-bookmark-thumbnail"&gt;
&lt;img src="https://stickershop.line-scdn.net/stickershop/v1/product/17346907/LINEStorePC/main.png;compress=true"&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/figure&gt;
&lt;figure class="kg-card kg-bookmark-card"&gt;
&lt;a href="https://store.line.me/stickershop/product/17379076/ja" class="kg-bookmark-container"&gt;
&lt;div class="kg-bookmark-content"&gt;
&lt;div class="kg-bookmark-title"&gt;まぁまぁ使えそう - LINE スタンプ | LINE STORE&lt;/div&gt;
&lt;div class="kg-bookmark-description"&gt;たぶん、まぁまぁ使えそうなスタンプです&lt;/div&gt;
&lt;div class="kg-bookmark-metadata"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="kg-bookmark-thumbnail"&gt;
&lt;img src="https://stickershop.line-scdn.net/stickershop/v1/product/17379076/LINEStorePC/main.png;compress=true"&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/figure&gt;
&lt;figure class="kg-card kg-bookmark-card"&gt;
&lt;a href="https://store.line.me/stickershop/product/17389950/ja" class="kg-bookmark-container"&gt;
&lt;div class="kg-bookmark-content"&gt;
&lt;div class="kg-bookmark-title"&gt;とにかく帰りたい - LINE スタンプ | LINE STORE&lt;/div&gt;
&lt;div class="kg-bookmark-description"&gt;とにかく帰りたい人の為のスタンプ&lt;/div&gt;
&lt;div class="kg-bookmark-metadata"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="kg-bookmark-thumbnail"&gt;
&lt;img src="https://stickershop.line-scdn.net/stickershop/v1/product/17389950/LINEStorePC/main.png;compress=true"&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/figure&gt;
&lt;figure class="kg-card kg-bookmark-card"&gt;
&lt;a href="https://store.line.me/stickershop/product/17488075/ja" class="kg-bookmark-container"&gt;
&lt;div class="kg-bookmark-content"&gt;
&lt;div class="kg-bookmark-title"&gt;うちでよく使いそうなスタンプ - LINE スタンプ | LINE STORE&lt;/div&gt;
&lt;div class="kg-bookmark-description"&gt;我が家では割とよく使われそうな雰囲気のスタンプ&lt;/div&gt;
&lt;div class="kg-bookmark-metadata"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="kg-bookmark-thumbnail"&gt;
&lt;img src="https://stickershop.line-scdn.net/stickershop/v1/product/17488075/LINEStorePC/main.png;compress=true"&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/figure&gt;
&lt;figure class="kg-card kg-bookmark-card"&gt;
&lt;a href="https://store.line.me/stickershop/product/17549941/ja" class="kg-bookmark-container"&gt;
&lt;div class="kg-bookmark-content"&gt;
&lt;div class="kg-bookmark-title"&gt;丸い目をした奴ら - LINE スタンプ | LINE STORE&lt;/div&gt;
&lt;div class="kg-bookmark-description"&gt;奴らは丸い目をしている&lt;/div&gt;
&lt;div class="kg-bookmark-metadata"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="kg-bookmark-thumbnail"&gt;
&lt;img src="https://stickershop.line-scdn.net/stickershop/v1/product/17549941/LINEStorePC/main.png;compress=true"&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;/figure&gt;
&lt;p&gt;初めてエアコンの清掃業者を頼んだりした。正直思ってたよりきれいになってかび臭さも一切なくなったので、清掃頼んだことない人はやった方が良い。&lt;/p&gt;</description></item><item><title>ansible.builtin.fileのmodeパラメータは頭に0が必要</title><link>https://blog.web-apps.tech/ansible-builtin-file-mode-leading-zero/</link><pubDate>Mon, 13 Dec 2021 10:45:28 +0000</pubDate><guid>https://blog.web-apps.tech/ansible-builtin-file-mode-leading-zero/</guid><description>&lt;p&gt;多分ほとんどのケースでは気にすることもなく&lt;code&gt;0755&lt;/code&gt;とか&lt;code&gt;0644&lt;/code&gt;とか書くと思うんですが、特殊な属性を付ける必要があるときに困るよ、という話。&lt;/p&gt;
&lt;p&gt;世の中にはSUIDとかSGIDとかスティッキービットとかいう、特殊な属性がありまして、例えば基本のファイルパーミッションが&lt;code&gt;0755&lt;/code&gt;でSUIDを指定したいという場合は&lt;code&gt;chmod&lt;/code&gt;で言うと&lt;code&gt;chmod 4755 path/to/file&lt;/code&gt;といった感じになるんですけれども、&lt;code&gt;ansible.builtin.file&lt;/code&gt;のmodeパラメータでは以下の様に書くとパーサが10進数として解釈して訳の分からんことになってしまいます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ansible.builtin.file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;path/to/file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4755&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;これはこう書く必要があります:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ansible.builtin.file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;path/to/file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;04755&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;もしくはこう:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;ansible.builtin.file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;path/to/file&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;4755&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;これは例えば、結構古いAnsible playbookなんかで、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;path=path/to/file mode=4755&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;とか書いていたやつを書き直したりしたときに注意が必要です。&lt;/p&gt;
&lt;p&gt;まぁ、&lt;a href="https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html#parameter-mode" target="_blank" rel="noopener"&gt;公式ドキュメントに書いてある&lt;/a&gt;
んですけど、そうは言ってもみんなそんなに細かいところまで読んでないでしょ、という。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You must either add a leading zero so that Ansible&amp;rsquo;s YAML parser knows it is an octal number (like 0644 or 01777) or quote it (like &amp;lsquo;644&amp;rsquo; or &amp;lsquo;1777&amp;rsquo;) so Ansible receives a string and can do its own conversion from string into number.&lt;/p&gt;</description></item><item><title>人生初Apple Watch (series 7)</title><link>https://blog.web-apps.tech/my-first-apple-watch-series-7/</link><pubDate>Tue, 19 Oct 2021 23:49:46 +0000</pubDate><guid>https://blog.web-apps.tech/my-first-apple-watch-series-7/</guid><description>&lt;p&gt;これまで私は基本的にAndroid端末を使うことが多く、初めて持ったスマートフォンであるGalaxy Sを始め、ほとんどのスマホ人生をAndroid端末とともに歩んできました。これまで最初で最後のiPhone端末はiPhone 5のみで、&lt;a href="https://blog.web-apps.tech/iphone13mini/"&gt;今回iPhone 13 miniを購入した&lt;/a&gt;
のは8年ぶりの事です。
Androidユーザであったために買えなかったAppleデバイス、それがApple Watchです。Androidデバイスでも使えるスマートウォッチはもちろんあります。私も&lt;a href="https://blog.web-apps.tech/fitbit-versa/"&gt;fitbit Versa&lt;/a&gt;
を使っていました。しかし、Apple Watchには遠く及びません。iDでの決裁もできない(現行のfitbit Versa 3/Senseはsuicaには対応している)し、何よりソロループがありません。
一日の大半をPCに向かってキーボードをカチャカチャするという虚業に従事していますから、時計のバックルというのは結構いづい(注：大半の人に伝わらない表現なのは理解しているけど他の表現がない)のです。&lt;/p&gt;
&lt;p&gt;そんな私もiPhoneを買ったことによりApple Watchが買える！という事でApple Watch series 7を購入しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/my-first-apple-watch-series-7/images/IMG_1391_hu_fbebcc506c9fd7ce.jpg" alt="" /&gt;
&lt;/p&gt;</description></item><item><title>iPad mini 6を買って1週間半経った</title><link>https://blog.web-apps.tech/ipad-mini-6/</link><pubDate>Tue, 19 Oct 2021 23:29:54 +0000</pubDate><guid>https://blog.web-apps.tech/ipad-mini-6/</guid><description>&lt;p&gt;みんなが待ってたiPad。そうiPad miniです。私は過去に会社のお下がりでもらったiPad mini第2世代を使っていたことがありますが、その後iPad Pro 第一世代(2018)に買い換え、今に至ります。Youtubeや読書に使用するにはちょっと大きいな、と思いつつ、なんだかんだ便利に使ったり使わなかったりしていました。iPad miniは良いサイズだったな、なんて思いながら。
とはいえ、iPad Proのベゼルレスデザインを体感すると、(ちょっとダサい)従来のiPad miniに戻る気にはなれず、ベゼルレスデザインのiPad miniがでたら買おうと思っていました。&lt;/p&gt;
&lt;p&gt;そして今年、第六世代iPad miniとしてベゼルレスデザインのモノが発売されたので購入しました。なんだかんだ安くはないので、一晩悩んだ結果発売日に入手することはできず、10月9日到着でした。&lt;/p&gt;
&lt;p&gt;今回購入したのはスペースグレイのiPad mini 第六世代 Wi-Fi + Cellularモデル、ストレージは256GBです。iPad Proも256GBのモノを使用していて、ストレージが大きく余っているので正直256GBは多すぎると思ったのですが、64GBか256GBという二つの選択肢を考えたとき、64GBは流石に小さすぎるだろう、と考え256GBを選択しました。MacBook Proですら256でストレージが余っている(最近ゲーム実況動画編集をするようになって、動画の為に外付けSSDを買ったけど)ため、iPad miniのストレージも枯渇することはおそらく無いと思います。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ipad-mini-6/images/IMG_1370_hu_3bb96169a61f6e13.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ipad-mini-6/images/IMG_1371_hu_52d11ead23fe8c1d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ケースは安定の公式Smart Folioを購入。iPad Pro用のモノとは異なり、アップルのロゴがエンボス加工されています。これはこれで良いですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ipad-mini-6/images/IMG_1372_hu_31fda7990773bb48.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ipad-mini-6/images/IMG_1373_hu_e0aa6d22da2ffab.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;iPad Proとサイズを比較するとこんな感じ。ざっくり半分くらいの大きさです。身長176センチ(最近1センチほど伸びました)の私だと片手でホールドできるくらいのサイズ感です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ipad-mini-6/images/IMG_1392_hu_76159ceef2b92054.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;著作権的なアレをアレするためモザイクをかけていますが、マンガを読むのに非常にちょうど良いサイズです。おそらく小説やビジネス書など、他の書籍にも良いでしょう(技術書は大判の事も多いしiPad Proの方が読みやすいかも知れない)&lt;/p&gt;
&lt;p&gt;本機はiPad Airと同じくtouch IDですが、個人的にはiPadはface IDの方が良いかな、という気がしました。家の中で使うことが多い端末ですから、マスクをしている事も無いため、face IDの方がボタンに指を持っていくという動作が不要なため便利です。
また、これは慣れの問題もあるとは思いますが、ボリュームボタンが画面左上部(ランドスケープでは左下)というのは少し操作しづらいように感じました。これはiPad Proとボタンの位置が違うから戸惑っているだけかも知れません。画面の向きによってボタンの方向が変わる(右側、上側が+になる)のは直感的で良いので、iPad Proにもバックポート(?)してほしいものです。&lt;/p&gt;</description></item><item><title>DroneCIでパイプライン全体をfailさせずに後続のジョブを停止する</title><link>https://blog.web-apps.tech/droneci_early_return/</link><pubDate>Mon, 18 Oct 2021 07:38:35 +0000</pubDate><guid>https://blog.web-apps.tech/droneci_early_return/</guid><description>&lt;p&gt;例えばmono repoで特定のディレクトリに変更があったときにだけジョブを実行したい、という様なケース。DroneCIのconditionはディレクトリ単位での変更でステップを実行するかという分岐はできません。かといってfailさせてしまうと、対象のディレクトリに変更がない場合はいつもfailする事になり、実際に問題があってfailしているのかどうなのか分からない、という事態に陥ります。&lt;/p&gt;
&lt;p&gt;そんなときは &lt;code&gt;exit 78&lt;/code&gt; すると良いようです。 &lt;code&gt;exit 78&lt;/code&gt; したステップはsuccess、後続のステップは実行されず、(&lt;code&gt;depends_on&lt;/code&gt; で設定しているような)後続のパイプラインは実行されます。&lt;/p&gt;
&lt;h2 id="reference"&gt;Reference&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://discourse.drone.io/t/how-to-exit-a-pipeline-early-without-failing/3951" target="_blank" rel="noopener"&gt;How to exit a Pipeline early without Failing&lt;/a&gt;
&lt;/p&gt;</description></item><item><title>iPhone 13 miniを買った</title><link>https://blog.web-apps.tech/iphone13mini/</link><pubDate>Sun, 26 Sep 2021 13:19:01 +0000</pubDate><guid>https://blog.web-apps.tech/iphone13mini/</guid><description>&lt;p&gt;新型コロナウイルス感染症ワクチンの副反応(ということにした)で、iPhone 13 miniを購入しました。色はミッドナイトで、128GBのモデルです。
日々のご飯の写真くらいしか写真は撮らないし、大きいスマホは好きになれないのでminiを選択しました。これまで使用していたPixel 4が64GBのモデルだったので、ストレージは倍になったことになります。AppleCare+ 盗難・紛失プラン for iPhone 13 miniもつけて、107,600円でした。
最後にiPhoneを使っていたのはiPhone 5なので、実に8年ぶりくらいのiPhoneです。&lt;/p&gt;
&lt;p&gt;iPad miniも買いましたが、買うかどうか一晩悩んだ結果発売日に届きませんでした。&lt;/p&gt;
&lt;p&gt;以下開封写真です:&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/iphone13mini/images/F88B6496-A4C3-4482-98B5-2559179A38E0_hu_e68192a854c6b529.JPEG" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/iphone13mini/images/EECF6EBA-21BE-4AF4-83BC-92C7B2989211_hu_332c62cfc252103f.JPEG" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/iphone13mini/images/988D0431-8F4B-41DB-A851-40F1AFC8658C_hu_a256704d2548022.JPEG" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/iphone13mini/images/0F84E98A-A244-4AC4-BA92-DA610BD88C14_hu_b275f462908b4591.JPEG" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/iphone13mini/images/EEC0617E-38A1-4FE0-810E-E52687BE1078_hu_58aac4f92f5d2fc.JPEG" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/iphone13mini/images/BFEFDA5A-AB64-4EF8-8EE4-E1B39C41B385_hu_3e466f318754bc49.JPEG" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/iphone13mini/images/IMG_0027_hu_91806a5a9c25c333.jpg" alt="" /&gt;
&lt;/p&gt;</description></item><item><title>bashのhere-documentは一時ファイルを作成するらしい</title><link>https://blog.web-apps.tech/bash-here-document-makes-tmp-file/</link><pubDate>Wed, 08 Sep 2021 09:33:25 +0000</pubDate><guid>https://blog.web-apps.tech/bash-here-document-makes-tmp-file/</guid><description>&lt;p&gt;皆さん使ってますか、here-document。bashでいうとこういう奴:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt;EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;this
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;document
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;出力はこう:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;this
is
here
document
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;複数行に渡るテキストをリテラルとして表現したい場合に便利ですね。で、shellscriptからREST APIにリクエストを投げたくて、here-documentを使ってJSONをべたっとスクリプト内で書いてたんですけど、こんなエラーが出てました(パスはもちろん違いますよ。念のため。):&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;/path/to/shellscript/using/here-document.sh: line 179: cannot create temp file for here-document: No space left on device
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;全然知らなかったけど、here-documentって一時ファイルを作成するんですね。確かめてみます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ docker run -it --rm centos:7 bash
[root@8017e5e28d6e /]# yum install -y strace
(中略)
[root@8017e5e28d6e /]# cat &amp;lt;&amp;lt;EOF &amp;gt; script.sh
&amp;gt; cat &amp;lt;&amp;lt;EOS
&amp;gt; foo
&amp;gt; bar
&amp;gt; baz
&amp;gt; EOS
&amp;gt; EOF
[root@8017e5e28d6e /]# strace -f bash script.sh |&amp;amp; grep tmp
[pid 61] stat(&amp;#34;/tmp&amp;#34;, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid 61] faccessat(AT_FDCWD, &amp;#34;/tmp&amp;#34;, W_OK) = 0
[pid 61] statfs(&amp;#34;/tmp&amp;#34;, {f_type=OVERLAYFS_SUPER_MAGIC, f_bsize=4096, f_blocks=6159700, f_bfree=4601655, f_bavail=4282999, f_files=1572864, f_ffree=1414766, f_fsid={val=[3003212711, 622231591]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_RELATIME}) = 0
[pid 61] open(&amp;#34;/tmp/sh-thd-1631118709&amp;#34;, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600) = 3
[pid 61] open(&amp;#34;/tmp/sh-thd-1631118709&amp;#34;, O_RDONLY) = 4
[pid 61] unlink(&amp;#34;/tmp/sh-thd-1631118709&amp;#34;) = 0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;/tmp/sh-thd-1631118709&lt;/code&gt; に書き込みをしている様子が見て取れます。&lt;/p&gt;</description></item><item><title>Huawei Band 6を買った</title><link>https://blog.web-apps.tech/huawei-band-6/</link><pubDate>Mon, 30 Aug 2021 04:12:05 +0000</pubDate><guid>https://blog.web-apps.tech/huawei-band-6/</guid><description>&lt;p&gt;TL;DR: 割と良い。&lt;/p&gt;
&lt;p&gt;スマートウォッチは長いこと&lt;a href="https://blog.web-apps.tech/fitbit-versa/"&gt;fitbit versa&lt;/a&gt;
を使用していたのですが、最近プールに行くようになり、プール内で使用できるレギュレーションに対応したスマートウォッチ/スマートバンドが欲しいと思っていました。&lt;/p&gt;
&lt;p&gt;私が行っているプールのスマートウォッチ/スマートバンドのレギュレーションは次の様になっています:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ベルト幅が30mm以下でディスプレイがベルト幅および厚みから出ないものは使用可能&lt;/li&gt;
&lt;li&gt;柔らかい素材のカバー等で覆えば使用可能&lt;/li&gt;
&lt;li&gt;シリコン製カバーまたはウォッチスーツで覆えば使用可能&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;fitbit versaは一つ目のレギュレーションにマッチしていないため、柔らかい素材のカバー・シリコン製カバー・ウォッチスーツで覆えば使用可能、ということです。
とはいえ、fitbit versaはもう2世代型落ちのモデルです。ディスプレイを覆うカバーを見つけるのがそもそも難しい(あるにはあるけど)ですし、&lt;a href="https://amzn.to/3mInH1P" target="_blank" rel="noopener"&gt;シリコン製カバーは何故か6個単位でしか売っていない&lt;/a&gt;
ため、私の結論としてはレギュレーションにマッチするスマートバンドを買うのが早い、となりました。&lt;/p&gt;
&lt;p&gt;じゃぁなにを買おうか、と考えたときに、私はPixelユーザですしfitbitのユーザでもありますから、Googleによるfitbitの買収を受けて、fitbitから良い感じの新製品が出るのを待ちたいという気持ちもありますから、あまりコストを掛けるわけにもいかないな、と考え、選択肢は自然とHuaweiかXiaomiの二択となりました。&lt;/p&gt;
&lt;p&gt;いろいろ検討しましたが、最終的には&lt;a href="https://amzn.to/3zv2r34" target="_blank" rel="noopener"&gt;mi band 6&lt;/a&gt;
の丸っこいデザインより、&lt;a href="https://amzn.to/3gIl9gv" target="_blank" rel="noopener"&gt;Huawei Band 6&lt;/a&gt;
の四角いデザインの方が通知などが見やすそうですし、画面もほどよく大きい、という事でHuawei Band 6を選択しました。&lt;/p&gt;
&lt;p&gt;以下開封写真です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/huawei-band-6/images/PXL_20210820_021323994-1_hu_cc414f10b050f0b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/huawei-band-6/images/PXL_20210820_021339110_hu_853f987a6ac9fcf0.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;外箱はこんな感じ。一応amazon.co.jp販売の日本正規代理店品と書かれたモノを購入したのですが、日本語はシールで修正しているような外箱でちょっと不安な感じがあります。まぁ気にしても仕方ないでしょう。安いし。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/huawei-band-6/images/PXL_20210820_021758503_hu_6d589ea32873139a.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱を開けると本体がこんな感じで入っています。まぁわかりやすいはわかりやすいですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/huawei-band-6/images/PXL_20210820_021856235_hu_c0b4499dc60b870c.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱に入っていたものはこれで全部です。本体、充電ケーブル、WARRANTY CARD、クイックスタートガイドですね。クイックスタートガイドは本当に必要最小限の情報だけが書いてあるという感じで、詳細はWebから説明書をダウンロードしてね！という事でQRコードが書いてありました。&lt;/p&gt;
&lt;p&gt;今のところ購入から二週間弱使用しましたが不満点は次の二つです:&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;HUAWEI BAND 6、お値段も含めて割と満足してるけど、保護フィルムにまともなのがなさそう（これはこのクラスのものに気を使いすぎかも）なのと、ツイートをしたときに通知が来ちゃうのが微妙ポイント&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1b) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1431285906405658627?ref_src=twsrc%5Etfw"&gt;August 27, 2021&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;まぁ保護フィルムはこのクラスの製品に保護フィルムをつけようというのが間違っているのかも知れませんが。
ツイートをしたときに通知が来ちゃうのは、「tweetをしました」という通知が一瞬通知欄に出るためそれを認識してしまっている、という事でHuawei Band側の問題と言うよりはtwitterアプリ側の問題の様な気もしますね。&lt;/p&gt;
&lt;p&gt;あとはまぁ、ウォッチフェイスを作ってみた、みたいなブログを書こうと思ってはいたんですが、環境のセットアップがまぁまぁめんどくさそうというか、バンドとスマホの情報同期にはHuawei Healthというアプリをスマホにインストールするんですが、ウォッチフェイスを作ってテストするにはこれのベータ版？開発版？をインストールしなければならないということなのでやめました。諦めて既製のウォッチフェイスを使うことにします。&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>剥がれかけたSesame 3を貼り直す</title><link>https://blog.web-apps.tech/re-sticking-sesame3/</link><pubDate>Thu, 12 Aug 2021 13:20:12 +0000</pubDate><guid>https://blog.web-apps.tech/re-sticking-sesame3/</guid><description>&lt;p&gt;弊宅では&lt;a href="https://jp.candyhouse.co/products/sesame3" target="_blank" rel="noopener"&gt;CANDYHOUSEのSESAME3&lt;/a&gt;
というスマートロック製品を使用していて、付属の両面テープで貼るだけ、剥がすときも跡が残らず便利！という最高の製品なんですが、最近少し剥がれてきてしまいました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/re-sticking-sesame3/images/PXL_20210807_084459967_hu_53ae0577e72b2b8.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;電池切れや故障などの有事に備えて鍵は持って歩いているので問題ないと言えば問題ないのですが、そうは言っても不便な思いはしたくないですし、完全に剥がれてしまってからバタバタするのもイヤなので張り直しをしました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jp.candyhouse.co/products/3m%E3%82%B7%E3%83%BC%E3%83%AB2%E6%9E%9A" target="_blank" rel="noopener"&gt;公式から交換用の両面テープも販売されてはいる&lt;/a&gt;
のですが、明らかに&lt;a href="https://www.command.jp/3M/ja_JP/command-jp/products/~/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89-%E3%82%BF%E3%83%96-%E3%81%AF%E3%82%8A%E3%81%8B%E3%81%88%E7%94%A8-CM2TN-L-20-%E3%83%91%E3%83%83%E3%82%AF-%E7%AE%B1/?N=5924736&amp;#43;3290188981&amp;amp;preselect=8738468&amp;#43;3293786499&amp;amp;rt=rud" target="_blank" rel="noopener"&gt;3Mのコマンドタブ&lt;/a&gt;
ですし、割高っぽい印象を受けたので近所のカインズで購入してきました。(実際比較してみると&lt;a href="https://www.yodobashi.com/product/100000001002982126/" target="_blank" rel="noopener"&gt;ヨドバシ.comでは8枚で300円弱&lt;/a&gt;
なのに対し、CANDYHOUSEから買うと4枚で350円と倍程度の値段設定となっています)&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/re-sticking-sesame3/images/PXL_20210807_083250354_hu_ce7a6139403adca2.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;たまたまカインズに行ったときに思い出して適当に買ってきてしまったため私はMサイズを購入しましたが、元々ついていたモノと比べると多分Lサイズだったので皆さんはLサイズを購入すると良いです。カインズではどのサイズも値段が同じでしたが、ヨドバシ.comではLサイズが若干安いようです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/re-sticking-sesame3/images/PXL_20210807_084753110.MP_hu_c2eacd94d1630f22.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;SESAME本体の形に合わせてコマンドタブをカットし、貼り付けます。剥がすときに引っ張る部分は電池ボックスの中に折り込んでおきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/re-sticking-sesame3/images/PXL_20210808_045849649-1_hu_c48e5d6bd1ad6783.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;無事しっかり貼ることができました。めでたしめでたし。&lt;/p&gt;</description></item><item><title>aタグのping属性</title><link>https://blog.web-apps.tech/atagunopingshu-xing/</link><pubDate>Mon, 02 Aug 2021 14:55:54 +0000</pubDate><guid>https://blog.web-apps.tech/atagunopingshu-xing/</guid><description>&lt;p&gt;私は基本的に業務・趣味の両方でGoを書いていると言うこともあり、ソースコードの管理はGOPATH方式で管理しています。しかしGOPATH方式で管理していると、ライブラリの挙動確認やらなんやらで使う書き捨てのコードをどこに置くか、という問題がある。 &lt;code&gt;src/github.com/nasa9084/...&lt;/code&gt; に置くというのも一つの手ではあるものの、社内のGitリポジトリやらGitHubやらにアップするつもりもないコードを他の、GitHubやらなんやらで管理されているリポジトリと同じ場所に置くと一覧性や検索性が下がるし、やりたくはないので、普段はそういった直ぐにいらなくなるコードは &lt;code&gt;src/practice&lt;/code&gt; というディレクトリに配置しています。&lt;/p&gt;
&lt;p&gt;毎回書き殴った後に削除をする、というまめな性格はしていないので、結果として二度と日の目を見ないことがほとんどなコード片が貯まっていくので定期的にクリーンアップを行っています。書き殴りのコードとはいえ、何かヒントが残っているかもしれないので、削除前にチラチラと内容を確認しながら削除していくのですけれど、そういえばそんなの調べたな、なんて思うコード片がたまに見つかったりする訳です。&lt;/p&gt;
&lt;p&gt;今回発見したのはタイトルにもあるとおり、&lt;code&gt;a&lt;/code&gt;タグの&lt;code&gt;ping&lt;/code&gt;属性です。W3C発行(発行、という表現が正しいのかどうかもよく分かっていないですけど)のHTML仕様が廃止となり、WHATWGのHTML仕様、HTML Living Standardに置き換えられる、との話を6月頃に見て、なるほどなーなんてちょろっと調べて、HTML Living Standardでは&lt;code&gt;a&lt;/code&gt;タグの&lt;code&gt;ping&lt;/code&gt;属性ってのがある、という情報にたどり着き、そして実際どんな挙動なのか、とコードを書いた、という経緯だったと思います。&lt;/p&gt;
&lt;p&gt;実際のコード片がこちら:
index.html:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Document&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; first page
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;second.html&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;ping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://localhost:8080/ping&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;second&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;second.html:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;meta&lt;/span&gt; &lt;span class="na"&gt;charset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;UTF-8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Document&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; second page
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;main.go:&lt;/p&gt;</description></item><item><title>dateコマンドで簡単な時間計算をする</title><link>https://blog.web-apps.tech/calcurate-datetime-in-shell/</link><pubDate>Tue, 13 Jul 2021 03:52:44 +0000</pubDate><guid>https://blog.web-apps.tech/calcurate-datetime-in-shell/</guid><description>&lt;p&gt;shellscript内で時間計算をしたい事がある。例えば、「最終実行から10分経過していたらxxxをする」という様なケース。定期的にファイルを生成したい、といった簡単なユースケースであれば、&lt;code&gt;find&lt;/code&gt;コマンドあたりでファイルの変更タイムスタンプを調べるといった方法でも実現可能ではあるけれど、「ファイルの中に記載された時間から10分経過しているかどうか調べる」なんて事もあるでしょう(あった)。
shellscriptで時間の計算するのって面倒そうなんだよな・・・と思っていたのですけれど、私のユースケースだとそれほど難しくなくて、&lt;code&gt;date&lt;/code&gt;コマンドで大体なんとかなるという事が分かったのでメモしておきます。&lt;/p&gt;
&lt;h2 id="時間を比較する"&gt;時間を比較する&lt;/h2&gt;
&lt;p&gt;二つの時間を比較したい。これは対象の時間がUnix時間で表現されていれば非常に簡単で、&lt;code&gt;date&lt;/code&gt;コマンドを使用する必要すら無く、&lt;code&gt;test&lt;/code&gt;乃至&lt;code&gt;[&lt;/code&gt;で普通に比較ができます。もちろん取り扱いは数字として取り扱うことになるので、比較演算子として&lt;code&gt;-lt&lt;/code&gt;か&lt;code&gt;-gt&lt;/code&gt;を使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1626146220 = 2021-07-13T12:17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 1626146340 = 2021-07-13T12:19&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="m"&gt;1626146220&lt;/span&gt; -lt &lt;span class="m"&gt;1626146340&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hello&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;対象の時間がUnix時間で表現されていない場合、Unix時間に変換して比較するのがおそらく最も簡単です。&lt;code&gt;date&lt;/code&gt;コマンドで一度時間をパースして、Unix時間の形で出力します。パースには&lt;code&gt;-d&lt;/code&gt; / &lt;code&gt;--date&lt;/code&gt;オプションを使用します。Unix時間として出力するためのフォーマット文字は&lt;code&gt;%s&lt;/code&gt;です。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;date -d &lt;span class="s1"&gt;&amp;#39;2021-07-13T12:17&amp;#39;&lt;/span&gt; +%s&lt;span class="k"&gt;)&lt;/span&gt; -lt &lt;span class="k"&gt;$(&lt;/span&gt;date -d &lt;span class="s1"&gt;&amp;#39;2021-07-13T12:19&amp;#39;&lt;/span&gt; +%s&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; hello
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hello&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;-d&lt;/code&gt; / &lt;code&gt;--date&lt;/code&gt; オプションは一般的なフォーマットの日付文字列をよしなにパースしてくれます。詳しいフォーマットは&lt;a href="https://www.gnu.org/software/coreutils/manual/html_node/Date-input-formats.html#Date-input-formats" target="_blank" rel="noopener"&gt;GNU Coreutilsのマニュアル&lt;/a&gt;
などを見ると良いでしょう。&lt;/p&gt;
&lt;h2 id="n分前n分後を求める"&gt;n分前/n分後を求める&lt;/h2&gt;
&lt;p&gt;扨、ここからが本題なのですが、n分前/n分後を計算してみましょう。といっても、&lt;code&gt;date&lt;/code&gt;コマンドを使用すると非常に簡単に求めることが可能です。&lt;/p&gt;
&lt;p&gt;まずは現在時刻から1時間後を求めてみましょう。&lt;code&gt;-d&lt;/code&gt; / &lt;code&gt;--date&lt;/code&gt;オプションに加算したい時間を渡すだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;date +%R
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;date -d &lt;span class="s1"&gt;&amp;#39;1 hour&amp;#39;&lt;/span&gt; +%R
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Output:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 12:34&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 13:34&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;hour&lt;/code&gt;の他にも、&lt;code&gt;year&lt;/code&gt;や&lt;code&gt;month&lt;/code&gt;、&lt;code&gt;day&lt;/code&gt;、&lt;code&gt;minute&lt;/code&gt;などそれっぽいモノは大体使用することができます。珍しいところだと&lt;code&gt;fortnight&lt;/code&gt;(2週間)を使うこともできます。
単に&lt;code&gt;1 hour&lt;/code&gt;と書くのがなんとなく気持ち悪いという人は&lt;code&gt;now&lt;/code&gt;や&lt;code&gt;today&lt;/code&gt;、&lt;code&gt;this&lt;/code&gt;などを使用してより自然言語っぽい感じで書くこともできます&lt;/p&gt;</description></item><item><title>梅仕事2021 (2)</title><link>https://blog.web-apps.tech/ume-2021-2/</link><pubDate>Fri, 18 Jun 2021 15:34:24 +0000</pubDate><guid>https://blog.web-apps.tech/ume-2021-2/</guid><description>&lt;p&gt;先だって梅シロップを漬け、既に半分以上梅シロップを消化してしまった今日この頃、大分遅くなってしまったものの今年も梅酒を仕込みました。
就職で関東に出てきてから今年で4L瓶が5本目と相成りました。
本年は面倒くさがっている間にあれよあれよと日が経ってしまい、近所の西友では4L瓶が買えなくなる始末でありましたがなんとか4L瓶を調達する事に成功し、無事仕込みを済ませることができました。&lt;/p&gt;
&lt;p&gt;今年はあまり時間が無かったこともあり、梅は近所の西友で調達した南高梅(大玉)です。割と傷も少なく良い香りのする梅で、西友侮りがたし、といったところですね。おそらく1kgと思われる袋が980円(税抜)でした。&lt;/p&gt;
&lt;p&gt;酒は今年は初めて日本酒を使用。実は以前から日本酒で梅酒を仕込むというのはやってみたいと思ってはいたのですが、通常店頭で販売されている日本酒は梅酒を仕込むには度数が足りないため、梅酒(乃至果実酒)用のものを調達する必要がある、という面倒さがあり、店頭でそういった梅酒用の日本酒が販売されているのを発見したことがなかったため、これまでは挑戦してきませんでした。
今年はむやみやたらにAmazonのポイントが貯まっていたという事もあり、Amazonでいろいろと探したところ、果実酒用の日本酒が販売されていたためこちらを購入しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2021-2/images/PXL_20210618_145710091_hu_d9697fabda8e93fd.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;苗場酒造という酒蔵の苗場山「果実酒用日本酒」、度数が20%のものです。&lt;a href="https://amzn.to/35Ar3tW" target="_blank" rel="noopener"&gt;Amazon&lt;/a&gt;
で本体価格が1,800円、送料が500円です。&lt;/p&gt;
&lt;p&gt;日本酒を使うのは初めてのため、砂糖は特に奇をてらわず一般的な氷砂糖を使用しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2021-2/images/PXL_20210618_145632642_hu_870204c4efe3f1bb.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;作り方は特に例年と変わらず、洗ってへたを取った梅と砂糖を瓶に入れ、上から酒を注ぎ入れるだけです。日本酒の場合米の甘みがあるため砂糖は控えめで良い、という事でしたので、酒に付属してきたレシピにあわせて氷砂糖の量は500gとしました。例年は1kgで使用しているため、例年の半分です。&lt;/p&gt;
&lt;p&gt;このあとは砂糖が溶けるまでは時々振ってあげて、砂糖が溶けたら放置です。自家製梅酒大体3ヶ月程度からが飲み頃と言われていますから、9月くらいになったら味見をして、そのあとはまた数年放置されることとなります。&lt;/p&gt;
&lt;p&gt;最後に、&lt;a href="https://blog.web-apps.tech/ume-2020/"&gt;昨年は2017年に漬けた梅酒を飲んで締めたようなので&lt;/a&gt;
今年は2018年に漬けた梅酒を飲んで締めようと思います。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2021-2/images/PXL_20210618_151906550_hu_7a39adc383f43c92.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ラベルによると2018年は久米仙と氷砂糖を使用したようです。泡盛ですね。意外と癖もなく、飲みやすく仕上がっています。&lt;/p&gt;
&lt;p&gt;今年の梅酒も美味しく漬かることを祈って。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2021-2/images/PXL_20210618_152347004_hu_3f9842c06e89405.jpg" alt="" /&gt;
&lt;/p&gt;</description></item><item><title>梅仕事2021 (1)</title><link>https://blog.web-apps.tech/ume-2021-1/</link><pubDate>Wed, 26 May 2021 07:53:09 +0000</pubDate><guid>https://blog.web-apps.tech/ume-2021-1/</guid><description>&lt;p&gt;向暑の候皆様いかがお過ごしでしょうか。近所の西友で梅酒関連の商品が店頭に並びはじめているのを見て季節を感じる今日この頃です。&lt;/p&gt;
&lt;p&gt;例年梅酒と梅シロップを漬けるわけですが、漬けっぱなしで放置している梅酒はさておき梅シロップはできればシーズン中に二回は仕込みたい、という気持ちがあり、店頭で梅の実を発見してとりあえず購入してきました。&lt;/p&gt;
&lt;p&gt;まだ出始めですから、まだかなり青い実ではありますが、急ぎ一発目の梅シロップを仕込みました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2021-1/images/PXL_20210526_073535973_hu_fc4caecd8aa0e900.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;手順自体は例年とそう変わるモノではなく、昨年梅シロップをつけていた空き瓶をアルコールで消毒した後、洗って水気を切りへたを取った梅の実と砂糖を交互に積んでおいておきます。&lt;a href="https://blog.web-apps.tech/ume-2020/"&gt;昨年&lt;/a&gt;
は中ザラ糖を使用した、との記録がありましたが今年は気分で三温糖をセレクトしました。特に深い理由はありません。三温糖はしっとりとしており、積み上げるのも容易ですし、粉末状なので隙間にも入っていきやすく取り扱いがしやすい様に感じました。氷砂糖はうまく積んでいくことを考えると意外と難しいです。&lt;/p&gt;
&lt;p&gt;うまいこと梅を砂糖の中に埋める事ができ、上から見ると梅が出てしまっているということもありませんから、今年は酢を入れない方針で行ってみようと思います。&lt;/p&gt;
&lt;p&gt;大粒の実が店頭に並びはじめたら梅酒も漬けたい所存です。&lt;/p&gt;</description></item><item><title>最近のWebカメラってすごい、の件</title><link>https://blog.web-apps.tech/anker-powerconf-c300/</link><pubDate>Sun, 16 May 2021 15:08:14 +0000</pubDate><guid>https://blog.web-apps.tech/anker-powerconf-c300/</guid><description>&lt;p&gt;どうもAnker大好き人間です。ケーブル類は大体Ankerだし、&lt;a href="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/"&gt;Thunderbolt 3 Dock&lt;/a&gt;
もAnkerだし、充電器も&lt;a href="https://blog.web-apps.tech/soundcore-life-q30/"&gt;ヘッドホン&lt;/a&gt;
もAnkerです。&lt;/p&gt;
&lt;p&gt;そんなAnkerから、新しくWebカメラが発売されたということで、購入したらすごかったのです。&lt;/p&gt;
&lt;p&gt;購入したのは&lt;a href="https://amzn.to/3tRAfUy" target="_blank" rel="noopener"&gt;Anker PowerConf C300&lt;/a&gt;
。Amazonで7,990円で購入できます。&lt;a href="https://amzn.to/33PFZ6x" target="_blank" rel="noopener"&gt;LogicoolのStreamCam&lt;/a&gt;
を買いたいな、と思っていたところのAnkerからの新商品、値段も半額以下、という事で即購入に至りました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerconf-c300/images/PXL_20210516_135759784_hu_c88ef7efd1886f47.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱は最近よくあるぴったりでしっかりしたタイプの箱です。ぴったりすぎて開けるのにちょっと時間がかかる奴ですね。高級感はあります。写真ではざらざらしたかんじのテクスチャっぽく見えますが、これは印刷で、手触りはすべすべです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerconf-c300/images/PXL_20210516_135917536_hu_df5d8cf1faeecea2.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;これまでのAnker製品によく入っていたHappy/Not Happyカードではあんく、&amp;ldquo;WHAT DO YOU THINK OUR WORK?&amp;ldquo;というカードが入っていました。PowerConfシリーズではこの紙なんでしょうかね。
ケーブルはType-C to Type-Cケーブルが付属しています。この手のWebカメラは本体からケーブルが伸びている事が多いので、ケーブル交換ができるのはとても嬉しい点ですね。&lt;/p&gt;
&lt;p&gt;外部ディスプレイを使っていると、Webカメラは大体ディスプレイのUSBポートを使うと思うんですが、Type-CからUSB-Aに変換するためのコネクタも入っているので安心(?)です(Type-Cの仕様的には全然安心じゃないんですが)&lt;/p&gt;
&lt;p&gt;プライバシー保護用の蓋みたいなものもついているのはなんだか時代を感じさせますね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerconf-c300/images/PXL_20210516_140004242_hu_f3db067ab5d9e065.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;これまで使っていたWebカメラと並べた様子はこんな感じ。サイズは結構大きくなりましたね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerconf-c300/images/----------2021-05-16-23.06.18_hu_e904dec254b5ab3d.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;古い方のカメラで、ライトをつけないとこんな感じでした。一般的なご家庭は大体そうだと思うんですが、壁に机をくっつける配置にしていると夕方以降逆光になる、という問題があり、顔がとても暗くなります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerconf-c300/images/----------2021-05-16-23.06.29_hu_73b9ce219d8b5d45.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;結果として、&lt;a href="https://amzn.to/3uRrKKv" target="_blank" rel="noopener"&gt;ライト&lt;/a&gt;
を購入して明るさを確保したりなんかしている人も多いと思います。私もその一人でした。ライトをつければまぁもちろん明るくはなります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerconf-c300/images/----------2021-05-16-23.08.32_hu_be22ea071caf97da.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;新しいカメラではこの通り。ライトなしでも頭が適当にボサボサなのがバレて恥ずかしいくらいには明るく映ります。これは本当に感動。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerconf-c300/images/----------2021-05-16-23.08.40_hu_3374cbe33afe355e.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;比較用にライトをつけてみました。むしろちょっと明るすぎる位ですね。これはライトはもうお役御免かもしれません。&lt;/p&gt;
&lt;p&gt;加えて、専用のアプリで細かい設定をする事ができます。解像度の調整、fps、画角、明るさやコントラストなどが設定できるほか、人の顔を追跡するような設定もできます。
このアプリの良いところは、他のメーカーで良くあるような、常駐させておかなければ設定が反映されないような類いのモノではなく、設定したらアプリを閉じても設定が反映され続ける、というところですね。&lt;/p&gt;
&lt;p&gt;総じて、非常に満足度が高く、コストパフォーマンスに優れた商品だと思いました。流石Anker。&lt;/p&gt;</description></item><item><title>RAMマウントをQi対応にする</title><link>https://blog.web-apps.tech/ram-mounts-plus-qi/</link><pubDate>Tue, 27 Apr 2021 03:26:23 +0000</pubDate><guid>https://blog.web-apps.tech/ram-mounts-plus-qi/</guid><description>&lt;p&gt;バイク乗りの皆さん、スマホホルダーは何を使っていますか？色々と選択肢はありますが、しっかりとしたものを使いたいと考えた時、RAMマウントを使っている人も多いでしょう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ram-mounts-plus-qi/images/2238DEFD-25A8-421A-A05F-3FEEA759DF11_hu_c64737922b501f63.jpeg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;加えて、バイクからUSB電源を引いてスマホを充電している人もいるでしょう。そうした場合、どこぞに駐車をして、スマホを取り外すたびにケーブルを抜いて、また走り出すときにケーブルを挿して、というのは少しばかり面倒じゃないでしょうか？&lt;/p&gt;
&lt;p&gt;世の中、面倒だという事柄にはそれを面倒ではなくするソリューションがあるもので、無接点充電対応のスマホホルダーなるものが販売されています。&lt;/p&gt;
&lt;iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=nasa9084-22&amp;language=ja_JP&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=as_ss_li_til&amp;asins=B083SP2KX8&amp;linkId=3f71293fc87adf3f2f1bb3fb5b1dcdc8"&gt;&lt;/iframe&gt;
&lt;p&gt;こういったモノを購入しても良いのですが、やはりスマホをしっかりホールドしてくれるという点でできれば安心安全のRAMマウントを使い続けたい気持ちがありました。
そう考えていたところ、世の中には防水仕様のQi充電器というモノが存在するという事を知りました。&lt;/p&gt;
&lt;iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=nasa9084-22&amp;language=ja_JP&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=as_ss_li_til&amp;asins=B07DHSHW37&amp;linkId=2d8a33f90ce9a3b75231e2c8c1f432c5"&gt;&lt;/iframe&gt;
&lt;p&gt;正直この手のものは屋内で使うモノだと思っていたので、どういうユースケースがあって防水仕様になっているのかはよく分からないのですが、私にとっては渡りに船、幸いなことに超薄型という事なのでなおのこと私のユースケースにぴったりということで商品がこちらです&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ram-mounts-plus-qi/images/IMG_20210424_135008472_hu_9871eba53256e318.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;友人の&lt;a href="https://twitter.com/tagucch" target="_blank" rel="noopener"&gt;@tagucch&lt;/a&gt;
に誕生日プレゼントとして送ってもらいました。感謝。&lt;/p&gt;
&lt;p&gt;&lt;ins datetime="2021-05-06T01:48:00+09:00"&gt;2021-05-06追記: Pixel 4とは相性が悪かった(Pixel 4ではうまく充電できず、iPhone XRで試したら充電できた)ため、本品はiPhoneを使っている妹に譲りRAMマウントは再びQi非対応となりました。無念。iPhoneユーザは本商品で問題ないはず。多分。&lt;/ins&gt;&lt;/p&gt;
&lt;p&gt;扨、実際これをRAMマウントに設置できるか、というところが問題ですが・・・&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ram-mounts-plus-qi/images/IMG_20210424_134929209_hu_e0c20a4f39d18d11.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;RAMマウントは汎用のスマホホルダーですので、ちゃんと余裕があります！ここに適当に突っ込んでみたところ、スマホのホールド感も問題なく設置できそうです。&lt;/p&gt;
&lt;p&gt;何故か丸い両面テープも付属していたので、おあつらえ向き、という感じで適当に両面テープで(本当は屋外用の両面テープを使った方がいいんでしょうが&amp;amp;屋外用の両面テープも持っては居るのですが)ぺたっと&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ram-mounts-plus-qi/images/IMG_20210424_135229582_hu_52cfa59427006516.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;うまく貼ることができました。これ自体は普通のUSB給電ですので、これまでケーブルを挿していたUSBポートからケーブルを抜き、代わりにQi充電器のケーブルを挿します。&lt;/p&gt;
&lt;p&gt;キーをオンにしてスマホを設置したところ無事に充電できました。
RAMマウントは中心部分は回転しないので、スマホの取り付け・取り外しも問題ありませんでした。&lt;/p&gt;
&lt;p&gt;めでたしめでたし。&lt;/p&gt;</description></item><item><title>Desk Tour 2021.04</title><link>https://blog.web-apps.tech/desk-tour-2021-04/</link><pubDate>Sun, 11 Apr 2021 15:12:31 +0000</pubDate><guid>https://blog.web-apps.tech/desk-tour-2021-04/</guid><description>&lt;p&gt;COVID-19が猛威を振るい、自宅で勤務するようになり早一年、少しずつ機材を増やし、入れ替え、作業環境を改善してきました。自分のデスクを紹介するDesk Tourの流行も少し落ち着いたところではありますが、ここで一度デスク環境を記録がてらご紹介します。&lt;/p&gt;
&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/desk-tour-2021-04/images/PXL_20210411_135744662_hu_67d92f1a07823c1e.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;全体像としてはこんな感じ。デスクは&lt;a href="https://www.nitori-net.jp/ec/feature/combineablefreedeskprefee/" target="_blank" rel="noopener"&gt;ニトリの組み合わせフリーデスク プレフェ&lt;/a&gt;
を使用しています。天板の幅は140cmです。最近腰痛がアレでアレなので、昇降デスクにしたい気持ちがあります。写真には写っていませんが、イスは&lt;a href="https://www.hermanmiller.com/ja_jp/products/seating/office-chairs/aeron-chairs/product-details/" target="_blank" rel="noopener"&gt;アーロンチェア&lt;/a&gt;
を使用していて、足下には&lt;a href="https://amzn.to/3t8DcRb" target="_blank" rel="noopener"&gt;エルゴノミクスフットレスト&lt;/a&gt;
を置いています。&lt;/p&gt;
&lt;p&gt;ディスプレイは&lt;a href="https://amzn.to/3dX3X4m" target="_blank" rel="noopener"&gt;LG 27UK850-W&lt;/a&gt;
という4K 27インチのディスプレイ2枚をモニターアーム(右が&lt;a href="https://amzn.to/3d5IV4C" target="_blank" rel="noopener"&gt;HP&lt;/a&gt;
、右が&lt;a href="https://amzn.to/3dX46Vs" target="_blank" rel="noopener"&gt;エルゴトロン&lt;/a&gt;
。HPのものもエルゴトロンのOEM商品なのでロゴ以外は実質同じ)で設置しています。右はHDMI接続、左はDisplayPort接続でつないでいて、わざわざType-C接続のモニタを買う必要が無かったな、と思っています。&lt;/p&gt;
&lt;h2 id="モニタの上"&gt;モニタの上&lt;/h2&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/desk-tour-2021-04/images/PXL_20210411_135852385_hu_1271cb772f2c01c6.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;マイクは&lt;a href="https://amzn.to/3wNL7VZ" target="_blank" rel="noopener"&gt;AKG LYRA&lt;/a&gt;
です。USB type-Cで接続するタイプのコンデンサマイクで、&lt;a href="https://amzn.to/3dRjiUl" target="_blank" rel="noopener"&gt;AnkerのType-C to Type-Aケーブル&lt;/a&gt;
を使用して接続しています。&lt;a href="https://amzn.to/3uEoLEE" target="_blank" rel="noopener"&gt;Rode PSA1&lt;/a&gt;
というマイクアームを使用して、マイクがモニタの上に来るように設置しています。マイクアームには&lt;a href="https://amzn.to/326Qh1w" target="_blank" rel="noopener"&gt;SwitchBot 温湿度計&lt;/a&gt;
をくっつけています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/desk-tour-2021-04/images/PXL_20210411_142249465_hu_257a6b6d01a70d85.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ウェブカメラは大昔に安く購入した&lt;a href="https://www.buffalo.jp/product/detail/bsw20km15bk.html" target="_blank" rel="noopener"&gt;バッファロー BSW20KM15&lt;/a&gt;
というものを使っていて、最近の良い感じのウェブカメラに買い換えたいな、と思っています。&lt;a href="https://amzn.to/2QjIPNW" target="_blank" rel="noopener"&gt;ロジクールのStreamCam&lt;/a&gt;
とか良さそう。まぁ特に不満は感じていないですが。&lt;/p&gt;
&lt;p&gt;日中は窓が机の奥にあるので特にライトとかは必要無いんですが、夕方になるとすぐ暗くなるのでライトも用意しました。&lt;a href="https://amzn.to/2PSGIAF" target="_blank" rel="noopener"&gt;UlanziのVL49&lt;/a&gt;
というライトを&lt;a href="https://amzn.to/3dO1b1u" target="_blank" rel="noopener"&gt;なんかぐねぐねするやつ&lt;/a&gt;
で設置しています。モニタ裏のアームにクリップ(の強い奴)で止めるような形です。&lt;/p&gt;
&lt;h2 id="手元"&gt;手元&lt;/h2&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/desk-tour-2021-04/images/PXL_20210411_135837318_hu_4c3f555e4fcf8f8d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;手元はこんな感じ。トラックパッドが結構好きなので、&lt;a href="https://www.apple.com/jp/shop/product/MJ2R2J/A/magic-trackpad-2-%E3%82%B7%E3%83%AB%E3%83%90%E3%83%BC" target="_blank" rel="noopener"&gt;Magic Trackpad 2&lt;/a&gt;
を使用しています。&lt;a href="https://amzn.to/3wLS4qC" target="_blank" rel="noopener"&gt;Magic Trackpad 2用のリストレスト&lt;/a&gt;
を使用しています。&lt;/p&gt;
&lt;p&gt;キーボードは&lt;a href="https://shop.yushakobo.jp/products/ergodash" target="_blank" rel="noopener"&gt;Ergodash&lt;/a&gt;
を使用していて、最近&lt;a href="https://shop.yushakobo.jp/products/ble-micro-pro" target="_blank" rel="noopener"&gt;BLE Micro Pro&lt;/a&gt;
で無線化しました。配線が減ってデスクの上がすっきりし、最高ですが時々接続が不安定になります。キーボード用のリストレストは&lt;a href="https://www.diatec.co.jp/shop/Macaron/" target="_blank" rel="noopener"&gt;FILCO Majestouch Wrist Rest &amp;ldquo;Macaron&amp;rdquo;&lt;/a&gt;
の17mm厚を使用しています。ちょっと厚いので、12mmの方でも良かったかな、という感じ。&lt;/p&gt;
&lt;p&gt;ゲームをするときは&lt;a href="https://amzn.to/3mD63dH" target="_blank" rel="noopener"&gt;ロジクール MX Master 3 for Mac&lt;/a&gt;
と&lt;a href="https://amzn.to/3a1XMes" target="_blank" rel="noopener"&gt;Razer Tartarus Pro&lt;/a&gt;
を使ってます。Razer Synapse、Macにも対応してくれ。&lt;/p&gt;
&lt;p&gt;スピーカーは&lt;a href="https://amzn.to/3mEVc3e" target="_blank" rel="noopener"&gt;Fostex PM0.1e&lt;/a&gt;
を最近買いました。電源ランプがまぶしすぎるのでサランネットの裏に養生テープを貼って調整しています(結果、白かったランプが緑
になった)。ゲームを配信するとき等に使っているヘッドホンは&lt;a href="https://amzn.to/3t8fuEE" target="_blank" rel="noopener"&gt;SoundCore Q30&lt;/a&gt;
で、&lt;a href="https://amzn.to/3mEPuhr" target="_blank" rel="noopener"&gt;ヘッドホンラック&lt;/a&gt;
にぶら下げています。。&lt;/p&gt;</description></item><item><title>switchbot-exporterを書いた</title><link>https://blog.web-apps.tech/switchbot-exporter/</link><pubDate>Tue, 23 Mar 2021 09:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/switchbot-exporter/</guid><description>&lt;p&gt;先だって、SwitchBot APIのGo言語用クライアント実装である&lt;a href="https://github.com/nasa9084/go-switchbot" target="_blank" rel="noopener"&gt;github.com/nasa9084/go-switchbot&lt;/a&gt;
を書いた、という&lt;a href="https://blog.web-apps.tech/go-switchbot/"&gt;記事&lt;/a&gt;
を書きましたが、これを使用してPrometheusで&lt;a href="https://www.switchbot.jp/meter" target="_blank" rel="noopener"&gt;SwitchBot温湿度計&lt;/a&gt;
の情報を収集できる&lt;a href="https://github.com/nasa9084/switchbot-exporter" target="_blank" rel="noopener"&gt;switchbot-exporter&lt;/a&gt;
を書いてみたので紹介します。&lt;/p&gt;
&lt;p&gt;switchbot-exporterは&lt;a href="https://github.com/prometheus/blackbox_exporter" target="_blank" rel="noopener"&gt;blackbox exporter&lt;/a&gt;
のように、起動時にはターゲットを指定せず、Prometheusがメトリクスを収集する際にrelabel_configでターゲットを与えるタイプのexporterです。
起動時に必要な情報はSwitchBotアプリから取得できるOpenTokenのみです。OpenTokenはコマンドラインオプションか、環境変数&lt;code&gt;SWITCHBOT_OPENTOKEN&lt;/code&gt;経由で渡すことができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ switchbot-exporter -switchbot.opentoken&lt;span class="o"&gt;=&lt;/span&gt;blahblahblah
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;SWITCHBOT_OPENTOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;blahblahblah switchbot-exporter
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;a href="https://hub.docker.com/r/nasa9084/switchbot-exporter" target="_blank" rel="noopener"&gt;docker image&lt;/a&gt;
も用意してありますので、例えばKubernetes上で動かすこともできます:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;apps/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Deployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;switchbot-exporter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;revisionHistoryLimit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;switchbot-exporter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;switchbot-exporter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;switchbot-exporter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nasa9084/switchbot-exporter:0.1.0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;TCP&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;SWITCHBOT_OPENTOKEN&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;valueFrom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;secretKeyRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;switchbot&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;opentoken&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;switchbot-exporter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;TCP&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;targetPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;switchbot-exporter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このようにして起動した後、&lt;a href="https://github.com/nasa9084/switchbot-exporter/blob/master/README.md" target="_blank" rel="noopener"&gt;README&lt;/a&gt;
に記載のあるようにprometheusの設定をします&lt;/p&gt;</description></item><item><title>SwitchBot APIのGoクライアント、go-switchbotを書いた</title><link>https://blog.web-apps.tech/go-switchbot/</link><pubDate>Thu, 25 Feb 2021 03:17:53 +0000</pubDate><guid>https://blog.web-apps.tech/go-switchbot/</guid><description>&lt;p&gt;&lt;a href="https://www.switchbot.jp/" target="_blank" rel="noopener"&gt;SwitchBot&lt;/a&gt;
は所謂IoT機器を扱っているメーカーで、温度計を専用のハブ経由でインターネットに接続し、アプリから室温を確認したり、室温によってエアコンの設定を変更する、などといったホームオートメーションに役立つガジェットを複数販売しています。&lt;/p&gt;
&lt;p&gt;しかし、それらのデータを確認できるのはSwitchBotのアプリからか、Bluetooth経由だけ、という状況で、私もHTTPのAPIを用意してくれたら良いのに、とずっと思っていました。&lt;/p&gt;
&lt;p&gt;ところが昨日、社のSlackで、&lt;a href="https://github.com/OpenWonderLabs/homebridge-switchbot-ble/issues/1" target="_blank" rel="noopener"&gt;こちらのissue&lt;/a&gt;
を共有してもらい、どうやら昨年12月ごろには&lt;a href="https://github.com/OpenWonderLabs/SwitchBotAPI" target="_blank" rel="noopener"&gt;HTTPのAPI&lt;/a&gt;
が使えるようになっていたっぽいことが分かりました。&lt;/p&gt;
&lt;p&gt;我が家にはHub Miniもあり、インターネットに接続してある状態ですから、早速次の手順でtokenを手に入れて試してみました:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;スマホでSwitchBotのアプリを開く&lt;/li&gt;
&lt;li&gt;プロフィールタブ &amp;gt; 設定と進み、アプリバージョンを10回連打する&lt;/li&gt;
&lt;li&gt;開発者向けオプションが表示されるので、開いてトークンを取得する&lt;/li&gt;
&lt;li&gt;Authorizationヘッダにトークンを入れ、https://api.switch-bot.com/v1.0/devices にGETでリクエストを投げてみる&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;結果、確かに自宅のSwitchBotデバイスの一覧を取得することができました。&lt;/p&gt;
&lt;p&gt;こうしちゃいられねぇ！と深夜に書いたGolang用のSwitchBotクライアントがこちらです:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nasa9084/go-switchbot" target="_blank" rel="noopener"&gt;https://github.com/nasa9084/go-switchbot&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;ドキュメントはpkg.go.inなどで見て下さい: &lt;a href="https://pkg.go.dev/github.com/nasa9084/go-switchbot" target="_blank" rel="noopener"&gt;https://pkg.go.dev/github.com/nasa9084/go-switchbot&lt;/a&gt;
今回はFunctional Option PatternとGoogleっぽいAPIの合わせ技構成にしてみました。&lt;/p&gt;
&lt;p&gt;例えば、デバイスの一覧を取得したい場合は次の様にすると取得することができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;switchbot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SET_YOUR_SWITCHBOT_OPEN_TOKEN&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;physical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;virtual&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Device&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;第一返値のphysicalはSwitchbotデバイスの事で、第二返値のvirtualは赤外線で通信するデバイスの事です。SwitchBot APIでは、SwitchBotデバイスの事を物理デバイス、赤外線で接続するデバイス(エアコンなど)のことをvirtual remote deviceと区別して扱います。&lt;/p&gt;
&lt;p&gt;API rate limitは1,000 request / dayとなっていて、あまり多いという訳ではないですが、例えば数分に一回、あるいは一時間に一回室温を取って記録するようなPrometheus Exporterを記述するといったことが捗ると思いますので、SwitchBotデバイスを使っている方は是非使ってみて下さい！&lt;/p&gt;</description></item><item><title>Firefox 83で導入されたピンチズームを無効にする</title><link>https://blog.web-apps.tech/disable-firefox-83-pinch-zoom/</link><pubDate>Tue, 02 Feb 2021 06:49:47 +0000</pubDate><guid>https://blog.web-apps.tech/disable-firefox-83-pinch-zoom/</guid><description>&lt;p&gt;11月7日にリリースされた&lt;a href="https://www.mozilla.org/en-US/firefox/83.0/releasenotes/" target="_blank" rel="noopener"&gt;Firefox 83&lt;/a&gt;
では、タッチスクリーン/タッチパッドを搭載したデバイスでのピンチズームがサポートされました。&lt;/p&gt;
&lt;p&gt;が、私としてはスクロールしたいだけなのにズームされてしまったりと誤動作が多く、使いづらいなーと感じましたので、無効化しましたが、設定画面からは無効化できなかったのでメモを残しておきます。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://support.mozilla.org/ja/kb/about-config-editor-firefox" target="_blank" rel="noopener"&gt;about:config&lt;/a&gt;
を開く&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zoom&lt;/code&gt;で検索し&lt;code&gt;apz.allow_zooming&lt;/code&gt;をfalseに設定する&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>チカの南蛮漬け</title><link>https://blog.web-apps.tech/tika-no-nanbanduke/</link><pubDate>Fri, 29 Jan 2021 13:17:22 +0000</pubDate><guid>https://blog.web-apps.tech/tika-no-nanbanduke/</guid><description>&lt;p&gt;チカはワカサギを少し大きくしたような小型の魚で、北海道では割とよく食べていた魚でした。上京してからはほとんど売られているのを見ず、たまに近所の西友や東武百貨店池袋店地下の鮮魚売り場で売られているのを見る程度です。&lt;/p&gt;
&lt;p&gt;天ぷらやフライなどで食べられることもある魚ではありますが、我が家では専ら南蛮漬けとして食卓に並んでいました。チカを見かけるとついつい買ってしまうのですが、今日も買ってしまったので南蛮漬けの紹介をします。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_081615168_hu_c14f08900e835439.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;材料はこちら。チカ1パック(100gあたり127円で、250gくらい入っていました)、玉ねぎ、パプリカです。我が家では実際のところ、魚より野菜が大量に入っている南蛮漬けが好きなこともあり、チカに対してかなりの量の野菜を入れます。玉ねぎは時期的に新たまねぎが売られていたので新たまねぎにしましたが、普通の玉ねぎでも問題ありません。チカも売っていなければワカサギを使うこともできます。パプリカは時期が悪いのか若干高かったです。&lt;/p&gt;
&lt;p&gt;まずは野菜を切っていきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_081727887_hu_dee00cdc1326639b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;これを&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_082107366_hu_2de59723cb855996.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;こうして&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_083518617_hu_ca35ae7b03f59781.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;こうです。パプリカはスライスすると水分が結構出ます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_083738890_hu_f4d3d09dfa04260c.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;キッチンペーパーなどを敷いたバットに乗せ、軽く塩をして冷蔵庫で休ませ、少し水を抜きます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_083914318_hu_fe8e704d78eb0dee.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;次は玉ねぎ。写真は二つですが結局三つ使いました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_084144399_hu_accfcec415773994.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;皮を剥いて、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_084937422_hu_82dbc65c90224418.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;こうです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_085220632_hu_c0451e7d006e2bc6.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;パプリカと同じく、キッチンペーパーなどを敷いたバットに載せ、軽く塩をして冷蔵庫で少し休ませます。特に、普通の玉ねぎを使う場合は空気にさらすことで辛味が抜けるので空気に触れる面積を広くするようにほぐしておきましょう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_091025548_hu_1aabcdd670541538.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;このぐらいのタイミングで漬けダレ用の出汁を引いておきます。面倒なら出汁の素をお湯で溶いても良いです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_085521412_hu_2aba2604fb296346.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;チカは軽く洗って、水気をしっかり切り(キッチンペーパーなどを使って！)ます。我が家ではワタなどは取ったりしませんが、気になる人は腹を開いてワタを抜いても良いと思います。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_090221341_hu_bf824a27e9dae3ac.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;何か手頃な袋などに入れて、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_090303340_hu_6b1a60e7db32e9e5.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;片栗粉をまぶします。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_090427099_hu_e9a4e8182ad68326.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;袋に空気を入れて適当に振るとうまくまぶすことができます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_091606258.MP-1_hu_932afc4217c17b31.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ピンボケしていますが、漬けダレです。砂糖大さじ3、醤油大さじ2、減塩醤油大さじ2(無ければ普通の醤油でもOK)、酢100cc、出汁200cc、輪切り唐辛子を適量です。これに揚げた魚やらなんやらを突っ込めば大体美味しいです。
玉ねぎ3、パプリカ2だと、更にこの倍量で漬けダレを作ります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_092039376_hu_d1b04631be3e8a3b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;漬けダレができたら、適当に温めた油を用意し、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_092123651.MP_hu_6c51016a8c33693f.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;チカを突っ込みます。写真では三匹しか入れてませんが、温度が下がりすぎないように適当に突っ込みます。この後更に四匹くらい突っ込みました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_092545349_hu_7c7831532a3f4810.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;なんか雰囲気で火が通ったっぽくなったら軽く油を切って、熱いうちに漬けダレに落とします。なんか泡が大きくなってきたり、良い感じの色がついたりしてきたら火が通ったと思って大丈夫でしょう。あとはひたすら、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_092703506.MP_hu_7469e50d6c72b323.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;揚げて、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_093650909_hu_774cd8fd5d9464e8.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ageて、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_094950967_hu_8f7d2869b3f0793f.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;漬けダレへ。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_100201515_hu_e1f8c979657e3699.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;冷蔵庫で休ませて少し水分を抜いた野菜と和えて、&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/tika-no-nanbanduke/images/PXL_20210129_100801232_hu_6ade5d750c270f03.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;偏りが発生しないように保存容器に詰めるなり皿に盛るなりして完成です。一晩おいたくらいが一番美味しくて、4日程度は日持ちします。&lt;/p&gt;</description></item><item><title>Soundcore Life Q30</title><link>https://blog.web-apps.tech/soundcore-life-q30/</link><pubDate>Tue, 26 Jan 2021 06:42:34 +0000</pubDate><guid>https://blog.web-apps.tech/soundcore-life-q30/</guid><description>&lt;p&gt;最近、&lt;a href=""&gt;Among Us&lt;/a&gt;
というゲームにはまっておりまして、友人とのプレイ動画を&lt;a href=""&gt;Youtubeで配信&lt;/a&gt;
なぞしているのですが、その際、リモートワークで自宅勤務になってからあまり使用されていなかったヘッドホンを使用しています。&lt;/p&gt;
&lt;p&gt;これまで使用していたヘッドホンは某社の社長からお下がりで頂いた&lt;a href=""&gt;beats studio wireless&lt;/a&gt;
なんですが、多少年数が経っているというのもあり、充電ポートがmicroUSB type-Bです。オフィスで使っている分には、専用のケーブルを一本用意しておいて、退勤時に充電するという運用でうまくいっていたものの、ここしばらくは自宅のケーブル類をなんとかtype-Cに統一しようとしていたことも相まってmicroUSBのケーブルを自宅で出しっぱなしにするというのは避けたいという気持ちが強くなりました。&lt;/p&gt;
&lt;p&gt;そんなわけでtype-C充電のヘッドホンがほしいな〜と思っていたのですが、beatsの新しめのモデルは相変わらずmicroUSB充電で、かといってSONYとかBOSEとかの上位モデルを買うかというと、&lt;a href="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/"&gt;Anker PowerExpand Elite&lt;/a&gt;
とか買っちゃったのでちょっと散財しすぎかな、と思っておりました。&lt;/p&gt;
&lt;p&gt;そんな折に目に入ったのが&lt;a href=""&gt;Soundcore Life Q30&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;ヘッドホンを購入しよう、と思ったときに個人的にはいくつか条件があり、まず一つは上述のtype-Cで充電できること。加えてオーバーイヤー型であること、&lt;a href=""&gt;ANC&lt;/a&gt;
がついていること、というあたりを条件としました。Soundcore Life Q30は多少形が好みではない感じがあるものの、どうせ基本は自宅で使うだけだし、価格も安いという事で購入に踏み切りました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051223360_hu_bd755fc34829060e.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;Soundcoreはみんな大好きAnkerのサブブランド(?)で、これまでには&lt;a href="https://blog.web-apps.tech/anker-soundcore-motionb/"&gt;スピーカー&lt;/a&gt;
を購入したことがありました。Web上のレビューも悪くなく、比較的安心して購入することができました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051401378_hu_a141b02f3251c1d2.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱はAnker製品にありがちなシンプル・・・という路線ではなく、Soundcore製品にありがちな写真+文字という感じのおしゃれな箱。最近(といってももう数年単位とかだと思いますが)こういう箱のオーディオ製品多いですよね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051420884_hu_b1b88798f6ca95dc.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;しかし梱包レベルはAnkerという感じ。ケースに入ったヘッドホンがそのまま箱に入っています。ウケる。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051437249_hu_7b210be58053c417.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051457893_hu_36c0286e2fd6e994.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051537937_hu_337db50838b1d75.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ケーブル類は小さい巾着袋に入って同梱されていました。この巾着が結構触り心地が良いです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051555602_hu_156f328fb78f346d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;付属していたケーブルはUSB type-A to USB type-Cケーブルと、AUXケーブルです。このAUXケーブルでつないで有線で音楽を聴けばハイレゾにも対応しているとか。そんなに音質のいい音楽を最近は聴かないので、あまり意味は無いですが。&lt;/p&gt;
&lt;p&gt;飛行機とかで無線NGな時に音楽を聴きたい人にはいいかも。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051637356_hu_c6f167e94cca99a4.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;中の仕切りは固定されているわけではなく、ただの梱包材だった模様。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_051707985_hu_23f04fe235002a5d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;梱包材を外してしまうと収納方法が分からなくなりそうですが、そういった可能性も考慮してか収納方法のタグがついてました。安心。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/soundcore-life-q30/images/PXL_20210126_053643159_hu_33342bb27a352fc5.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;装着感としては側圧が結構やさしめな様に感じます。眼鏡をかけて数時間装着しても痛くありませんでした。&lt;/p&gt;
&lt;p&gt;まだ使い始めなので音質等はレビューできませんが、以上、開封レビューでした。&lt;/p&gt;</description></item><item><title>Anker PowerExpand Elite 13-in-1 Thunderbolt 3 Dock</title><link>https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/</link><pubDate>Fri, 22 Jan 2021 07:47:47 +0000</pubDate><guid>https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/</guid><description>&lt;p&gt;Ankerが最近(といっても国内の販売開始は12月中旬頃だったはずなので、かれこれ一ヶ月は経過している)発売した、PowerExpand Elite 13-in-one Thunderbolt 3 Dockを購入したので、unboxing &amp;amp; review noteを書いておきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/product_hu_f17c737533b01585.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;実はこの商品自体は海外では大分前に発売されており、個人的には国内の発売を今か今かと待ち望んでいた形でした。発売即購入・・・といきたかったのですが、そこはAnker。良さそうな新商品はすぐに完売と相成ってしまったのでありました。&lt;/p&gt;
&lt;p&gt;個人的にこの商品を選んだのは、以下のような理由があります:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;USB Type-Cポートが複数ある
&lt;ul&gt;
&lt;li&gt;USB Type-Cポートが4つあり、うち二つはThunderbolt 3ポートです。一つはPCとつなぐことになるため、都合2つUSB Type-Cのポートが増える計算になります。弊宅ではケーブルをできるだけUSB Type-C to USB Type-Cに統一しようとしているため、USB Type-Cポートを増やすことができるというのが最優先事項でした。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;余計なポートが少ない
&lt;ul&gt;
&lt;li&gt;USB Type-Cポートを増やすというのが主目的なため、多くのドックにありがちな「いろんなポートがついてるよ！」は無駄でしかないという気持ちでした。光デジタルオーディオやSDカード、USB Type-AやEthernetも正直不要です。が、世の中の人はたくさんポートがついているものをほしがっているのか、Type-Cのポートを増やすだけ、という物はほぼ存在しておらず・・・&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;比較的小さい
&lt;ul&gt;
&lt;li&gt;世の中のドックは大きいんです。USB Type-Cポートを増やしたいだけなのに(以下略&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;比較的安い
&lt;ul&gt;
&lt;li&gt;大体このスペック(Thunderbolt 3 dock)だと約3万というのは最も安い方の値段で、高い物だと4万〜5万程度します。同時に発売されたThunderbolt 3ではないほうのドックは2万円程度ですが、Type-Cポートが少ないのです。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/cabling_hu_22f4776d4d5c2be2.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;現在の配線はこんな感じです。最初、PowerExpand - ディスプレイ間もtype-C to type-Cケーブルでつないでみたのですが、何か遅延があるのか、カクついているのか、マウスカーソルの動きに違和感がすごかったので、試しにHDMIでつないでみたところ、違和感がなくなったためHDMIでの接続としました。ウェブカメラはディスプレイのtype-Aポートにつないでおり、これをPowerExpandまで引き延ばすと取り回しが良くなさそうだったので、ディスプレイとPowerExpandの間にもう一本type-A to type-Cのケーブルを配線し、ウェブカメラは引き続きディスプレイのダウンストリームポートに接続するという形にしました。&lt;/p&gt;
&lt;p&gt;現状マイク(AKG Lyra)とキーボード(Ergodash)がPCに直接接続されているので、これをPowerExpandに接続する形にまとめられれば、PCのポートは一つで済むという事になり、取り回しが非常に楽になりそうです。マイクはtype-C接続なのでそのまま特に問題なく接続できそうですが、キーボードはmicro-Bなので、今更micro-Bのケーブルを増やしたくもないですし、どうするかはちょっと検討することになりそうです。&lt;/p&gt;
&lt;p&gt;以下unboxing。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_023730942-1_hu_82eec802daabc620.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_023738621_hu_24f9937f9a9b761e.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_023801087_hu_5d37cd4cb2b39859.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_023824554_hu_ee4cf15e1408029d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_023912747_hu_2c7c903831cc9a3b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_023925651_hu_a1703a4e66ed1bbb.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_023951313_hu_f2e6f7516ec6be3d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_024057681.NIGHT_hu_f6cd6f1c59b2748d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_024110717_hu_eb80a5a5ab6edb98.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-powerexpand-elite-13-in-1/images/PXL_20210122_064950710_hu_70cc615da6ac0542.jpg" alt="" /&gt;
&lt;/p&gt;</description></item><item><title>2020年買って良かった物</title><link>https://blog.web-apps.tech/2020-good-buy/</link><pubDate>Wed, 23 Dec 2020 16:38:13 +0000</pubDate><guid>https://blog.web-apps.tech/2020-good-buy/</guid><description>&lt;p&gt;世間の波に乗って、書いてみる。&lt;/p&gt;
&lt;h2 id="ガジェット類"&gt;ガジェット類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3he1TpV" target="_blank" rel="noopener"&gt;Anker PowerWave 10 Pad(改善版)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;ワイヤレス充電器は安物だったり、ノベルティでもらった物だったりしか使ったことがなかったためあまりいい印象がなかったが(といってもこれも別に高くはないけど)、改めてちゃんと買って見たら充電速度も十分でかなり良い。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/2WIaOGI" target="_blank" rel="noopener"&gt;サンワサプライケーブルトレー(メッシュ・汎用タイプ) CB-CT5&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;クランプでデスク下に付けるタイプのケーブルトレー。デスクの上が大分すっきりした。キーボードの配線だけは現状どうしようもないので、なんとかしたい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3mHYLUE" target="_blank" rel="noopener"&gt;スリムな人間工学的なリストレストマジックトラックパッド2世代&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;明らかにアレっぽい感じの商品名で、実際梱包の感じがアレだったけど商品自体はそこそこちゃんとしてる。机との相性が良くないのか、手首がかゆくなる事がちょいちょいあったけど、これを使い始めてからはそういったことも無くなった。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3mKfFll" target="_blank" rel="noopener"&gt;Twelve South BookArc for MacBook (Space Grey)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;結構ずっとほしかったものの、スタンドだけでこの値段は・・・と思ってためらっていたが、最終的に購入し、机の上が広くなったので大変満足。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="メガネ関連"&gt;メガネ関連&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/2WInXQ5" target="_blank" rel="noopener"&gt;SIMON アンチフォグ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;このご時世、メガネをしている人は絶対買った方が良い。これを使っていないで「マスクすると眼鏡が曇るから・・・」というのは甘え。マジで全く曇らなくなり世界が変わるので、最寄りのビックカメラ or amazonで即購入してください。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3hdLrWJ" target="_blank" rel="noopener"&gt;メガロック ミニ&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;軽めのフレームで、視力が悪くて薄型レンズにしているひとに特にオススメ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="キッチン用品類"&gt;キッチン用品類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3nMD8nd" target="_blank" rel="noopener"&gt;Iwatani たこ焼きプレート CB-P-TAF&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3hdkPVW" target="_blank" rel="noopener"&gt;Iwatani 焼肉プレート小 CB-P-Y2&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;我が家で使用しているIwataniのカセットコンロをホットプレートのごとく使用することができる焼き肉プレートとたこ焼きプレート。大阪の人が「たこ焼きは絶対ガス火で作った方がいい」という気持ちも分かるようになったし、ちゃんと油が下に落ちる焼き肉プレートはかなり快適。ホットプレートと違って、熱源とプレートが別売のものなので、どちらかが使えなくなってもダメになった物だけ買い換えればよい、というのも大変よいところ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/2KM3NSG" target="_blank" rel="noopener"&gt;貝印 バターケース&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;バターケースというより、バターカッターとして使用。カットした後のバターは&lt;a href="https://amzn.to/37Hi5Nw" target="_blank" rel="noopener"&gt;山崎実業 バルブ付き密閉バターケース&lt;/a&gt;
に入れている。個包装のカット済みバターより安く、同程度の利便性を得られるのでバターをよく使う人にオススメ。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3nJGbNe" target="_blank" rel="noopener"&gt;OXO シリコン スパチュラ M&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;実家にいたときはゴムべらなんて製菓の時にしか使わないと思っていたけど、料理に使っても便利と言うことを実家を離れてから知ったので、100円のじゃなくてそこそこちゃんとしたのを買った。溶ける心配も無いし(100円のは柄が溶けそう)、使いやすい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/34EPxCc" target="_blank" rel="noopener"&gt;超強力 マグネットフック Cosego 6個入&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;こちらも100円の物から買い換え。磁力も強く、割と何でも掛けることができて便利。4人前用のパエリアパンくらいの重さになると、一つでは支えきれなくなる程度の力がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/3hpTcJz" target="_blank" rel="noopener"&gt;山崎実業 戸棚下調味料ラック&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;細かい調味料類(&lt;a href="https://amzn.to/3mNHqtg" target="_blank" rel="noopener"&gt;こういうの&lt;/a&gt;
とか&lt;a href="https://amzn.to/3ppMk1z" target="_blank" rel="noopener"&gt;こういうの&lt;/a&gt;
、なおこれらはあまり良くなかった)を置いておくのに便利。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>バックアップはちゃんと取りましょう、という話</title><link>https://blog.web-apps.tech/we-need-backup/</link><pubDate>Tue, 06 Oct 2020 06:18:33 +0000</pubDate><guid>https://blog.web-apps.tech/we-need-backup/</guid><description>&lt;p&gt;諸般の事情・・・というか単純に本ブログを動かしていたサーバーがどうやら壊れたようで(すぐに作業できる場所に置いてない)、とりあえずクラウド上に同じような環境を作ってバックアップからリストアしたんですが、最後にバックアップ取ってから何本か記事を書いていた物が消失しました。&lt;/p&gt;
&lt;p&gt;皆さんちゃんとバックアップは定期的にとりましょう。&lt;/p&gt;
&lt;p&gt;以上です。&lt;/p&gt;</description></item><item><title>Rakuten Mini unpacking</title><link>https://blog.web-apps.tech/rakuten-mini-unpacking/</link><pubDate>Sat, 13 Jun 2020 11:27:54 +0000</pubDate><guid>https://blog.web-apps.tech/rakuten-mini-unpacking/</guid><description>&lt;p&gt;昨日、何かと今話題の&lt;a href="https://network.mobile.rakuten.co.jp/product/smartphone/rakuten-mini/" target="_blank" rel="noopener"&gt;Rakuten Mini (C330)&lt;/a&gt;
が届きましたので、開封・セットアップしました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/IMG_20200612_172921_hu_8afa23328896e823.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;外箱はシンプルな感じ。このタイプの箱、最近流行ですね。届いた内容物としては、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rakuten Mini&lt;/li&gt;
&lt;li&gt;Rakuten Mini初期設定方法のご案内&lt;/li&gt;
&lt;li&gt;Rakuten Mobile eSIM版 START GUIDE&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;の三つでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/IMG_20200612_172937_hu_f5cc18fa542d04dc.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱の底面には何も書いてありません。ちょっと作りが甘いというか、蓋が大きいように見えます。が、Appleの作りの良い箱とかはぴったりすぎてちょっと開けにくいので、これくらい緩い方がむしろ開けやすいかも。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/IMG_20200612_173001_hu_77479cd4b8586f62.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;開けると早速端末がお目見え。小さくて可愛いです。色はクリムゾンレッドを選択しました。少し落ち着いた感じの赤で良い感じ。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/IMG_20200612_173119_hu_d2c5d65a441fe0a6.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;付属品はこんな感じ。本体の他、ペライチの説明書、充電用のケーブル、充電アダプタ、イヤホン変換ケーブルが入っていました。&lt;/p&gt;
&lt;p&gt;充電アダプタは5V1Aで、急速充電には対応していないようです。多分。写真でもわかるとは思うんですが、コンセント側が少し小さい台形になっているので、コンセントの状況によっては使いづらいかもしれません。&lt;/p&gt;
&lt;p&gt;説明書は小さく、半分に折りたたまれているだけの紙なので、情報は非常に少ないですね。&lt;/p&gt;
&lt;p&gt;イヤホン変換ケーブルはPixel 4だと付属していなくて、&lt;a href="https://store.google.com/jp/product/usb_c_headphone_adapter" target="_blank" rel="noopener"&gt;Google Storeで1,320円&lt;/a&gt;
なので、有線のイヤホンを使いたい人には嬉しいかも。私は使いませんが・・・。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/IMG_20200612_173315_hu_dbed9af34d366b7.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;本体を保護していたフィルム？を剥がしたらこんな感じ。つやのある色で、あまり安っぽい感じはありません。Rの文字とFelicaマークは銀色です。白は背面が白、側面がシルバーなので、側面がメッキっぽい感じの赤とかだったらやだなぁ・・・と思っていたのですが、そんなこともなく、違和感のない色合いになっています。&lt;/p&gt;
&lt;p&gt;カメラは(イマドキのスマホはだいたいそうですが)若干飛び出ています。が、0.5mmに満たないくらいしか飛び出ていないので、あんまり気にする必要はなさそうです。&lt;/p&gt;
&lt;p&gt;写真で言うところの左下の角にストラップホールがあり、これは最近の端末としては結構珍しいように思えます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/IMG_20200612_173351_hu_2c68395f0b866404.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;画面側。まぁ特筆すべきことは特にないですね。画面向かって右側に電源ボタンと音量ボタンがあります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/IMG_20200612_182704_hu_7e647f56768f2e30.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;サイズ比較のため、SAPICAと重ねてみました。普段はPASMOを使っているんですが、東武カード一体型のため、写真には使えなかったんですよね・・・&lt;/p&gt;
&lt;p&gt;幅はカードと同じか少し小さいくらいで、長さはカードより長いです。こうしてみるとかなり小さいですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/rakuten-mini-unpacking/images/MVIMG_20200612_175719_hu_bf47a5dd34389eb1.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;起動するとホーム画面はこんな感じです。なんだかちょっと高齢者向けあるいは子供向けの端末っぽい気もしますが、小さい画面で扱いやすい、なかなか悪くないホーム画面だと思います。ベゼルが大きいスマホは久々に持ったので、ちょっと違和感があります。&lt;/p&gt;
&lt;p&gt;初期IMEはiWnn IMEとか言うやつで、わたしはATOKに入れ替えました。フリック入力は思ったより余裕で、twitterくらいなら全然不便を感じません。一方でQWERTYキーボードによる入力はやはりちょっと厳しい感じ。入力自体はできますが、ちょっと疲れてしまいそうです。&lt;/p&gt;
&lt;p&gt;まぁ1円で手に入り、Felica搭載、顔認証でロック解除ができ、ジーンズのコインポケットに入る小ささ、回線料金も一年は無料ですから、興味があったら申し込んでみても良いのではないでしょうか。特に、Falicaを搭載していない端末をメインで使っている方は決済用端末として購入してみても悪くは無いと思いますよ。事務手数料も無料というか、むしろポイントでプラスになりますしね。&lt;/p&gt;</description></item><item><title>梅仕事2020</title><link>https://blog.web-apps.tech/ume-2020/</link><pubDate>Sat, 06 Jun 2020 16:53:33 +0000</pubDate><guid>https://blog.web-apps.tech/ume-2020/</guid><description>&lt;p&gt;6月ですね。梅の季節でございます。
数日前から近所の西友でも梅の実やらなんやらが店頭に並び始めまして、あぁ6月か、と感じる次第です。
20歳になった6月から毎年梅酒やら梅シロップやらを作ってまして、シロップはまぁ家族も飲みますし、そもそもそれほど(少なくとも年単位では)日持ちする物ではありませんから、作っては消費し、という感じですが、梅酒は(あまり自宅で酒を飲まないので)毎年4L瓶が増え続けています。就職して関東に出てくるまでに作った物は実家に置いてきてしまったのですが、どこかのタイミングで引き取りたい気持ちがありますね。
まぁそこまでの物を置いてきたとはいっても、関東に出てきてからかれこれ4年、4L瓶も今年で4本目、札幌に置いてきた物と合わせると8本になりますから、なんとか圧縮するなりする必要がありそうです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_181702_hu_915cef09b05c86f9.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;扨、今年は池袋にある東武百貨店の地下食料品売り場で南高梅を購入してきました。約1kg(1kgをちょっと超えるくらい)で1500円でした。2kgほど買いましたので、3000円ですね。スーパーで買うと大体1000円/kg位ですが、そこは百貨店、実も大きく、傷がほとんど無い良い梅です。&lt;/p&gt;
&lt;p&gt;梅酒用にはまだ青い実を、梅シロップ用には比較的熟していそうな黄色い実を選んできました。&lt;/p&gt;
&lt;p&gt;20歳の時に作ったときに、このように水に実を漬けて、あく抜き(?)をせよという情報を見たため、何も考えずに毎年このように水に漬けていますが、わりとさっとあげてしまうので、実際効果というか、意味があるのかどうかは不明です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_191123_hu_4c6c8bcbaa7fc0b0.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;瓶は特に特別な物は使用していなくて、西友で買ってきました。680円です。昨年梅シロップに使用した瓶は洗うのをサボって放置したため、再使用するのはちょっといやだな、と思ったので捨ててしまいました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_191534_hu_aa37320f144f6e18.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;さっと水で洗った後(本当はちゃんと洗った方が良いと思うんですけど、でかくて洗いにくいのでさっとで済ませてしまいます。毎年。特に問題は発生していません)、アルコール製剤を拭きかけて消毒します。特に梅シロップは酒が入らない分、ちゃんと消毒しておかないと変なことになりかねません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_195511_hu_c031fc8baac589ae.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;例年は氷砂糖を使用して作っていたのですが、今年は何の影響やら氷砂糖が完売だったので、思い切ってザラメを選択してみました。1kgあたり228円です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_200451_hu_20224aefd2f9a5fd.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;まずは梅シロップを仕込んでいきます。&lt;/p&gt;
&lt;p&gt;水からあげた梅の実をキッチンペーパーで拭いて水気を取り、爪楊枝でへたをとり、砂糖に埋めます。瓶に梅を敷き詰める、砂糖を上からかける、梅を敷き詰める、砂糖をかける、という感じです。&lt;/p&gt;
&lt;p&gt;梅は金気を嫌う、というはなしがありますが、これはまぁいろいろと理由があるようで、曰く、梅の酸で金属が腐食するので金属の道具を使うのは良くない、だとか、曰く、金属の道具では梅の実を傷つけやすく、傷がつくとカビなどの原因になったり、見た目や味が悪くなったりするから良くないのである、だとか。まぁ理由がないということは無いはずですので、素直に先達の言葉に従い、金属の道具を使わずにやっていきましょう。&lt;/p&gt;
&lt;p&gt;梅シロップは酢を入れるレシピと酢を入れないレシピがありますが、個人的にはむやみに発酵されたりカビられたりしても困りますし、液体が入った方が呼び水的な感じで早くできるかな、という気持ちで酢を少量入れています。効果のほどは不明です。今年はたまたまリンゴ酢があったので、これを使用してみました。大さじ三ほど適当にかけておきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_200809_hu_fcf74b89faa0703f.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;梅シロップの仕込みが終わったら次は梅酒です。今年は宝酒造の「果実酒の季節」を使用します。近年どこのスーパーでもよく売られている甲類焼酎ですね。毎年梅酒を仕込んでいますが、実は果実酒の季節は使ったことがありませんでした。特にここ数年は麦焼酎で漬けてみたり、泡盛で漬けてみたりしていたので、ホワイトリカー自体使用していませんでした。&lt;/p&gt;
&lt;p&gt;毎年氷砂糖でやっていたので、酒の方をいろいろ試していたのですが、今年は前述の様にザラメを使用しており、砂糖側の条件を変えたので、まぁ果実酒用のホワイトリカーなら余計な匂いもなかろうということでこれを選んでみました。1.8Lで1258円です。&lt;/p&gt;
&lt;p&gt;開封してみて驚いたんですが、この「果実酒の季節」、全然匂いしないんですね。まぁ、もちろんアルコールの匂いは多少しますが、それでも全然匂いがない。なるほど、確かにこれは果実酒向きっぽい。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_201816_hu_8b5b0486c1a90e95.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;梅酒も最初の手順はシロップと同様です。梅を水から取り出し、キッチンペーパーで拭き、へたを取り、敷き詰め、砂糖をかけ、敷き詰め、砂糖をかけ・・・です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_202107_hu_919cd1f4a7c3a93b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;詰め終わったら上から酒をドバドバと流し込みます。ザラメを使用しているからだと思いますが、すでに茶色い色です。これはなんかちょっと楽しみですね。&lt;/p&gt;
&lt;p&gt;この後は数日ごとに軽く振るなり混ぜるなりしてあげて、梅のエキスを抽出していきます。氷砂糖だと大体3ヶ月から半年くらいで飲めるようになるんですが、ザラメでも同様なのかどうかはよくわかりません。まぁそもそも一年以上経たないと味見もろくにしないので、気長に待つことにします。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/ume-2020/images/IMG_20200606_203033_hu_a2b51403ce45f74b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;最後に2017年、つまり就職で関東に出てきた年の梅酒を引っ張り出してきて一杯やりました。大分角も取れて飲みやすくなっていましたね。この年はレシピを瓶に貼っていなかったので、どういうレシピで作ったのかはよく覚えてないんですが、とりあえず美味しかったのでよしとします。&lt;/p&gt;</description></item><item><title>AKG LYRAを購入した</title><link>https://blog.web-apps.tech/akg-lyra/</link><pubDate>Mon, 01 Jun 2020 08:29:47 +0000</pubDate><guid>https://blog.web-apps.tech/akg-lyra/</guid><description>&lt;p&gt;ようやく緊急事態宣言が解除され、むやみにガジェットを買う理由がなくなってしまった皆様、いかがお過ごしでしょうか。&lt;/p&gt;
&lt;p&gt;新型コロナウイルス感染症拡大防止の観点から、ﾍｲｼｬでも数ヶ月ほどリモートワーク(余談ですがWFH、という字面をついついWTFと空目してしまうのは私だけでしょうか)をしてきたわけですが、弊宅にはまともなマイクというものがありませんでした。しばらくはかなり前に購入したWebカメラ、&lt;a href="https://www.buffalo.jp/product/detail/bsw20km15bk.html" target="_blank" rel="noopener"&gt;BuffaloのBSW20KM15&lt;/a&gt;
の音声入力を使っていたのですが、何度か聞き取りにくい、と言われたので(大半は問題ないと言ってくれたのですが、まぁ理由付けのようなものです)、ある程度のUSBマイクを購入することを決意しました。&lt;/p&gt;
&lt;p&gt;とはいえ、社内外でおすすめされた&lt;a href="https://www.buffalo.jp/product/detail/bsw20km15bk.html" target="_blank" rel="noopener"&gt;オーディオテクニカ AT2020USB+&lt;/a&gt;
はそれこそみんなリモートワークをしているのが理由、と言わんばかりにどこを見ても在庫がない、という状態です。在庫復活はいつになることやら、、、と思いながら&lt;a href="https://www.soundhouse.co.jp/" target="_blank" rel="noopener"&gt;SOUNDHOUSE&lt;/a&gt;
を眺めていたところ、&lt;a href="https://www.soundhouse.co.jp/products/detail/item/269265/" target="_blank" rel="noopener"&gt;AKG LYRA&lt;/a&gt;
という何やらよさげな見た目をしたマイクが一押しっぽい感じでしたので、つい勢いで購入しました。今となってはAKG LYRAもお取り寄せ、となってしまっていますが、購入時点では1週間ほどで入荷予定ということでしたので、まぁそれくらいなら待とうか、ということで即注文、5月22日に届きました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/akg-lyra/images/IMG_20200522_150414_hu_3014763242fcc965.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;This is my new gear、な訳です。Youtubeではすでにそこそこ国内外のレビュー動画が投稿されており、それをぼーっと眺めたりもしていたので、そこそこサイズが大きい、というのはわかっていたのですが、届いてみたら予想以上に外箱が大きく驚きました。&lt;/p&gt;
&lt;p&gt;適当に何かサイズ感のわかる物はなかろうか、と思って手元を探したのですが、どうにもしっくりくる物がなく、唯一しっくりきたのがNINTENDO SWITCHでしたので、比較のために置いてみたのが次の写真です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/akg-lyra/images/IMG_20200522_150439_hu_f4d9092ea75f7ab1.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/akg-lyra/images/IMG_20200522_150503_hu_a2b37bd536cb3cfe.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;なかなかのサイズ感ですね。この手の物はスタンドと本体がバラバラになっていて、到着してから自分で組み立てる、ということになるのが良くあるパターンだと思うのですが、本製品はすでにガッチャンコされた状態で梱包されているので、外箱が大きくなったようでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/akg-lyra/images/IMG_20200522_215856_hu_6fde892da40b93ff.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;なんて入り方をしているのでしょう。。。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/akg-lyra/images/IMG_20200522_220031_hu_a1f3e3e31a115a66.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;取り出した本体がこちら。比較用にティッシュの箱を置いています。外箱の比較もティッシュでよかった説。結構良いサイズですね。まぁけっして小さくはありませんが、そこそこ重量があり安定していますし、高さもそこそこあるので普通の姿勢で安心してしゃべることができます。&lt;/p&gt;
&lt;p&gt;音質ですが、他のマイクは使ったことがないので、はっきり言って良くわかりません。しかし、ちゃんと聞こえてはいるようです。良かった良かった。PCとの接続は&lt;a href="https://www.ankerjapan.com/category/USBCCABLE/A8485.html" target="_blank" rel="noopener"&gt;ANKERのC2Cケーブル&lt;/a&gt;
を使っていますが、特に問題ないようです。&lt;/p&gt;
&lt;p&gt;個人的にはマイク側のMUTEボタンと、ZOOMなどのミュートが連動できたらなお良いと思うのですが、どなたか方法をご存じだったら教えて下さい。&lt;/p&gt;</description></item><item><title>rustで書かれたlsの代替コマンドexaをインストールしてみた</title><link>https://blog.web-apps.tech/replacing-ls-with-exa/</link><pubDate>Wed, 20 May 2020 02:54:27 +0000</pubDate><guid>https://blog.web-apps.tech/replacing-ls-with-exa/</guid><description>&lt;p&gt;twitterでおのかちお氏(鍵垢なのでここでは紹介できないが)が&lt;a href="https://github.com/ogham/exa" target="_blank" rel="noopener"&gt;&lt;code&gt;exa&lt;/code&gt;&lt;/a&gt;
というlsの代替コマンドを試してみている、ということでスクショをアップしており、これがなかなか良さそうであったので、探してインストールしてみました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://the.exa.website/" target="_blank" rel="noopener"&gt;website&lt;/a&gt;
の説明によると、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A modern replacement for ls.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;トのことで、色をつけれたり、早かったり、tree viewができたり、Gitのステータスを表示できたりするらしい。&lt;/p&gt;
&lt;p&gt;macの場合、&lt;a href="https://brew.sh/index_ja" target="_blank" rel="noopener"&gt;homebrew&lt;/a&gt;
でインストールできるようなので早速インストールしてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew install exa
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;very easyですね。使ってみましょう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/replacing-ls-with-exa/images/----------2020-05-20-11.24.34_hu_d210109d7de5c828.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;なるほど、デフォルトの表示は&lt;code&gt;ls&lt;/code&gt;と同じくgrid viewなんですね。ホームにディレクトリしかないのでわかりにくいですけど、字が太いですね。あと&lt;a href="https://github.com/klaussinani/hyper-pokemon" target="_blank" rel="noopener"&gt;klaussinani/hyper-pokemon&lt;/a&gt;
を使っている都合で、色は表示されません・・・&lt;/p&gt;
&lt;p&gt;アイコン付きで表示してみましょう。アイコンを表示したい場合は&lt;code&gt;--icons&lt;/code&gt;オプションをつければ良い、とのこと。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/replacing-ls-with-exa/images/----------2020-05-20-11.24.59_hu_3d79a5873ba9959c.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;おや、表示されないですね。これは困った。まぁこの手の問題は(見た目から言っても)フォントがインストールされてないために発生しているのだろう、とあたりをつけつつ、issueを検索します。&lt;/p&gt;
&lt;p&gt;すると&lt;a href="https://github.com/ogham/exa/pull/368" target="_blank" rel="noopener"&gt;どうやら&lt;/a&gt;
&lt;a href="https://www.nerdfonts.com/" target="_blank" rel="noopener"&gt;nerd fonts&lt;/a&gt;
というフォントがアイコン表示用に使用されているようです。これをインストールしてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew tap homebrew/cask-fonts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;==&lt;/span&gt;&amp;gt; Tapping homebrew/cask-fonts
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Cloning into &lt;span class="s1"&gt;&amp;#39;/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask-fonts&amp;#39;&lt;/span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Enumerating objects: 19, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;19/19&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;14/14&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;remote: Total &lt;span class="m"&gt;35658&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 8&lt;span class="o"&gt;)&lt;/span&gt;, reused &lt;span class="m"&gt;9&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;delta 5&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused &lt;span class="m"&gt;35639&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;35658/35658&lt;span class="o"&gt;)&lt;/span&gt;, 6.07 MiB &lt;span class="p"&gt;|&lt;/span&gt; 3.34 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;25786/25786&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Tapped &lt;span class="m"&gt;924&lt;/span&gt; casks &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;973&lt;/span&gt; files, 7.8MB&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ brew cask install font-hack-nerd-font
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updating Homebrew...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error: Cask font-hack-nerd-font exists in multiple taps:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; homebrew/cask-fonts/font-hack-nerd-font
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; caskroom/fonts/font-hack-nerd-font
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;おや、エラーが出ましたね。今回追加した&lt;code&gt;homebrew/cask-fonts&lt;/code&gt;というtapと元々あった&lt;code&gt;caskroom/fonts&lt;/code&gt;というtapの両方に同名のパッケージがあったようです。詳細を見てみましょう。&lt;/p&gt;</description></item><item><title>Gmail Filter as Code</title><link>https://blog.web-apps.tech/gmail-filter-as-code/</link><pubDate>Fri, 08 May 2020 01:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/gmail-filter-as-code/</guid><description>&lt;p&gt;&lt;a href="https://twitter.com/yamamoto_febc" target="_blank" rel="noopener"&gt;@yamamoto_febc&lt;/a&gt;
さんの&lt;a href="https://febc-yamamoto.hatenablog.jp/entry/2020/04/26/182608" target="_blank" rel="noopener"&gt;ブログ記事&lt;/a&gt;
で、&lt;a href="https://github.com/jessfraz/gmailfilters" target="_blank" rel="noopener"&gt;jessfraz/gmailfilters&lt;/a&gt;
というツールを知りました。なんでも、GmailのフィルタをTOMLで管理するツール、とのこと(実際の使用例などは&lt;a href="https://kakakakakku.hatenablog.com/entry/2020/04/22/090002" target="_blank" rel="noopener"&gt;kakakakakkuさんの記事&lt;/a&gt;
で紹介されています)。
それは素敵っぽい、ということで触ってみたところ、実際良い物っぽい感じはあったものの、TOMLというのが(個人的に)つらいし、releasedなバージョンではexportができない(機能自体はmasterにあるものの、一年前に機能開発されてからリリースが打たれていない、という点がちょっと不安)という二点が気になりました。
特にTOMLはどうにも好きになれず、やはりYAMLで書きたい、という気持ちが強かった+GWの自由研究が決まらなかったので自前で書き直し、これをGmail as Code (今はfilterしか管理できないけど、他の設定も管理できるようにしたい)から&lt;a href="https://github.com/nasa9084/gmac" target="_blank" rel="noopener"&gt;gmac&lt;/a&gt;
と名付けました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;YAMLで設定したい&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1b) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1254720750264541184?ref_src=twsrc%5Etfw"&gt;April 27, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;h2 id="gmac---gmail-as-code"&gt;GMaC - Gmail as Code&lt;/h2&gt;
&lt;p&gt;大枠の挙動としては、jessfraz/gmailfiltersとそれほど変わりません。Gmail APIを&lt;a href="https://pkg.go.dev/google.golang.org/api/gmail/v1" target="_blank" rel="noopener"&gt;google.golang.org/api/gmail/v1&lt;/a&gt;
を使用して叩いているのも同じです。
jessfraz/gmailfiltersと比較して、違う点として次の様なものがあります:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TOMLではなくYAMLで設定を記述する&lt;/li&gt;
&lt;li&gt;Gmail Web UIに比較的近い設定項目
&lt;ul&gt;
&lt;li&gt;jessfraz/gmailfiltersも実装しているArchiveやDeleteなどはもちろん実装&lt;/li&gt;
&lt;li&gt;条件/アクションを個別に設定する形にした
&lt;ul&gt;
&lt;li&gt;jessfraz/gmailfiltersみたいに全部まとまってるとわかりにくくない？&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;larger_than&lt;/code&gt;や&lt;code&gt;subject&lt;/code&gt;、&lt;code&gt;has_attachment&lt;/code&gt;といった条件も追加&lt;/li&gt;
&lt;li&gt;&lt;code&gt;star&lt;/code&gt;や&lt;code&gt;important&lt;/code&gt;、&lt;code&gt;category&lt;/code&gt;(私は使ってないけど)といったアクションも追加&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;OAuthの際に認証/認可ページを自動で開き、OAuth callbackも受ける
&lt;ul&gt;
&lt;li&gt;jessfraz/gmailfiltersはURLと、OAuth tokenをコピペする必要がある&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;credentials.json&lt;/code&gt;および&lt;code&gt;token.json&lt;/code&gt; (OAuthの認証ファイル)を特定の場所に置き、そこから読み込む
&lt;ul&gt;
&lt;li&gt;jessfraz/gmailfiltersは毎回ファイルパスを指定する必要がある&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;kubectl-likeなサブコマンド配置
&lt;ul&gt;
&lt;li&gt;get/applyが個別に行え、(k8sに慣れている人は)比較的なじみやすいはず&lt;/li&gt;
&lt;li&gt;jessfraz/gmailfiltersはオプションフラグで挙動を変える方針っぽい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CIで使いやすい(と思う)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;credentials.json&lt;/code&gt;を標準入力から読める&lt;/li&gt;
&lt;li&gt;OAuth refresh tokenを環境変数で指定できる&lt;/li&gt;
&lt;li&gt;jessfraz/gmailfiltersはファイルからのみ&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(そこそこ)ちゃんとテストを書いている
&lt;ul&gt;
&lt;li&gt;全部とはいえないけど・・・&lt;/li&gt;
&lt;li&gt;jessfraz/gmailfiltersはほとんどテストがなくてちょっと怖い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;(そこそこ)ドキュメントを整備してある
&lt;ul&gt;
&lt;li&gt;README.mdを頑張って書いた&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;逆にjessfraz/gmailfiltersがサポートしている、&lt;code&gt;queryOr&lt;/code&gt;や&lt;code&gt;archiveUnlessToMe&lt;/code&gt;は実装していません。ORとか普通に書けばよかろう。&lt;/p&gt;
&lt;h3 id="manage-with-ci"&gt;Manage with CI&lt;/h3&gt;
&lt;p&gt;実際に、GitHub Actionsを使用して自分のGmail Filterを管理するように設定しました。管理用のプライベートリポジトリに&lt;code&gt;filters.yml&lt;/code&gt;としてフィルタの設定ファイル(これ自体も &lt;code&gt;gmac get filters -o yaml &amp;gt; filters.yml&lt;/code&gt; として出力したもの)と、次のGitHub Actions設定ファイルをおいてpushごとに適用するように構成しました。&lt;/p&gt;</description></item><item><title>YOBYBO CARD20</title><link>https://blog.web-apps.tech/yobybo-card20/</link><pubDate>Mon, 27 Apr 2020 08:56:45 +0000</pubDate><guid>https://blog.web-apps.tech/yobybo-card20/</guid><description>&lt;ins datetime="2020-05-19T14:32:37+09:00"&gt;
2020-05-19追記:
外出時にPixel 4との組み合わせで使用したら、音の途切れが激しく、正直使い物にならなかったので、「不良品では？」と問い合わせをしたら返品・返金対応となりました。見た目、サイズ感、装着感などは良かっただけに残念です。
&lt;/ins&gt;
&lt;p&gt;先だってMakuakeで応援購入した&lt;a href="https://www.makuake.com/project/card20/" target="_blank" rel="noopener"&gt;CARD20&lt;/a&gt;
が届いたので、開封レビューします。&lt;/p&gt;
&lt;p&gt;CARD20は非常に薄い左右完全独立型のワイヤレスイヤホンで、クラウドファンディングプラットフォームMakuakeで出資を募っていました。私も1月末頃に支援をし、紆余曲折あり(コロナのせいであれこれあったらしい)本日手元に届きました。&lt;/p&gt;
&lt;p&gt;なお、多くの「提供」記事がウェブで展開されていますが、本記事は提供を受けたわけでもなく、自分で買っての感想です。&lt;/p&gt;
&lt;p&gt;特筆すべきはその薄さで、この手のTWSイヤホンでも比較的標準と思われるサイズ感の&lt;a href="https://aviot.jp/product/te-bd21f" target="_blank" rel="noopener"&gt;AVIOT TE-BD21f&lt;/a&gt;
のケースの厚さが3cm弱程度なのに対し、CARD20はなんと1.3cmと、TE-BD21fの約半分の厚さです。Pixel 4 (ファブリックケース付き)より若干厚いかな、という程度です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_171634_hu_65100ee0cdeff1bd.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;CARD20の13.4mm世界最薄クラスのボディは、お財布やジーンズのコインポケットにしまうことができ、コードや収納の煩わしさから解放されます。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;との説明がプロジェクトページに書かれていたものの、さすがに1.3cmのものを財布に入れたら邪魔そうではあります。とはいえコインポケットに入るのはなかなか良さそうです。&lt;/p&gt;
&lt;p&gt;また、近年は店頭で販売されるイヤホンの大半がカナル型ですがCARD20はインナーイヤー型です。これは個人によってプラス評価になるかマイナス評価になるかというのはかなり分かれるところですが、左右完全独立型のワイヤレスイヤホンの選択肢はほとんど存在しない(AirPodsとその類似品+αくらい)現状で、カナル型があまり得意ではない私としてはかなり心が惹かれる製品となっています。ウェブ上でさっと調べても、「カナル型ではない点が惜しい」との記述を見ますが、個人的にはカナル型じゃないからこそ、「買い」でした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165405_hu_3a04b9a9b979a851.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;外箱は至ってシンプルで、製品を上面から見た写真が白い箱に印刷されています。蓋と内箱がぴったり吸い付くようなサイズ感で構成された箱、しろい外観、余計な物が書かれていないデザイン、最近流行のデザインともいえますが、Appleっぽさがありますね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165410_hu_38d7e0ba26b7bc4a.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱底面にはケースからだしたイヤホンの写真と、モデル番号をはじめとした一通りのスペックが記載されています。Bluetoothのバージョンは5.0、MakuakeのプロジェクトページによるとQualcomm QCC3020を使用しているようです。TWS Plus対応ということなのですが、ざんねんながらPixel 4はTWS Plusに対応しておらず、あまり恩恵を受けることはなさそうです。&lt;/p&gt;
&lt;p&gt;連続再生時間は約4時間、ケースのバッテリーが約16時間分充電できるようなので、合計で約20時間使用可能とのこと。AVIOT TE-BD21fが約7時間+約18時間の合計約25時間、SONY Xperia Ear Duoが約4時間+約16時間の合計約20時間なので、サイズの割には標準的な使用時間となっているように思えます。&lt;/p&gt;
&lt;p&gt;箱には記載がありませんが、防水性能はIPX4ということなので、少なくとも雨が降る、汗をかく、くらいでは問題がないようです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165445_hu_706ae11d591072b2.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;開封すると直ぐに本体が入っています。注文時にロゴなしバージョンを選択したため、イヤホン本体にはロゴが入っていません。プロジェクトページや箱に描かれていたものよりは深い黒で、光沢感もあまりきつくなく、高級感もありなかなか良い色だとおもいます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165459_hu_cb67b12aedf9dbd7.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165504_hu_3952f150bcf57046.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;表面は天窓設計によりイヤホン本体の一部が見えています。これにより、気づかないうちになくなっていた、ということがなくなるとのことですが、実際はどうなんでしょうか。タッチコントロール対応と言うことで、おそらく銀色の部分をタッチして操作することができるのでしょう。AVIOT TE-BD21fはボタン式で、うまく押さえて操作しないと耳にさらに押し込む形になってしまうという感じだったので、タッチで操作できるのはプラスポイントです。(感度が悪いor良すぎる、ということがなければ)&lt;/p&gt;
&lt;p&gt;裏面には技適をはじめとした各種法令関係のマークとバッテリー容量、電源関連情報、生産国、モデル名などが書かれています。平面に対して垂直に充電ケーブルを挿すのはどうなのか、とおもわなくもないのですが、この薄さなら仕方が無かったのでしょう。充電ケーブルはUSB Type-Cです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165528_hu_dc02e4bab0bc4ff3.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;付属品として説明書と充電ケーブル。ケーブルはUSB Type A to Type Cのそれほど長くない物です。説明書は英語と日本語で記載がありますが、日本語の一部が中国語？になったりしていて微妙に怪しさがあります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165749_hu_e18c0502545b5c59.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;本体ケースを空けるとこんな感じ。空けるときに若干イヤホンに干渉するようで、すこしイヤホンがぐらっとします。取り落としてしまうほどではないのでとくに問題はありませんが、繰り返し開け閉めしていたらすこしイヤホンが傷つくかもしれません。&lt;/p&gt;
&lt;p&gt;YOBYBOロゴとL/Rの文字はエンボス加工というか、すこし周りから浮き出たような処理になっていて、高級感があります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165812_hu_535e1b31fcadfcc3.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;閉じると真ん中が光ります。充電残量の表示でしょうね。多分。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yobybo-card20/images/IMG_20200427_165831_hu_460a3d801c720929.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;イヤホンの内側はこんな感じ。ケースから取り出す際、少し取り出しにくいかも、という印象をうけましたが慣れれば多分大きな問題ではないでしょう。&lt;/p&gt;
&lt;p&gt;充電端子部分に絶縁フィルムがついているので、これを剥がして充電を開始します。&lt;/p&gt;
&lt;p&gt;まだ音楽を再生していないので音や接続の安定度などについてはなにもコメントできないのですが、開封してみての見た目だけでいうならかなり満足度が高い商品となっていると思います。AVIOT TE-BD21fやXperia Ear Duoのケースや本体がプラプラしいのに対して、CARD20はそういった安っぽさはあまり感じられません。&lt;/p&gt;
&lt;p&gt;新型コロナウイルス感染症の影響を受けてリモートワークをしていますから、ワイヤレスのイヤホンを使用する機会が激減してはいるのですが、機を見て使ってレビュー記事でも書けたらな、とはおもっています。&lt;/p&gt;</description></item><item><title>ギョーザ×ラザニア</title><link>https://blog.web-apps.tech/gyolasagna/</link><pubDate>Sun, 19 Apr 2020 06:20:25 +0000</pubDate><guid>https://blog.web-apps.tech/gyolasagna/</guid><description>&lt;blockquote&gt;
&lt;p&gt;ラザニア（単数形: lasagna）あるいはラザニエ（複数形: lasagne）は、イタリアのカンパニア州ナポリの名物である、平たい板状のパスタの一種、またはそれを用いたパスタ料理。 イタリア語の発音ではラザーニャやラザーニェに近い。&lt;/p&gt;
&lt;p&gt;料理の場合は、イタリア語で「オーブンで焼き上げたラザニア」を意味するラザーニャ・アル・フォルノ (lasagna al forno) と呼ぶこともある。深さのある耐熱容器に、ベシャメルソース、ミートソース、ラザニア、チーズを何層か重ね、最上段のベシャメルソースに焼き色がつくようにバターを乗せて、オーブンで焼いたもの。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;餃子、すなわち薄いパスタ(小麦粉なので大体一緒です)と挽肉の集合体にトマトソースとチーズを載せて焼いたら大体ラザニアになりそう、ということで作りました。ベシャメルは面倒なので省略します。適当にホワイトソースを買ってくるとか、フレークタイプのホワイトソースとかを買ってくれば良い感じになる可能性がありますが、家になかったので諦めます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_134830_hu_7dd4a1e8584a8b63.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;我が家には&lt;a href="http://www.mansyu.co.jp/" target="_blank" rel="noopener"&gt;三割うまい!!&lt;/a&gt;
の冷凍餃子が常備されておりますので、これをゆでていきます。お好みによっては焼いても良いかもしれませんが。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_134832-1_hu_7eb933ca763a249d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;玉ねぎが余って(？)いたのでいれようと思い立ち適当に炒めていきます。このあと適当に刻みニンニクを加えて香りを足してみたりしました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_134957_hu_6dd4015dba8c4edf.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;トマトソースはこちらを使います。カルディで買えるもので、結構便利です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_135155_hu_12e170c93bf438a4.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;だばぁ。軽く水分を飛ばしましょう。お好みでなんかハーブとか入れても良いかもしれない。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_135418-1_hu_83ae3232d36e594d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;耐熱皿にゆでた餃子を並べます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_135534_hu_e0d42bf2724e866e.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ソースをかけます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_135710_hu_2f66972bc05383d6.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;チーズ。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_140320_hu_b128f29c78938d12.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;オーブン/オーブントースターで良い感じになるまで焼きます。餃子もソースも予め火を通してるので、チーズが良い感じになればOK。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gyolasagna/images/IMG_20200419_140359_hu_4dc135a798a144fd.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;お好みでバーナリングしましょう。香りが立ってより旨そう感が増します。&lt;/p&gt;
&lt;p&gt;いざ実食。これはまぁラザニア的な物体として十分戦えます。ベシャメルを入れたらもっとラザニアになりそうではありますが、そこまでやるともうそれは普通にラザニアを作った方が良いかもしれません。&lt;/p&gt;</description></item><item><title>アーロンチェア リマスタード</title><link>https://blog.web-apps.tech/aeron-remastered/</link><pubDate>Wed, 15 Apr 2020 09:24:39 +0000</pubDate><guid>https://blog.web-apps.tech/aeron-remastered/</guid><description>&lt;p&gt;諸般あり、オフィスでも使用している、最高の椅子と名高い&lt;a href="https://storesystem.hermanmiller.co.jp/fs/hmjapan/AER1B23DWALPG1G1G1BBBK23103" target="_blank" rel="noopener"&gt;アーロンチェア&lt;/a&gt;
をかなりお安く購入できるという機会を頂戴したので、COVID-19の影響を受けて完全にリモートワークをしていることもあって購入を決意しました。&lt;/p&gt;
&lt;p&gt;おそらくオフィスで使用している物は旧型のアーロンチェアなのですけれども、今回購入したのは(新品なので当然ですが)現行の「アーロン リマスタード」、型番で言うと&lt;code&gt;AER1B23DW ALP G1 G1 G1 BB BK 23103&lt;/code&gt;というものです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/aeron-remastered/images/IMG_20200415_174205_hu_9dfd50408bdb379a.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;注文をして支払いをしてからちょうど一週間で届きました。販売元は&lt;a href="http://www.gregorylyon.com/ja/" target="_blank" rel="noopener"&gt;Gregory Lyon社&lt;/a&gt;
で、アーロンチェアをはじめとするハーマンミラーのオフィシャルディーラーです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/aeron-remastered/images/IMG_20200415_174326_hu_4660b91f7812b898.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱には取り扱いや持ち上げる際は二人でやりなさい、との注意書き。重いからとのことではありますが、重さよりも大きさがやばくて、我が家の階段(我が家は一階に玄関があり、内階段を上って二階が居住スペースという構成)は幅がぴったりで、手すりの上を通さないとだめでした。購入を検討している方は要注意。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/aeron-remastered/images/IMG_20200415_174434_hu_3d3e7072e353e6a9.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱を空けると中から箱が。これは多分スペーサーですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/aeron-remastered/images/IMG_20200415_174522_hu_231b171d9e38028c.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;外箱は下部が空いていて、上からスポッと取り外すことができます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/aeron-remastered/images/IMG_20200415_174608_hu_2cc93772f073eb71.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ご対面！！！そうそう、これですこれ。うひょー。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/aeron-remastered/images/IMG_20200415_174622-2_hu_bbf454f4e3157b66.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;説明書が座席下のノブにかかってました。特に結ばれているとかいう訳ではなく、棒状の物に引っかかっているだけなので、はさみとかも必要無く取り外すことができます。むしろ配送途中に取れなかったのがすごい。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/aeron-remastered/images/IMG_20200415_175459-1_hu_6f6a1aaddf7c6c4.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;デスクに合わせるとこんな感じに。机の上があまりきれいではないのはご愛敬と言うことで・・・&lt;/p&gt;
&lt;p&gt;ちなみにこれまで使っていた椅子は&lt;a href="https://www.nitori-net.jp/ec/product/6620573s/" target="_blank" rel="noopener"&gt;ニトリのリカルドPUブレスレザーBK&lt;/a&gt;
でした。これはこれでなかなか良い椅子だったので、ちょっと手放すのが惜しい、という気持ちがしています。スペースはあるし、とりあえず置いておいても良いかな・・・
ゲームするときとか、本読むときはふかふかしてる方が嬉しいですね。&lt;/p&gt;
&lt;p&gt;アーロンチェアは基本的に保証が12年なので、長いお付き合いになる見込みです。よろしく。&lt;/p&gt;</description></item><item><title>2020年3月時点での自宅機材・消耗品類まとめ</title><link>https://blog.web-apps.tech/2020-april-goods/</link><pubDate>Sun, 12 Apr 2020 10:05:44 +0000</pubDate><guid>https://blog.web-apps.tech/2020-april-goods/</guid><description>&lt;p&gt;自分用のメモみたいなものですが、現時点(2020-04-12)で自宅で使用している家電や道具、消耗品類などをまとめてみます。&lt;/p&gt;
&lt;h2 id="家電類"&gt;家電類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;冷蔵庫: &lt;a href="https://jp.sharp/reizo/products/sjgw35c.html" target="_blank" rel="noopener"&gt;SHARP SJ-GW35C&lt;/a&gt;
。2016年製、幅60cm、定格内容積350L。&lt;/li&gt;
&lt;li&gt;食器洗い乾燥機: &lt;a href="https://panasonic.jp/dish/p-db/NP-TH1.html" target="_blank" rel="noopener"&gt;Panasonic NP-TH1&lt;/a&gt;
。2018年製、幅550mm×奥行344mm×高さ598mm、庫内容量が約50L。後継機がNP-TH2, NP-TH3と出ているためすでに生産終了ではあるが、それほど大きな変更はない模様(小物ホルダーがついたり、庫内の棚の仕様が変わったり、というマイナーチェンジくらい？)。&lt;/li&gt;
&lt;li&gt;洗濯乾燥機: &lt;a href="https://www.toshiba-lifestyle.co.jp/living/laundries/tw_127x7/" target="_blank" rel="noopener"&gt;TOSHIBA TW-127X7R&lt;/a&gt;
。2019年製。洗濯脱水容量が12kg、洗濯乾燥容量が7kgで、2019年8月時点では業界トップクラスの洗濯容量、業界最大の乾燥容量だったらしい(今はどうか、については調べていないので知らない)。操作がタッチパネルなのはちょっと特徴的かも。残念ながら洗剤等の自動投入機能はついていないが、後述の様にプッシュ式の(はかる必要の無い)洗剤を使用しているため不便はない。&lt;/li&gt;
&lt;li&gt;炊飯器: &lt;a href="https://www.tiger.jp/product/ricecooker/JPH-A.html?productId=JPH-A" target="_blank" rel="noopener"&gt;TIGER JPH-A100&lt;/a&gt;
。2017年製を型落ちで買ったので大分安く買えた記憶がある。最近釜を欠けさせてしまったので買い換えたいが、釜だけでも2万以上するのでためらっている。&lt;/li&gt;
&lt;li&gt;オーブンレンジ: SHARP RE-SS8D。2016年製で、すでに公式ページなし。所謂過熱水蒸気オーブンレンジ、というジャンルに当たる物っぽい。庫内容量23L。&lt;/li&gt;
&lt;li&gt;ミキサー: &lt;a href="https://www.t-fal.co.jp/products/cooking-appliances/blenders/mix_and_drink_red/" target="_blank" rel="noopener"&gt;T-fal ミックス＆ドリンク&lt;/a&gt;
。定格消費電量300W、最高容量600ml。特に不満なし。&lt;/li&gt;
&lt;li&gt;スロークッカー: &lt;a href="https://www.twinbird.jp/products/epd819.html" target="_blank" rel="noopener"&gt;TWINBIRD EP-D819W&lt;/a&gt;
。たまに作る煮物に便利。&lt;/li&gt;
&lt;li&gt;エスプレッソメーカー: NESPRESSO U。すでに公式ページがなくなっている模様。製造年は不明・・・。水のタンクを右側に置いたり左側に置いたり奥に置いたりできる変わったマシン。現行の低価格帯マシンだとリストレット(25ml)が選択できないけど、本機は対応。牛乳で割ることがほとんどなので、あまり薄くならないので嬉しい。&lt;/li&gt;
&lt;li&gt;コーヒーメーカー: &lt;a href="https://www.tiger.jp/product/coffeemaker/ACX-S060.html?productId=ACX-S060" target="_blank" rel="noopener"&gt;TIGER ACX-S060&lt;/a&gt;
。大学生の、それも割と早い時期に買ったやつなので、もう結構な年数使っている気がする。定価は6000円だけど、購入時はセールかなんかで2000円くらいで買った記憶がある。サーバーがステンレスなので割る心配がないというのが嬉しいところ。&lt;/li&gt;
&lt;li&gt;低温調理器: &lt;a href="https://anovaculinary.com/?lang=ja" target="_blank" rel="noopener"&gt;ANOVA&lt;/a&gt;
。Wi-Fiなしの2014モデル(多分2018年製とかそれくらいの奴)。&lt;/li&gt;
&lt;li&gt;加湿空気洗浄機: &lt;a href="https://jp.sharp/kuusei/products/kcg50.html" target="_blank" rel="noopener"&gt;SHARP KC-G50&lt;/a&gt;
。所謂気化式のもの。&lt;/li&gt;
&lt;li&gt;掃除機: &lt;a href="https://www.dyson.co.jp/dyson-vacuums/cordless/dyson-v10/%e3%82%b7%e3%83%aa%e3%83%bc%e3%82%ba%e4%b8%80%e8%a6%a7.aspx" target="_blank" rel="noopener"&gt;Dyson Cyclone V10 fFluffy&lt;/a&gt;
。言わずもがな。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="キッチンウェア"&gt;キッチンウェア&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;鍋類: &lt;a href="https://www.t-fal.co.jp/products/pots-pans/stackable/ingenio_grand_bleu_premier/" target="_blank" rel="noopener"&gt;T-fal インジニオ・ネオ グランブルー・プレミア(セット10)&lt;/a&gt;
を基本に、ニトリの鍋やIKEAのフライパン、就職祝いでもらった圧力鍋などを適当に使っている。&lt;a href="https://blog.web-apps.tech/birthday-paella/"&gt;最近なぜかパエリアパンが仲間に加わった&lt;/a&gt;
。IKEAの激安(300円くらい)フライパンはクソ便利だったのに、ラインナップからなくなってしまって悲しい。&lt;/li&gt;
&lt;li&gt;計量カップ: &lt;a href="https://www.oxojapan.com/products/cooking-baking-34/measuring/angled-measuring-cup-2-cup" target="_blank" rel="noopener"&gt;OXO アングルドメジャーカップ(中)&lt;/a&gt;
。まぁそんなに真面目にはからないので、500mlの水が入るカップ、位の使われ方をしている。不憫。&lt;/li&gt;
&lt;li&gt;ゴムべら: &lt;a href="https://www.oxojapan.com/products/cooking-baking-34/silicone-nylon-cooking-tools/medium-silicone-spatula#raspberry" target="_blank" rel="noopener"&gt;OXO シリコンスパチュラ M&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;まな板: &lt;a href="https://www.kitchentime.jp/products/detail/4" target="_blank" rel="noopener"&gt;アサヒ クッキンカット&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;包丁: &lt;a href="https://tsubaya.co.jp/?pid=107802071" target="_blank" rel="noopener"&gt;三徳(火造り 三徳)&lt;/a&gt;
と&lt;a href="https://tsubaya.co.jp/?pid=107802057" target="_blank" rel="noopener"&gt;ペティ(槌目MV鋼強化木 ペティ)&lt;/a&gt;
を使っている。いずれも合羽橋 つば屋さんのもの。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="消耗品類"&gt;消耗品類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;食器洗い用洗剤: &lt;a href="https://www.myrepi.com/home/cleaning/joy-geltab" target="_blank" rel="noopener"&gt;JOY GELTAB&lt;/a&gt;
。洗浄力の高い粉末洗剤と油汚れにききやすいジェルが一つにまとめられたタイプのすごいやつ。コスパより性能重視。Amazonでセールのときはだいたいこれの超特大サイズというやつが割引されてお得なので、セールの度に追加購入するとだいたい良いペース。&lt;/li&gt;
&lt;li&gt;衣類用洗剤: &lt;a href="https://www.kao.co.jp/attack/products/zero/" target="_blank" rel="noopener"&gt;アタック ZERO ドラム式専用&lt;/a&gt;
。プッシュタイプの容器で、軽量がすごく簡単。&lt;/li&gt;
&lt;li&gt;衣類用柔軟剤(1): &lt;a href="https://www.kao.co.jp/flair-fragrance/lineup/" target="_blank" rel="noopener"&gt;フレアフレグランス ドレッシーベリーの香り&lt;/a&gt;
。特に深い理由はないけど、安かったときに一度買ってから、これもamazonのセールで安くなりがちなので継続して使っている。匂いは結構強め。&lt;/li&gt;
&lt;li&gt;衣類用柔軟剤(2): &lt;a href="https://www.kao.co.jp/humming/linne/" target="_blank" rel="noopener"&gt;ハミング LINNE 無香性&lt;/a&gt;
。前述のフレアフレグランスは結構香りが強くて、バスタオルに使うとちょっと微妙な感じだったのでバスタオルを洗うときはこっちを使う。&lt;/li&gt;
&lt;li&gt;手洗い石けん: ミューズノータッチ泡ハンドソープ 香りが残らないキッチン用。amazonの2月のセールで安かったので、前々から使いたいと思っていたノータッチタイプの物にした。料理中に手を洗っても香りが残らないタイプで、料理を結構する人間には結構お勧め。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pc周辺機器類"&gt;PC/周辺機器類&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PC: &lt;a href="https://www.apple.com/jp/macbook-pro-13/" target="_blank" rel="noopener"&gt;MacBook Pro 13inch&lt;/a&gt;
。2018年のモデルで、Core i7 4コア 2.7GHz、16GB RAM、256GB SSDの構成。エンジニアが使うマシンとしては良くある構成だし、特に言うことはない。&lt;/li&gt;
&lt;li&gt;タブレット: &lt;a href="https://www.apple.com/jp/ipad-pro/" target="_blank" rel="noopener"&gt;iPad Pro 11inch&lt;/a&gt;
+ &lt;a href="https://www.apple.com/jp/apple-pencil/" target="_blank" rel="noopener"&gt;Apple Pencil&lt;/a&gt;
。絵を描きたくて買った。が、あんまり活用できていない。最近は&lt;a href="https://twitter.com/search?q=from%3A%40nasa9084%20%23posemaniacs&amp;amp;src=typed_query" target="_blank" rel="noopener"&gt;#posemaniacs&lt;/a&gt;
描いてるけど、へた。&lt;/li&gt;
&lt;li&gt;スマートフォン: &lt;a href="https://store.google.com/jp/product/pixel_4" target="_blank" rel="noopener"&gt;Pixel 4&lt;/a&gt;
。モバイルPASMO使いたいけど、PASMO一体型クレジットカードではオートチャージができないらしく、おこ。&lt;/li&gt;
&lt;li&gt;モニタ: &lt;a href="https://www.lg.com/jp/monitor/lg-27UK850-W" target="_blank" rel="noopener"&gt;LG 27UK-850-W&lt;/a&gt;
。USB-PD対応の4Kモニタがほしくて購入したもの。DP OUTはついていない。amazonでめっちゃ安かったのでこれにした。&lt;a href="https://www8.hp.com/jp/ja/monitors/product-details/4285255" target="_blank" rel="noopener"&gt;HPのシングルモニターアーム&lt;/a&gt;
(エルゴトロンのOEM)と合わせて使用している。&lt;/li&gt;
&lt;li&gt;プリンタ: &lt;a href="https://jpn.nec.com/printer/laser/color/5600c/index.html" target="_blank" rel="noopener"&gt;NEC MultiWriter 5600C&lt;/a&gt;
。A4カラーページレーザープリンタで、AmazonだったかNTT-Xだったか、まぁその辺で激安だったので購入した。基本的に写真を印刷することがないので、インクジェットインクジェットより使いやすい(気がする)。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Bauhutteのデスクごとチェアマットを購入した</title><link>https://blog.web-apps.tech/bauhutte-chairmat/</link><pubDate>Fri, 10 Apr 2020 15:44:39 +0000</pubDate><guid>https://blog.web-apps.tech/bauhutte-chairmat/</guid><description>&lt;p&gt;昨今の情勢を受け、私もかれこれ一ヶ月以上自宅でリモートワークをしています。自宅でリモートワークをするということは、机に向かう、すなわち椅子に座る時間が圧倒的に増える(一日あたり8時間くらい増えていますね)ことになるわけです。弊宅は賃貸かつ床が(多分)木製のフローリングで、長時間椅子に座るとなると椅子のキャスターによる床の傷つきがきになります。&lt;/p&gt;
&lt;p&gt;なにかチェアマットを敷いた方がよかろう、結構椅子を動かすタイプの人間であるからして大きめの物を選ぶべきであろう、という判断の下、大きく、見目もよろしそうであった&lt;a href="https://amzn.to/2XopY5x" target="_blank" rel="noopener"&gt;Bauhutteのデスクごとチェアマット(160cmx130cm)&lt;/a&gt;
を購入しました。&lt;/p&gt;
&lt;iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=nasa9084-22&amp;language=ja_JP&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=as_ss_li_til&amp;asins=B01N9AYNP1&amp;linkId=f43dedb3463d9ba5eb51866fe66f4925"&gt;&lt;/iframe&gt;
&lt;p&gt;なおamazonのリンクをはってはいる物の、たまたま楽天のポイントが貯まっていたので楽天で購入しました。&lt;/p&gt;
&lt;p&gt;届いてみて、確かにこれは大きい。なかなか良いサイズだ、と思ったのですが、さて敷いてみよう、とすると幅がなんとも惜しい感じでありました(これは我が家のデスクとの相性、という話で商品自体が悪いわけではないので注意)。
机はニトリの&lt;a href="https://www.nitori-net.jp/ec/cat/TableChair/CombinationFreeTable/1/" target="_blank" rel="noopener"&gt;組み合わせデスク&lt;/a&gt;
、&lt;a href="https://www.nitori-net.jp/ec/product/6240121s/" target="_blank" rel="noopener"&gt;幅140cmの天板&lt;/a&gt;
に&lt;a href="https://www.nitori-net.jp/ec/product/6240134s/" target="_blank" rel="noopener"&gt;特に何の変哲も無い脚&lt;/a&gt;
を付けて使っていますが、左脚の外側から右脚の外側までが約135cm、左足の内側から右脚の内側までが約125cmなので、完全に両脚で踏ませることも、内側に収めることもできない、かといって長辺を横向きにすると長すぎるという程度の幅です。
前述の様になかなか大きいサイズ、長辺が160ありますから、きれいにカットするのもなかなか困難です。&lt;/p&gt;
&lt;p&gt;厚さが1.5mmですから、まぁそれ自体はたいした問題ではないのですが、裏面の滑り止めがくせ者です。確かに滑らないのですが、表面もなかなかグリップ力があるせいか、座った状態で椅子を動かすとマットが波打ち、机の脚のところで引っかかって、机がギシギシ言うのです。&lt;/p&gt;
&lt;p&gt;これはちょっとなんとかしたい、と思いチェアマット用の滑り止めを別途amazonで物色中です。
また、来週新しい椅子が届く予定なので、椅子が変わったらまた違うのかもしれない、とは思っています。&lt;/p&gt;
&lt;p&gt;総じて、現状としては「惜しい」という評価をするしかないのですが、机の幅などの条件が折り合えば、商品の見た目やさわり心地などはなかなか悪くないと思いますので、チェアマットを探している方は検討してみてはいかがでしょうか。&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;2020-04-11 追記&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.nitori-net.jp/ec/product/7160152s/" target="_blank" rel="noopener"&gt;ニトリのすべり止めテープ&lt;/a&gt;
を貼ったところ、改善しました。三辺(長辺x1、短辺x2)に貼ると長さ4メートルのテープをちょうど良い具合に使い切る感じです。
現状は机の脚の一本だけチェアマットにのっている状態で、のっている側の長辺と前後の短辺にすべり止めテープを貼っています。全くギシギシ言わなくなったので、大変良いですね。&lt;/p&gt;
&lt;p&gt;2020-05-01追記&lt;/p&gt;
&lt;p&gt;裏面の滑り止め加工が裏目に出たのか、ニトリの滑り止めテープが剥がれてきました。つらい。&lt;/p&gt;</description></item><item><title>誕生日パエリア</title><link>https://blog.web-apps.tech/birthday-paella/</link><pubDate>Wed, 08 Apr 2020 15:38:24 +0000</pubDate><guid>https://blog.web-apps.tech/birthday-paella/</guid><description>&lt;p&gt;先日、無事誕生日なるものを今年も迎えることができたのですが、twitterやらfacebookやらに&lt;a href="https://www.amazon.jp/hz/wishlist/ls/901D5E6QYC2X?ref_=wl_share" target="_blank" rel="noopener"&gt;欲しいものリスト&lt;/a&gt;
を貼った結果、皆様いろいろと贈ってくださり、本当にありがとうございます。&lt;/p&gt;
&lt;p&gt;ところで、欲しいものリストにパエリアパンなど入れていなかったのですが、なぜか届きました。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;家広そうだし入って無くても送ってみっかと思ってポチってみた?&lt;/p&gt;&amp;mdash; TᗩKᑌᗰI KOᗷᗩYᗩᔕᕼI (@chamaharun) &lt;a href="https://twitter.com/chamaharun/status/1247704520060063745?ref_src=twsrc%5Etfw"&gt;April 8, 2020&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;全く以て意味がわからないですね。しかし贈ってくれたのに使わない、というのもなんなので、パエリアを作ることにしました。&lt;/p&gt;
&lt;p&gt;なお誕生日パエリアというタイトルですが、今日誕生日、というわけではありません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_195036_hu_f5edc3a92385f7af.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;材料はこちら。アサリ小パック、パプリカ一つ、鶏肉一枚、エビ、イカ、トマト、米、サフラン、玉ねぎ、ニンニク。
鶏肉は一口大に切って軽く塩こしょうしてあります。
玉ねぎとニンニクはみじん切りしておきましょう。
また、アサリは砂抜きをしました(が、食べたらガリッといった。なんでや。)
トマト、パプリカは適当に切りましょう。
イカはカット済みのものを買いました。&lt;/p&gt;
&lt;p&gt;ちなみにこの中で一番高かったのは(多分)サフランです。サフラン高い。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_195341_hu_12d2769449a9587c.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;こちらが件のパエリアパンです。四人前作れるらしい。大きくて端の方に火が入りにくいのではないかと心配です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_195709_hu_2b551104b35a42a9.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;さび止めの油が塗ってあるらしいのでそれを飛ばした後、オリーブオイルを適当に熱して、肉やら魚介やらを炒めます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_200651_hu_afe99af707f217a7.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;火が通ったものから一旦どけておきます。特にアサリは火を通しすぎると縮んでしまうので、開いた時点でどけておいた方がいいでしょう。多分。
なんかすでにパエリアの匂いがする気がしてきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_200842_hu_722600c0dc4a1e10.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;追いオリーブオイルをして、玉ねぎとニンニクを炒めます。ちょっと焦げ付いている？ようなところはこそいでおいた方が良いでしょう。多分これがうま味ってやつです。多分。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_200913_hu_5a4a5c1e946ef2bc.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;玉ねぎがしなっとしてきたら、生米を突っ込んで炒めます。大きいのでフライパンの様に振ることはできません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_201332_hu_9158dc12ac5ddc36.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;どんな状態になったら米に火が通ってきた、といえるのかはよくわかんないんですけど、それっぽい感じになったら水とコンソメ、サフランを加えて一煮立ちさせます。
コンソメは多分予めお湯か何かで溶いておくか、顆粒のものを使った方が良かった気がする。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_201553_MP_hu_74fb6e5b18b5cd0a.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;煮立ったらパプリカを入れます。インゲンを入れたい人はここで入れましょう。&lt;/p&gt;
&lt;p&gt;トマトさんを入れるタイミングがわからなかったので、「パプリカと同じ赤だしいけるっしょー」とここで投入。まぁ大丈夫。赤いし。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_201812_hu_feb4758cb13d525b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;少しぐつぐつさせた後、よけておいた肉やら魚介やらを再投入します。これもタイミングが不明だったので気分で入れました。だいたいなんとかなる。&lt;/p&gt;
&lt;p&gt;この状態で十分ほど強火で煮込みます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_202849_MP_hu_d0de1a02bd9ddde.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;十分経ったら弱火にして、水がなくなるというか、どろっとした感じになるまで煮ます。これもなんとなく雰囲気で。多分やり過ぎると焦げる。&lt;/p&gt;
&lt;p&gt;良い感じになったら火を止めて、適当なアルミホイルとかで蓋をして(できてない)五分ほど蒸らします。結構これで雰囲気変わるんで大事。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_203457_MP_hu_39eb71783e602c02.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;五分経つとこんな感じで汁っ気が飛びます。マジで。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/birthday-paella/images/IMG_20200408_203758_hu_f6fc4392d16c2714.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;最後によしなにパセリングして完成。うまいです。あと簡単。
魚介とかサフランとかそこそこするので、結構自炊ものとしてはお高めだけど、まぁ一回くらいやってみても良いんじゃないでしょうか。
なお二人で四人前は多いです。注意。&lt;/p&gt;</description></item><item><title>context.WithTimeoutに0を与えるとどうなるのか</title><link>https://blog.web-apps.tech/context-withtimeout-with-zero/</link><pubDate>Wed, 08 Apr 2020 04:17:35 +0000</pubDate><guid>https://blog.web-apps.tech/context-withtimeout-with-zero/</guid><description>&lt;p&gt;当然と言えば当然なんですけど、特に &lt;code&gt;panic&lt;/code&gt; とかそういうことはなく、一瞬でタイムアウトします。まぁ、どうと言うことは無いですが、設定ファイルとかで未定義時に0が来るような実装になっている場合はなんか処理する(0の時は処理をしない、というのは多分あんまりなさそうですし)必要がありますね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;timeout&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;a href="https://play.golang.org/p/63DkfIEImjv" target="_blank" rel="noopener"&gt;https://play.golang.org/p/63DkfIEImjv&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="もうちょっと細かい話"&gt;もうちょっと細かい話&lt;/h2&gt;
&lt;p&gt;さすがに短すぎるので、もう少し細かい実装の話。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;context.WithTimeout&lt;/code&gt;は内部的には特別な実装は無くて、&lt;code&gt;context.WithDeadline&lt;/code&gt;を&lt;code&gt;time.Now.Add(timeout)&lt;/code&gt;に対して呼んでいます。&lt;/p&gt;
&lt;p&gt;で、&lt;code&gt;context.WithDeadline&lt;/code&gt;は返値を返す前に&lt;code&gt;time.Until&lt;/code&gt;を使って現在時刻とデッドラインまでの差分をチェックしていて、これが0以下なら&lt;a href="https://github.com/golang/go/blob/go1.14.1/src/context/context.go#L437-L439" target="_blank" rel="noopener"&gt;その場でキャンセル関数を呼んで&lt;/a&gt;
います。&lt;/p&gt;
&lt;p&gt;まぁそんなわけで、余分な待ち時間が発生することもなく、&lt;code&gt;time.WithTimeout&lt;/code&gt;を呼んだ時点でちゃんとタイムアウトされる、ということでした。ちゃんちゃん。&lt;/p&gt;</description></item><item><title>Goで(メールサーバを用意せずに)メールを送る</title><link>https://blog.web-apps.tech/go-smtp-sendmail-without-mailserver/</link><pubDate>Mon, 06 Apr 2020 10:13:42 +0000</pubDate><guid>https://blog.web-apps.tech/go-smtp-sendmail-without-mailserver/</guid><description>&lt;p&gt;単純な興味というか、特にこれで何かを作るというわけではないのだけれど、ふと思い立って調べてみたら意外と情報が無かったのでメモを残しておきます。&lt;/p&gt;
&lt;p&gt;Goでメールを送りたい、と思ったとき、Googleで検索してみると、&lt;a href="https://pkg.go.dev/net/smtp" target="_blank" rel="noopener"&gt;net/smtp&lt;/a&gt;
パッケージを使ってgmailのSMTPサーバを使用する、とかSendGridを使用する、とかそういった例ばかりが目につきました。これらはもちろん便利であることは疑いようもない(自前でメールサーバの管理とかやってられないし)んですけど、こういったSMTPサーバやらsendmail/postfixやらを使わなくても、本来SMTPではメールを簡単に送れるはず(なんと言っても「Simple Mail Transfer Protocol」ですから)、と思いました。
とはいえじゃぁどうしたら良いのか、と思ったとき、Goを用いた例というのはぱっと見当たらないのです。仕方ないのでtelnetを使用した例を見ながら、telnetでどうやれば自分のgmail宛てにメールが送れるのか、というのを試しました。&lt;/p&gt;
&lt;p&gt;具体的な手順というのは、次の様なものです。なお、以下の手順では(macにtelnetが入っておらずインストールして環境がごちゃごちゃするのも面倒だったので)centos:7のDockerコンテナを使用しています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;# nslookup -type=mx gmail.com
Server: 192.168.65.1
Address: 192.168.65.1#53
Non-authoritative answer:
gmail.com mail exchanger = 20 alt2.gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 10 alt1.gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 40 alt4.gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 5 gmail-smtp-in.l.google.com.
gmail.com mail exchanger = 30 alt3.gmail-smtp-in.l.google.com.
Authoritative answers can be found from:
# telnet gmail-smtp-in.l.google.com 25
Trying 74.125.204.26...
Connected to gmail-smtp-in.l.google.com.
Escape character is &amp;#39;^]&amp;#39;.
220 mx.google.com ESMTP 6si12301456pjb.7 - gsmtp
HELO smtp.gmail.com
250 mx.google.com at your service
MAIL FROM:&amp;lt;nasa9084@example.com&amp;gt;
250 2.1.0 OK 6si12301456pjb.7 - gsmtp
RCPT TO:&amp;lt;XXXXXXXXXX@gmail.com&amp;gt;
250 2.1.5 OK 6si12301456pjb.7 - gsmtp
DATA
354 Go ahead 6si12301456pjb.7 - gsmtp
Subject: Test via telnet
From: nasa9084
To: nasa9084.gmail
Hello, world
.
250 2.0.0 OK 1586166529 6si12301456pjb.7 - gsmtp
QUIT
221 2.0.0 closing connection 6si12301456pjb.7 - gsmtp
Connection closed by foreign host.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;無事自分のgmailアカウントにメールが届きました。この手順をGoでやってみます。&lt;/p&gt;</description></item><item><title>Anker SoundCore Motion B</title><link>https://blog.web-apps.tech/anker-soundcore-motionb/</link><pubDate>Wed, 01 Apr 2020 17:05:46 +0000</pubDate><guid>https://blog.web-apps.tech/anker-soundcore-motionb/</guid><description>&lt;p&gt;自宅では(も)職場と同じくMacBook Pro 13inchを使っていて、デスクに向かうときはLGの4Kモニタをクラムシェルモード、USB type-C接続で使っているんですが、まぁ普通モニタのスピーカーというのはあまりいい音はしません。まぁ、おまけみたいなものなので仕方ないんですけど。そんなわけでモニタからは音を出さず、音はPCのスピーカーから出してました。&lt;/p&gt;
&lt;p&gt;私は基本的にあまりPCで音楽を聴く、ということはしない人間なので、特にそれでも不満はないままここまで来たんですけど、先月から新型コロナウイルス感染症(COVID-19)流行のあおりを受けてヘイシャでもリモートワークで仕事をする、という形になりました。
そうすると、これまでは帰宅後食事やら風呂やら、の後くらいから寝るまでしか自宅ではPCに向かっていなかったのが一気に一日中へと伸びました。ミーティングの類いもzoomで行うことになり、これを機にスピーカーでも買おうかな、なんて思っていたところ、Ankerが&lt;a href="https://www.ankerjapan.com/category/REMOTEWORKING/" target="_blank" rel="noopener"&gt;リモートワーク特集&lt;/a&gt;
でいくつかの商品(元々は4種類か5種類くらい対象商品があったんですけど、売り切れたのか現在は3種類になってますね)が半額、その中にBluetoothスピーカーもある、という話を聞きまして、購入に踏み切りました。&lt;/p&gt;
&lt;p&gt;今回購入したのは&lt;a href="https://www.ankerjapan.com/item/A3109.html" target="_blank" rel="noopener"&gt;SoundCore Motion B&lt;/a&gt;
という商品です。一年半位前に発売された商品で、Bluetooth接続、IPX7規格の防水性能、最大12時間連続再生可能なバッテリーというのが売りの商品です。
また、こちらの商品は二台を一台のPCにつなぐことで二台で一つのステレオとして使用できる(わかりにくい)という機能もあります。
せっかく半額なのだし、二台買っても一台分、二台でつなぐとどんな感じなのかもちょっとやってみたい、ということで二台購入しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165119-1_hu_8db4e79e9ce60051.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;届いた商品がこちら。Ankerらしく、小柄なパッケージです。発送はAmazonが代行しているようで、Amazon Japanからの荷物として届きました(が、箱はAmazonの箱ではありませんでした)。輸送用の段ボール箱も小さめだったため、一瞬「二個頼んだよな・・・？」と不安になりましたが、ちゃんと二個入ってました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165158_hu_2ddd73de48b4592.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱の上面には商品の売りと内容物が書いてあります。内容物が少なすぎて、左側のWhat&amp;rsquo;s In The Boxと右側の内容物の間が開きすぎていて戸惑います。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165205_hu_9bb76e544a5375df.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165210_hu_d28dfd0d54b52368.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;側面。完全防水と12時間再生、との記載があります。完全防水とのことですけど、仕様としてはIPX7なので、防水特性としては1mの水深に30分浸かってもOK、という感じですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165300_hu_31f4d0513254462b.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;箱下部のテープ(?)を剥がして開封。飾り気のない白い箱が姿を現します。
右側にプルタブ(?)があるので、付属品がはいっている箱で蓋されている、という状態ですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165305_hu_6787847f353dd7a6.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;白い箱を取り出すと、本体が姿を現します。充電器とかと同じく、薄い袋に入っています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165358_hu_4ca8b1ced2fb8736.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;内容品を取り出した様子。おなじみHappy? Not Happy?の紙とUser Manual、充電ケーブルが入っていました。充電ケーブルはMicro USB Micro-Bです。User Manualはちゃんと各国語で書かれています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/IMG_20200401_165601_hu_d2609621a2da4372.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;二台積んだ様子。わかりにくいですけど、上部にボタンがついています。これに充電ケーブルを挿して、左右で使用します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/----------2020-04-02-1.59.33_hu_dc04ae28a9e8818f.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ステレオで接続する場合はまず両方のスピーカーを起動し、ステレオモードにします。スピーカー同士がつながった後(状態変化がわかりにくい・・・)、PCに接続します。
PC側の表示は一台分として表示されます。二台バラバラに管理する必要はない、ということですね。&lt;/p&gt;
&lt;p&gt;で、肝心の音ですが、もちろんモニタやPC本体の音より圧倒的に良いと思います。スピーカーとしての音質がすごく良いかというと、まぁBluetoothの時点でそこそこ、という感じだと思いますが、私としては特に問題ない音質です。
きちんと右、左から別々に音が出ていて、センターの音はセンターあたりから聞こえている様な気がします。
パッケージにもBig Soundと記載がありましたが、音量は大きめだと思います。
音量設定を下記スクリーンショットくらいに設定していますが、MBPのスピーカーで音量をバーの真ん中位に設定したときと同じくらいの音量がでています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anker-soundcore-motionb/images/----------2020-04-02-11.58.46_hu_55d49f9fd55c6ac7.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;まぁみんながみんな二台買うのがいいかというと、それはよくわかんないですけど、すごく高いものという訳でもないので、そこそこのPC用スピーカーを探している、というかたはこれを機に二台えいっと買ってみても良いのではないでしょうか。&lt;/p&gt;</description></item><item><title>サーモンをAnovaでやる</title><link>https://blog.web-apps.tech/salmon-sous-vide-miso/</link><pubDate>Tue, 03 Mar 2020 05:30:29 +0000</pubDate><guid>https://blog.web-apps.tech/salmon-sous-vide-miso/</guid><description>&lt;p&gt;昨晩の晩ご飯として、サーモンを低温調理でやりましたので、記録に残しておきます。
なお、使用したサーモンは刺身用のサーモンを使用しています。多分刺身用じゃなくても良いとは思うんですが、ちょっと怖かったので。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_204342_hu_3c7119b2b2b88ea9.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;使用するサーモンはこちら。近所の西友で割引になっていたもので、300g前後で600円弱だった気がします。二人分です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_204558_hu_8b10d411027d1041.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;水気を適当に拭いた後、半分にざっくりと切ってステンレスのトレー？バット？に置きます。実家にはバットというものは存在しなかったんですが、使ってみると非常に便利です。100均でも売っているので、適当に数枚そろえておくとなんだかんだ重宝します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_204632_hu_479c60fd31d3c2e9.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_204720_hu_242b9a9d23fdc19f.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;塩と水と砂糖を何やら混ぜ合わせたものに浸します。細かい分量はオライリーさんの「&lt;a href="https://amzn.to/2TBYdTw" target="_blank" rel="noopener"&gt;家庭の低温調理&lt;/a&gt;
」を参照してください。なお、私は紙の本を買いましたが、電子書籍で買ってiPadかなんかに表示しながら調理するのがおすすめです。結構厚い本なので、とにかく取り回しがしにくいので。&lt;/p&gt;
&lt;p&gt;我が家のバットでは若干サーモンが液体から出てしまうので、キッチンペーパー的なものに液体をしみこませて上からかぶせておきました。この状態で20分ほど放置します。&lt;/p&gt;
&lt;iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=nasa9084-22&amp;language=ja_JP&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=as_ss_li_til&amp;asins=487311862X&amp;linkId=3e70bc4098a26c187997b670ad6c567e"&gt;&lt;/iframe&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_204836_MP_hu_64b0d0a0930c6abe.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;その間に水槽(というかバケツですけど)を暖めておきます。今回は52度でやります。水道から普通にお湯(できれば少し温度設定をあげたもの)をためるとあたため時間が短縮できます。多分。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_212521_hu_30fd9e7ff734075e.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;20分経過したものがこちら。あんまり見た目は変わってない気がします。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_212747_hu_e42053cceaaccf43.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;流水でさっと洗って余分な塩気を落とし、ペーパーで水分をとります。なんか筋がピロピロしててキモい。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_212959_hu_f4fa9d6f6d72765.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;キャノーラ油をまんべんなくまぶし、ジッパーつきの袋に投入します。写真のものはIKEAの袋です。まだ袋の口は閉じていません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_213158_hu_139bd6156e5d7fe.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;いわゆる水圧法で空気を抜き、袋の口を閉じて52度で20分やります。あたためている間にソースを作ったりするのですが、昨日はパスタを作ったりもしたので、結局40分くらい放置してしまいました。「家庭の低温調理」には30分までと書いてあったのですが、まぁ40分でも大丈夫です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/salmon-sous-vide-miso/images/IMG_20200302_222037_hu_e269d4fb4e6f4505.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ソース単体の写真は取り忘れてしまったんですけど、味噌とディジョンマスタード、蜂蜜、レモン汁、すりおろした生姜、ごま油とキャノーラ油をよしなに混ぜたモノです。適当にスプーンで混ぜても案外ちゃんと乳化するもんですね。&lt;/p&gt;
&lt;p&gt;ソースをかけた後七味をかけていますが、買ってから大分たった七味なので、辛みも香りも何もない物体になってしまっていました。&lt;/p&gt;
&lt;p&gt;おいしかったです。まる。&lt;/p&gt;</description></item><item><title>emacs/lsp-mode + goplsでGo用のLSP環境を設定する</title><link>https://blog.web-apps.tech/lsp-mode-with-gopls/</link><pubDate>Fri, 07 Feb 2020 08:19:29 +0000</pubDate><guid>https://blog.web-apps.tech/lsp-mode-with-gopls/</guid><description>&lt;p&gt;&lt;a href="https://microsoft.github.io/language-server-protocol/" target="_blank" rel="noopener"&gt;Language Server Protocol&lt;/a&gt;
(以下LSP)はこれまでエディタ/IDEが独自に実装する必要があった、補完や定義参照、静的解析によるエラー分析などをサービスとして実現するためのプロトコルです。
LSPを実装したクライアントは、Language Serverを提供している言語であれば何でも補完や定義参照、静的解析といった便利機能を使用することができます。&lt;/p&gt;
&lt;p&gt;Microsoftが2016年にその仕様を公開してから、多くのエディタ用のLSPのクライアント実装が作られ、また各種言語用のLanguage Serverも公開されています。&lt;/p&gt;
&lt;p&gt;Go言語も例に漏れずLanguage Serverの実装がいくつか存在します。今回は準公式提供の&lt;a href="golang.org/x/tools/gopls"&gt;gopls&lt;/a&gt;
を使用して設定してみます。
もちろんemacsにも複数のLSP Client実装がありますが、今回は&lt;a href="https://github.com/emacs-lsp/lsp-mode" target="_blank" rel="noopener"&gt;lsp-mode&lt;/a&gt;
を使用します。&lt;/p&gt;
&lt;p&gt;まずはemacs用のパッケージをインストールします。次のモノを&lt;code&gt;package-install&lt;/code&gt;か&lt;code&gt;package-list-packages&lt;/code&gt;か、そのあたりでよしなにインストールします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;lsp-mode&lt;/li&gt;
&lt;li&gt;lsp-ui&lt;/li&gt;
&lt;li&gt;company-lsp&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;インストールできたら、(私はuse-packageを使っているので)設定ファイルにuse-packageの設定を入れておきます。ついでにgo用の設定も入れておきましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; Golang&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;lsp-go-install-save-hooks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;before-save-hook&lt;/span&gt; &lt;span class="nf"&gt;#&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;lsp-format-buffer&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;before-save-hook&lt;/span&gt; &lt;span class="nf"&gt;#&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;lsp-organize-imports&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;go-mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:ensure&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:mode&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;\\.go\\&amp;#39;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;go-mode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:init&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;add-hook&lt;/span&gt; &lt;span class="ss"&gt;&amp;#39;go-mode-hook&lt;/span&gt; &lt;span class="nf"&gt;#&amp;#39;&lt;/span&gt;&lt;span class="nv"&gt;lsp-go-install-save-hooks&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;;; Language Server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;lsp-mode&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:ensure&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:hook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;go-mode&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;lsp-deferred&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:commands&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;lsp&lt;/span&gt; &lt;span class="nv"&gt;lsp-deferred&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;lsp-ui&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:ensure&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:commands&lt;/span&gt; &lt;span class="nv"&gt;lsp-ui-mode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;use-package&lt;/span&gt; &lt;span class="nv"&gt;company-lsp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:ensure&lt;/span&gt; &lt;span class="no"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="ss"&gt;:commands&lt;/span&gt; &lt;span class="nv"&gt;company-lsp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;goplsのインストールもしましょう。&lt;/p&gt;</description></item><item><title>Flutter環境構築 with emacs</title><link>https://blog.web-apps.tech/flutter_setup_with_emacs/</link><pubDate>Sat, 18 Jan 2020 15:18:55 +0000</pubDate><guid>https://blog.web-apps.tech/flutter_setup_with_emacs/</guid><description>&lt;p&gt;ここ数日、FlutterでAndroidアプリを書く、ということに入門してみています。
Androidアプリの開発自体は大分前(無印Galaxy Sを使っていた頃なので、EclairとかFroyoとかの頃)にすこしだけやったことがあるんですが、そのころと比べるとかなり簡単に、きれいなアプリがシュッと動いて、ちょっとばかし感動しています。&lt;/p&gt;
&lt;p&gt;扨、Flutter/Android開発の環境構築ですが、ほとんどのドキュメントがAndroid Studioを前提としており、私のようなemacsユーザがどうしたらいいのか、ちょっとばかし躓きそうなので、メモがてら残しておきます。&lt;/p&gt;
&lt;p&gt;なお、基本的な手順は&lt;a href="https://flutter.dev/docs/get-started/install/macos" target="_blank" rel="noopener"&gt;公式サイト&lt;/a&gt;
に準じます。また、環境はmacOS Catalina バージョン 10.15.1、emacsはbrewで入れるemacs-mac 26.3です。
Flutterのバージョンは執筆時点でv1.12.13+hotfix.5でした。&lt;/p&gt;
&lt;h2 id="flutter-sdkのインストール"&gt;Flutter SDKのインストール&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://flutter.dev/docs/get-started/install/macos" target="_blank" rel="noopener"&gt;公式サイト&lt;/a&gt;
のダウンロードリンクからFlutter SDKをダウンロードしてきて解凍、任意の場所に配置します。私はなんとなくで&lt;code&gt;$HOME/.local/flutter&lt;/code&gt;以下に配置しています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ wget https://storage.googleapis.com/flutter_infra/releases/stable/macos/flutter_macos_v1.12.13+hotfix.5-stable.zip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ unzip flutter_macos_v1.12.13+hotfix.5-stable.zip
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mv flutter &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.local/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;配置できたらPATHを通します。
私はzshを使っているので、&lt;code&gt;$HOME/.zshrc&lt;/code&gt;に以下の行を追加しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Flutter SDK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.local/flutter/bin&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;PATHを通したら、&lt;code&gt;flutter --version&lt;/code&gt;でちゃんとPATHが通っているかを確認します。&lt;/p&gt;
&lt;h2 id="android-sdkのインストール"&gt;Android SDKのインストール&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://flutter.dev/docs/get-started/install/macos" target="_blank" rel="noopener"&gt;公式サイト&lt;/a&gt;
の手順ではAndroid Studioを入れろとのことですが、emacsを使う予定なので、Android Studioはインストールせず、Android SDKのみをインストールします。
&lt;a href="https://developer.android.com/studio" target="_blank" rel="noopener"&gt;Android Studioのサイト&lt;/a&gt;
へアクセスし、&lt;a href="https://developer.android.com/studio#downloads" target="_blank" rel="noopener"&gt;DOWNLOAD OPTIONS&lt;/a&gt;
をクリックしてCommand line tools onlyのところからmacOS用のCommand line toolsをダウンロード、Flutter SDKと同様に適宜配置してPATHを通すか、簡単に&lt;code&gt;brew cask install android-sdk&lt;/code&gt;とします。
私は今回はbrewで入れました。(Flutter SDKもbrewで配布されていますが、Flutter SDKは少し古かったので、公式からダウンロードしてきた方が良さそうです)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;brew cask install android-sdk&lt;/code&gt;をしたときにもメッセージが出ますが、android-sdkを使用するにはJDK 8が必要なので、&lt;code&gt;brew cask install adoptopenjdk8&lt;/code&gt;としてJDKもインストールしておきます。&lt;/p&gt;</description></item><item><title>2019年の振り返り</title><link>https://blog.web-apps.tech/2019-review/</link><pubDate>Wed, 08 Jan 2020 04:58:54 +0000</pubDate><guid>https://blog.web-apps.tech/2019-review/</guid><description>&lt;p&gt;‌&lt;/p&gt;
&lt;p&gt;2020年に入って早1週間が経過しましたが、皆様いかがお過ごしでしょうか。 一年の振り返り！みたいのはあんまりやるつもりがなかったのですが、あまりにもみんなやっていて目につくので、これはやった方が良い物なのか・・・と思い直し、遅ればせながら振り返ってみようかと思います。&lt;/p&gt;
&lt;h3 id="1月"&gt;1月&lt;/h3&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;そういえば2018年振り返りみたいなブログ書いてないんですが、2019年は心おだやかに生きたいと思っております&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1080869672818335744?ref_src=twsrc%5Etfw"&gt;January 3, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;twitterによると、2019年は心おだやかに生きたいというのが目標だった様子。あまり心穏やかには生きられませんでした。合掌。&lt;/p&gt;
&lt;p&gt;そういえば昨年は年明け早々インフルエンザにかかったんでした。&lt;/p&gt;
&lt;p&gt;一月はLOCALのイベントに行ったり、YAPC::Tokyoに行ったりしていた様子。ここ半年はカンファレンス/勉強会参加数も減ってきてしまっているので、ここらでちょっと頑張りたいところです。&lt;/p&gt;
&lt;h3 id="2月"&gt;2月&lt;/h3&gt;
&lt;p&gt;ONIconをやったり、自作ケーブルを作り始めたり。&lt;/p&gt;
&lt;p&gt;gomaconfやcookpadtechconfもこのあたりだったようです。&lt;/p&gt;
&lt;h3 id="3月"&gt;3月&lt;/h3&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;ペティナイフが欲しい&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1101339768116281344?ref_src=twsrc%5Etfw"&gt;March 1, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;ペティナイフ、ネット上でもいろんな人が「便利！」って言ってて、しかしまぁ三徳で不自由してなかったんですけど、買ってみたら実際メチャクチャ便利で、正直三徳よりペティを使うことの方が圧倒的に多い。&lt;/p&gt;
&lt;p&gt;LINE.goというイベントを開催したのも3月でした。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;朝ご飯 &lt;a href="https://t.co/PLRDDJEOCY"&gt;pic.twitter.com/PLRDDJEOCY&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1102716831599484928?ref_src=twsrc%5Etfw"&gt;March 4, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;ご神体は今も職場の机にまつられています。なんと今は鳥居もついています
&lt;img loading="lazy" src="https://blog.web-apps.tech/2019-review/images/IMG_20200108_133705_hu_ba317fa691ed50a1.jpg" alt="IMG_20200108_133705" /&gt;
&lt;/p&gt;
&lt;h3 id="4月"&gt;4月&lt;/h3&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;皆さん技術書典の進捗どうですか&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1112944814541070337?ref_src=twsrc%5Etfw"&gt;April 2, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;今もまた、技術書典の進捗に追われています。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;たいした意味もなく近所のコインランドリーで枕を洗濯した結果、ドラム式洗濯乾燥機がほしくなってる&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1116727517849608193?ref_src=twsrc%5Etfw"&gt;April 12, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;この後勢いよくドラム式洗濯機を買いました。最高。&lt;/p&gt;
&lt;h3 id="5月"&gt;5月&lt;/h3&gt;
&lt;p&gt;PyCon mini sapporoが5月だったらしいです。GoConでしゃべったのもこのあたりだったらしい。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;改めて。でかい。 &lt;a href="https://t.co/zO9TLfdhy8"&gt;pic.twitter.com/zO9TLfdhy8&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1133758838824288258?ref_src=twsrc%5Etfw"&gt;May 29, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;OSC19doも5末〜6始でしたね&lt;/p&gt;
&lt;h3 id="6月"&gt;6月&lt;/h3&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;鰹節食べ放題 &lt;a href="https://t.co/c6ouIwcHis"&gt;pic.twitter.com/c6ouIwcHis&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1138395750902054915?ref_src=twsrc%5Etfw"&gt;June 11, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;ところで、まとめを書くのも疲れてきました。&lt;/p&gt;
&lt;h3 id="7月"&gt;7月&lt;/h3&gt;
&lt;p&gt;Golang 101を開催したのが7月だったようす。またやりたいんですが、会場が難しいですね。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;進捗です &lt;a href="https://t.co/cbZGgdeHiA"&gt;pic.twitter.com/cbZGgdeHiA&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1155029202300628992?ref_src=twsrc%5Etfw"&gt;July 27, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;次の技術書典に向けて、これの第二巻を書いています。&lt;/p&gt;</description></item><item><title>趣味サーバーのインフラを再構成した件</title><link>https://blog.web-apps.tech/my-private-cloud-2019/</link><pubDate>Mon, 06 Jan 2020 09:06:45 +0000</pubDate><guid>https://blog.web-apps.tech/my-private-cloud-2019/</guid><description>&lt;p&gt;明けましておめでとうございます。
本年もどうぞよろしくお願いいたします。&lt;/p&gt;
&lt;p&gt;扨、もう一昨年になりますが、&lt;a href="https://blog.web-apps.tech/my-infra-with-k8s/"&gt;趣味サーバーのインフラをKubernetesで整えた件&lt;/a&gt;
という記事を投稿しました。
その後紆余曲折ございまして、これらを再構成しましたので、改めて記録に残しておこうと思います。&lt;/p&gt;
&lt;h2 id="紆余曲折"&gt;紆余曲折&lt;/h2&gt;
&lt;p&gt;まずは紆余曲折とは？という話から始めましょう。&lt;/p&gt;
&lt;p&gt;当時、Kubernetes用のPersistent VolumeはGlusterFSを使用していました。最初はこれで問題なかったのですが、一部のアプリケーション(具体的にはRedmine)を動かしていく上で、非常に速度が遅い、ということが問題となりました。
調査の上、どうやら遅い原因がGlusterFSであり、Cephに置き換えることである程度速度を改善することができそうだ、という見込みが立ったため、前述の記事を投稿してから約二ヶ月後にGlusterFSを&lt;a href="https://blog.web-apps.tech/ceph-rbd-storageclass/"&gt;Ceph RBDへと置き換えました&lt;/a&gt;
。&lt;/p&gt;
&lt;p&gt;その後、&lt;a href="https://nttxstore.jp/" target="_blank" rel="noopener"&gt;NTT-X Store&lt;/a&gt;
でSSDが安かったため、12台ほどSSDを購入、すべての物理ボリュームをHDDからSSDに置き換え、RAID1+0で再構成しました。
同時に、以前はローカルボリュームを直接使用していたOpenNebulaのストレージ部も分散構成にするべく、物理マシン上に直接Cephを構成、これをOpenNebulaとKubernetesでシェアする形にしました。&lt;/p&gt;
&lt;p&gt;これでうまくいったか？と思ったのですが、どっこい、どうやらDL360G6のRAIDカードとSSDの相性(しかもファームウェア単位)が悪いらしく、一週間〜一ヶ月程度で、故障もないのにRAIDから抜けてしまう、という問題が発生しました。&lt;/p&gt;
&lt;p&gt;on Kubernetes on OpenNebulaで稼働していた本ブログの運用にも影響が出たため、一旦本ブログを(今は亡き)&lt;a href="https://cloudgarage.jp/" target="_blank" rel="noopener"&gt;CloudGarage&lt;/a&gt;
へと退避、SSDの交換をNTT-X Storeへと申請しました。&lt;/p&gt;
&lt;p&gt;その後無事SSDは新品交換され、その間に&lt;a href="https://virtualtech.jp/" target="_blank" rel="noopener"&gt;某社&lt;/a&gt;
から廃棄するということでいただいてきたDL360G7が三台ほど導入されたため、これを基盤として再度プライベートクラウド基盤を構築することと相成りました。&lt;/p&gt;
&lt;h2 id="現在の構成"&gt;現在の構成&lt;/h2&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/my-private-cloud-2019/images/private-cloud-diagram_hu_b52b17dddd4a31ed.png" alt="private-cloud-diagram" /&gt;
&lt;/p&gt;
&lt;p&gt;再構成した、とはいえ、構成は大きくは変わっていません。
IaaS基盤としてOpenNebula/KVMを使用しているのも変わりませんし、コンテナ基盤としてKubernetesを使用しているのも変わりません。&lt;/p&gt;
&lt;p&gt;強いて言えば、本ブログのストレージは最近までSQLiteを使用していましたが、外部MySQLへと移行したくらいでしょうか。&lt;/p&gt;
&lt;h3 id="物理層"&gt;物理層&lt;/h3&gt;
&lt;p&gt;物理サーバとしては前述の通り、DL360G7を使用しています。適当にメモリを増設しており、それぞれ次の様になっています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;8コア16スレッド、36GB&lt;/li&gt;
&lt;li&gt;8コア16スレッド、47GB&lt;/li&gt;
&lt;li&gt;8コア16スレッド、49GB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;メモリの量はできるだけそろえたかったんですが、&lt;del&gt;計算が面倒&lt;/del&gt;うまくそろえることができませんでした。&lt;/p&gt;
&lt;p&gt;OSはCentOS 7を使用しています。最初はCentOS 8でやろうとしたんですが、もろもろパッケージがうまくインストールできず、7に落ち着きました。なんとかなってくれ。&lt;/p&gt;
&lt;p&gt;これらに、OpenNebulaおよびCeph MIMICをインストールしてあります。Ceph Nautilusにアップデートしたいんですが、安定しているのだろうか・・・&lt;/p&gt;
&lt;h3 id="vm層"&gt;VM層&lt;/h3&gt;
&lt;p&gt;OpenNebula/KVMを使用したIaaSの上にVMをポチポチと立てられるようになっています。OpenNebulaのストレージはCephを使用しています。VMも基本的にはCentOS 7を使用しています。&lt;/p&gt;
&lt;p&gt;また、DBやPrometheusなど一部のアプリケーションをVMとして構築してあります。
以前はK8s上でPrometheusなども管理していたのですが、(主にストレージの)管理が面倒だったので、今回はVMにDockerをインストールして個別に起動しています。&lt;/p&gt;
&lt;h3 id="コンテナ層"&gt;コンテナ層&lt;/h3&gt;
&lt;p&gt;コンテナ基盤はKubernetesで、相も変わらず&lt;a href="https://github.com/kubernetes-sigs/kubespray" target="_blank" rel="noopener"&gt;Kubespray&lt;/a&gt;
を使用して構築しています。便利便利。現在はKubernetes 1.16.3です。&lt;/p&gt;
&lt;p&gt;PersistentVolume用のStorageClassはPM上のCephをOpenNebulaと共用で使用しています。手前味噌ですが、&lt;a href="https://blog.web-apps.tech/ceph-rbd-storageclass/"&gt;Ceph RBDをKubernetesのStorageClassとして登録する&lt;/a&gt;
を見ながら設定しました。&lt;/p&gt;
&lt;p&gt;Service type LoadBalancerの実装として&lt;a href="https://metallb.universe.tf/" target="_blank" rel="noopener"&gt;MetalLB&lt;/a&gt;
を、Ingress実装として&lt;a href="https://kubernetes.github.io/ingress-nginx/" target="_blank" rel="noopener"&gt;NGINX Ingress Controller&lt;/a&gt;
を導入してあります。また、HTTPSの証明書を自動設定するため、&lt;a href="https://github.com/jetstack/cert-manager" target="_blank" rel="noopener"&gt;cert-manager&lt;/a&gt;
を導入しています。以前はうまくインストールできないことがあり困ったりもしたのですが、今回は特にトラブルもなくスムーズに導入できました。だいぶCRDの構造が変わっていたので、以前導入していて、再度構成する必要がある人は注意が必要かもしれません。&lt;/p&gt;
&lt;p&gt;証明書を取得する方法はDNS01で、CloudFlareを使用しているのも変わりません。&lt;/p&gt;</description></item><item><title>go-openapi を書き直しています</title><link>https://blog.web-apps.tech/nasa9084-go-openapi-rewriting/</link><pubDate>Fri, 20 Dec 2019 08:15:39 +0000</pubDate><guid>https://blog.web-apps.tech/nasa9084-go-openapi-rewriting/</guid><description>&lt;p&gt;本記事は&lt;a href="https://qiita.com/advent-calendar/2019/go2" target="_blank" rel="noopener"&gt;Go2 Advent Calendar&lt;/a&gt;
の20日目の記事です。昨日はyaegashiさんによる、&lt;a href="https://l0w.dev/posts/jsonex.go/" target="_blank" rel="noopener"&gt;jsonx.go&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;皆さんは&lt;a href="https://github.com/OAI/OpenAPI-Specification" target="_blank" rel="noopener"&gt;OpenAPI Specification&lt;/a&gt;
というモノをご存じでしょうか。OpenAPI SpecificationはJSONまたはYAMLでREST APIを表現するための仕様で、現在&lt;a href="https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md" target="_blank" rel="noopener"&gt;バージョン3.0.2&lt;/a&gt;
が最新です。いわゆる&lt;a href="https://swagger.io/" target="_blank" rel="noopener"&gt;Swagger&lt;/a&gt;
の後継で、バージョン1系、2系がSwagger、3系以降がOpenAPI、ということになっています(Swaggerなら聞いたことがある/使っているという人も多いのではないでしょうか)。&lt;/p&gt;
&lt;p&gt;OpenAPI Specificationは人間にも機械にも(比較的)読みやすい仕様書として、コード生成や、ドキュメントページの生成に使用することが可能です。&lt;/p&gt;
&lt;p&gt;個人的には専らコード生成に使用しており、Go言語向けの実装として&lt;a href="https://github.com/nasa9084/go-openapi" target="_blank" rel="noopener"&gt;github.com/nasa9084/go-openapi&lt;/a&gt;
(以下go-openapi)を実装・公開しています。
go-openapiは2017年ごろから細々と実装を続けており、(多分)二番目か三番目には古いと思われるOpenAPIのGo実装です。&lt;/p&gt;
&lt;p&gt;基本的にはただひたすらOpenAPIのオブジェクトをGoの構造体として定義、値のバリデーション関数を用意しているといったもので、特別な機能はほとんどありません。
YAMLのパーサも、&lt;a href="https://github.com/go-yaml/yaml" target="_blank" rel="noopener"&gt;go-yaml/yaml&lt;/a&gt;
を使用しており、自前では実装していません。&lt;/p&gt;
&lt;p&gt;そんな中、&lt;a href="https://twitter.com/goccy54" target="_blank" rel="noopener"&gt;@goccy&lt;/a&gt;
さんが、encoding/jsonとコンパチなインターフェースを持ったYAMLパーサを開発した、という話を耳にし、これを機に、とgo-openapiの実装を一から書き直し始めました。
もともと、パースは完全にgo-yaml/yamlに依存しており、Unmarshal系のメソッドも実装していなかった(途中から全部書くのはつらかったので・・・)ため、一部バリデーションに必要な関数を埋め込んだりもできなかったので、書き直したいとは思っていたのです。&lt;/p&gt;
&lt;p&gt;現時点ではまだ&lt;a href="https://github.com/nasa9084/go-openapi/pull/3" target="_blank" rel="noopener"&gt;マージしておらず&lt;/a&gt;
、書いている途中なのですが、大きな変更点として次の様なものがあります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;もともとパブリックだったフィールドをすべてプライベートに変更し、ゲッターをはやした&lt;/li&gt;
&lt;li&gt;各構造体に対応する&lt;code&gt;UnmarshalYAML()&lt;/code&gt;メソッドをすべてコード生成するようにした&lt;/li&gt;
&lt;li&gt;YAMLパーサは&lt;a href="https://github.com/goccy/go-yaml" target="_blank" rel="noopener"&gt;github.com/goccy/go-yaml&lt;/a&gt;
に乗り換えた&lt;/li&gt;
&lt;li&gt;rootオブジェクトを各構造体に埋め込むことで、バリデーションをとりやすくした&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今後はよりコード生成に便利なメソッドを追加していきたいと思っています。&lt;/p&gt;
&lt;p&gt;時間の都合で今日はここまで。技術的な話が全然無い記事になってしまった・・・&lt;/p&gt;</description></item><item><title>builderscon tokyo 2020やるぞ！という話</title><link>https://blog.web-apps.tech/builderscon-tokyo-2020/</link><pubDate>Tue, 03 Dec 2019 09:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/builderscon-tokyo-2020/</guid><description>&lt;p&gt;buildersconは「知らなかった、を聞く」あるいは英語で &amp;ldquo;Discover Something New&amp;quot;をスローガンとした、IT技術者向けの技術カンファレンスです。2016年、2017年、2018年、2019年と&lt;a href="https://twitter.com/lestrrat" target="_blank" rel="noopener"&gt;@lestrrat&lt;/a&gt;
さんが主催として開催してきて、私もコアスタッフとして関わってきました。&lt;/p&gt;
&lt;p&gt;そんなbuildersconですが、2020年は子育てで多忙な@lestrratさんに代わり、私(&lt;a href="https://twitter.com/nasa9084" target="_blank" rel="noopener"&gt;@nasa9084&lt;/a&gt;
)が主催として開催に向けて準備を進めていくことになりました！&lt;/p&gt;
&lt;p&gt;まぁ、今のところはやるぞ！という話だけで細かい話はこれからですが、皆さんどうぞよろしくお願いいたします。&lt;/p&gt;</description></item><item><title>net/http.ClientにHookをかける</title><link>https://blog.web-apps.tech/hook-on-http-client/</link><pubDate>Fri, 01 Nov 2019 05:48:19 +0000</pubDate><guid>https://blog.web-apps.tech/hook-on-http-client/</guid><description>&lt;p&gt;昨日のこと。&lt;a href="https://github.com/jszwedko/go-circleci" target="_blank" rel="noopener"&gt;jszwedko/go-circleci&lt;/a&gt;
というパッケージを使用してCircleCI EnterprizeのAPIを叩くという処理を実装していたのですが、どうにもうまくいかない。正直に言ってこのパッケージはドキュメントがしっかりしている、という訳ではないし、エラーメッセージを見ても何がだめなのか(そもそも現在使用しているCircleCI Enterpriseで使用できるかもよくわかっていなかった)わからない。&lt;/p&gt;
&lt;p&gt;しかしまぁ、自分でHTTP requestを作ったりしてあれやこれややるのもまぁ面倒であるので、なんとかデバッグしたいと思ったのですが、外部のパッケージをフォークして変更を加えてデバッグする・・・という様なことはもちろんやりたくないわけです。&lt;/p&gt;
&lt;p&gt;このパッケージは&lt;a href="https://golang.org/pkg/net/http/#Client" target="_blank" rel="noopener"&gt;&lt;code&gt;*http.Client&lt;/code&gt;&lt;/a&gt;
を指定できます。&lt;code&gt;*http.Client&lt;/code&gt;はインターフェースではなく構造体なので、別の実装に置き換えるということはできません。が、その実装はほぼほぼ後述する&lt;code&gt;http.RoundTripper&lt;/code&gt;なため、&lt;code&gt;http.RoundTripper&lt;/code&gt;をラップして、HTTP requestとHTTP responseをログに吐けばまぁ、何が問題かわかるだろう、と考えました。
そんなモノは誰かがすでに書いているだろう、というのはさておき、&lt;code&gt;http.RoundTripper&lt;/code&gt;を実際にいじってみるということはやったことがなかったので、勉強がてら&lt;a href="https://github.com/nasa9084/go-logtransport" target="_blank" rel="noopener"&gt;nasa9084/go-logtransport&lt;/a&gt;
なるものを書きました。
書いていく途中で、考えたことなど、記録に残しておくのも良さそうと思ったため、本記事とします。&lt;/p&gt;
&lt;h2 id="httpclientとhttproundtripper"&gt;http.Clientとhttp.RoundTripper&lt;/h2&gt;
&lt;p&gt;Go言語でHTTPのリクエストを発行するには基本として&lt;a href="https://golang.org/pkg/net/http/#Client" target="_blank" rel="noopener"&gt;&lt;code&gt;*http.Client&lt;/code&gt;&lt;/a&gt;
というものを使用します。簡便のため、&lt;a href="https://golang.org/pkg/net/http/#Get" target="_blank" rel="noopener"&gt;GET&lt;/a&gt;
、&lt;a href="https://golang.org/pkg/net/http/#Post" target="_blank" rel="noopener"&gt;POST&lt;/a&gt;
、&lt;a href="https://golang.org/pkg/net/http/#Head" target="_blank" rel="noopener"&gt;Head&lt;/a&gt;
についてはパッケージグローバルの関数も用意されてはいるのですが、これらも内部的にはパッケージグローバルで宣言された&lt;a href="https://golang.org/pkg/net/http/#DefaultClient" target="_blank" rel="noopener"&gt;&lt;code&gt;DefaultClient&lt;/code&gt;&lt;/a&gt;
という&lt;a href="https://golang.org/pkg/net/http/#Client" target="_blank" rel="noopener"&gt;&lt;code&gt;*http.Client&lt;/code&gt;&lt;/a&gt;
が使用されています。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;*http.Client&lt;/code&gt;はゼロ値で使用できるようにまとめられた構造体で、&lt;a href="https://golang.org/pkg/net/http/#DefaultClient" target="_blank" rel="noopener"&gt;DefaultClient&lt;/a&gt;
は&lt;code&gt;*http.Client{}&lt;/code&gt;と宣言されています。&lt;/p&gt;
&lt;p&gt;普段はこの&lt;code&gt;*http.Client&lt;/code&gt;を使用してHTTPの通信を行うわけですが、実は&lt;code&gt;*http.Client&lt;/code&gt;はそれほど多くの機能は持っていません。実際、持っているフィールドはたったの4つ(Go1.13時点)しかないのです。&lt;code&gt;*http.Client&lt;/code&gt;はリダイレクトやクッキーなどの一部の処理だけを受け持っていて、実際のHTTP通信のほとんどはフィールドとして保持している&lt;code&gt;http.RoudTripper&lt;/code&gt;が行います。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http.RoundTripper&lt;/code&gt;はインターフェースとして定義されていて、自由に差し替えをすることができます。特に指定していない場合は&lt;code&gt;*http.Transport&lt;/code&gt;がデフォルトの実装として使用されます。
Goの他の標準パッケージの例に漏れず、&lt;code&gt;http.RoundTripper&lt;/code&gt;は非常にシンプルなインターフェースで、次の様に定義されています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;RoundTripper&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;RoundTrip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;RoundTrip()&lt;/code&gt;がHTTP requestを受け取り、HTTP responseを返します。つまり、requestのログをとり、子&lt;code&gt;RoundTripper&lt;/code&gt;の&lt;code&gt;RoundTrip()&lt;/code&gt;を実行し、&lt;code&gt;Response&lt;/code&gt;のログをとってそのまま返す、という様なラッパーを書けば良さそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;RoundTrip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Requestのログをとる&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RoundTrip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// responseのログをとる&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;実際にrequestとresponseのログをとるには、&lt;code&gt;net/http/httputil&lt;/code&gt;パッケージの&lt;code&gt;Dump&lt;/code&gt;系関数が使用できます。今回はクライアント側の実装なので、&lt;code&gt;httputil.DumpRequestOut&lt;/code&gt;と&lt;code&gt;httputil.DumpResponse&lt;/code&gt;を使用します。&lt;/p&gt;</description></item><item><title>空文字列確認は長さをとるべきか？</title><link>https://blog.web-apps.tech/how-to-check-empty-string/</link><pubDate>Wed, 09 Oct 2019 07:02:52 +0000</pubDate><guid>https://blog.web-apps.tech/how-to-check-empty-string/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;s == &amp;quot;&amp;quot;&lt;/code&gt;と&lt;code&gt;len(s) == 0&lt;/code&gt;は等価&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="文字列比較か長さ比較か"&gt;文字列比較か、長さ比較か&lt;/h2&gt;
&lt;p&gt;Go言語で文字列が空かどうかを調べるには次の二つの方法があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 1: 文字列を空文字列と比較する&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// do something&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 2: 文字列の長さが0かどうか調べる&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// do something&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;標準パッケージ・サードパーティパッケージともに、どちらの書き方も散見されます。
どちらを使うのが良いのでしょうか？&lt;/p&gt;
&lt;p&gt;答えは&lt;strong&gt;どちらでも良い&lt;/strong&gt;だそうです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;benchmark_test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;somethingString&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hogehogefugafuga&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkCompareString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;somethingString&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkCompareStringByLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;somethingString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このコードに対して &lt;code&gt;go tool compile -S&lt;/code&gt;した結果が以下。
&lt;code&gt;BenchmarkCompareString&lt;/code&gt;と&lt;code&gt;BenchmarkCompareStringByLength&lt;/code&gt;では同じ内容となっています。&lt;/p&gt;</description></item><item><title>Unuboでアプリケーションをサクッとデプロイする</title><link>https://blog.web-apps.tech/first-impression-unubo/</link><pubDate>Thu, 26 Sep 2019 15:10:40 +0000</pubDate><guid>https://blog.web-apps.tech/first-impression-unubo/</guid><description>&lt;p&gt;&lt;a href="https://unubo.com" target="_blank" rel="noopener"&gt;Unubo&lt;/a&gt;
というPaaSっぽいものが出てきたようなので触ってみました。 まだリリースされたばかりのようで、クレジットカードの登録もせずに無料で使用できます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/first-impression-unubo/images/----------2019-09-26-23.31.15-2_hu_9fb3f6fed7d05c0d.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/first-impression-unubo/images/----------2019-09-26-23.34.02-2_hu_4571ad0487e60176.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;とりあえず適当にリポジトリを作って動かしてみました。 登録・ログインを済ませたら、使用したい機能を選択します。今回はGoのアプリケーションなので、AppsセクションにあるGoのアイコンを選択しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/first-impression-unubo/images/----------2019-09-26-23.41.18-2_hu_1c818b672f3fd913.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;次の画面でアプリケーション名を入れ、デプロイ先のリージョンを選択します。 DBと接続する場合はDBと同一リージョンじゃなきゃ接続できないそうです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/first-impression-unubo/images/----------2019-09-26-23.42.09_hu_aa617e2abdfd6644.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;最後に、細かい設定をできる画面になりますので、必要な情報を入力します。
ここでは、とりあえずGitHubとの連携をして、リポジトリを選択するだけであとは放置します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/first-impression-unubo/images/----------2019-09-26-23.43.11_hu_51dfb166af0b6576.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;最後にDeployボタンをポチッとしてデプロイされるのを待ちます。
どうやら、Deploy成功からアクセスできるようになるまで若干タイムラグがあるようなので、気長に待ちましょう。&lt;/p&gt;
&lt;p&gt;有料プランが出てから価格設定や無料枠がどうなるかわかりませんが、まぁぼちぼち便利に使えそうですね。&lt;/p&gt;</description></item><item><title>技術書典7でGo言語の本を頒布します</title><link>https://blog.web-apps.tech/techbookfest7/</link><pubDate>Thu, 19 Sep 2019 01:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/techbookfest7/</guid><description>&lt;p&gt;今週末はいよいよ技術書典7ですね！&lt;/p&gt;
&lt;p&gt;今回はGo言語の標準パッケージの解説本を頒布予定です。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://techbookfest.org/event/tbf07/circle/5694676325629952" target="_blank" rel="noopener"&gt;web-apps.tech: サークル詳細ページ&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;当初の予定では全パッケージを詳解！みたいな予定だったんですが、ページ数が増えまくった結果、残念ながら26個しか詳解できませんでした。&lt;/p&gt;
&lt;p&gt;108ページで一冊1,000円、電子版もあるよ、の予定です(電子版と両方での割引をどうしようか今考えてます)。
サークルスペースは「か11C」です。&lt;/p&gt;</description></item><item><title>社用Gitサーバでは社用のメールをつかう.gitconfig 〜社内ドメインを外に漏らさない編〜</title><link>https://blog.web-apps.tech/gitconfig-secret/</link><pubDate>Sat, 24 Aug 2019 04:36:12 +0000</pubDate><guid>https://blog.web-apps.tech/gitconfig-secret/</guid><description>&lt;p&gt;GitHubのコミットログ、コミットした人のアイコンが出ていてとてもわかりやすいですよね。
コミットとアカウントの紐付けにはどうやら、コミットに紐付けられたメールアドレスが使用されているようです。そうなると、コミットに紐付ける(&lt;code&gt;git config user.email=...&lt;/code&gt;とかやるアレです)メールアドレスはアカウントに登録してあるメールアドレスにしたいものです。&lt;/p&gt;
&lt;p&gt;しかし、会社ではGitHub Enterprise(GHE)、私用では&lt;a href="https://github.com" target="_blank" rel="noopener"&gt;github.com&lt;/a&gt;
を使用している、と言った場合はどうでしょうか。コミットに紐付けたいメールアドレスがリポジトリによって変わる、ということになってしまいます。&lt;/p&gt;
&lt;p&gt;調べてみると、そういった場合、次の様に&lt;code&gt;.gitconfig&lt;/code&gt;に&lt;code&gt;IncludeIf&lt;/code&gt;のブロックを設定することでうまく回避ができそうということがわかり、しばらく設定していました&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[IncludeIf &amp;#34;gitdir:~/src/GHE_DOMAIN&amp;#34;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;~/.gitconfig.ghe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;~.gitconfig.ghe&lt;/code&gt;には次の様に書かれています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[user]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;社用メールアドレス&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;私はGo言語をよく書くのと、&lt;a href="https://github.com/motemen/ghq" target="_blank" rel="noopener"&gt;ghq&lt;/a&gt;
を使っている都合上、gitのリポジトリを配置するパスが&lt;code&gt;$(GOPATH)/src/GIT_DOMAIN/USERNAME/REPOSITORY&lt;/code&gt;という形式になっているため、リモートリポジトリのドメインを指定することでうまいこと社用GHEの時だけ設定を上書きすることができていたのでした。&lt;/p&gt;
&lt;p&gt;そしてこれは、どのPCでも使用できるように、&lt;a href="https://github.com/nasa9084/dotfiles" target="_blank" rel="noopener"&gt;dotfilesリポジトリ&lt;/a&gt;
として&lt;a href="https://github.com" target="_blank" rel="noopener"&gt;github.com&lt;/a&gt;
にpushしていました。&lt;/p&gt;
&lt;p&gt;その結果、会社の人から、「社内のサービスのURL(この場合はGHEのURL)はセキュリティ的な理由から外に出さないようにしてほしい」と連絡を受けました。すぐさま該当のブロックは消したのですが、そうするとメールの設定が自動でされなくなってしまい不便です。リポジトリのパスを変更するというのも、せっかくの統一的な操作に違いが出てしまい、不便です。&lt;/p&gt;
&lt;p&gt;そこで思いついたのが、こういったセンシティブな情報を別のプライベートリポジトリに分け、&lt;a href="https://github.com/nasa9084/dotfiles/blob/master/Makefile" target="_blank" rel="noopener"&gt;Makefile&lt;/a&gt;
でインストールを自動化するという方法です。&lt;/p&gt;
&lt;p&gt;パブリックな&lt;a href="https://github.com/nasa9084/dotfiles" target="_blank" rel="noopener"&gt;dotfilesリポジトリ&lt;/a&gt;
にある&lt;a href="https://github.com/nasa9084/dotfiles/blob/master/.gitconfig" target="_blank" rel="noopener"&gt;&lt;code&gt;.gitconfig&lt;/code&gt;&lt;/a&gt;
には次の様に書いてあります。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[include]
path = ~/.gitconfig.secret
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;.gitconfig.secret&lt;/code&gt;はその名の通り、秘匿情報を含んだ&lt;code&gt;.gitconfig&lt;/code&gt;で、プライベート化されたdotfiles-secretリポジトリにおいてあります。dotfiles-secretリポジトリは&lt;code&gt;make install&lt;/code&gt;としたときに&lt;code&gt;git clone&lt;/code&gt;され、さらにそのディレクトリ内の&lt;code&gt;Makefile&lt;/code&gt;により配置されます。&lt;code&gt;dotfiles-secret/.gitconfig.secret&lt;/code&gt;には先ほどの&lt;code&gt;IncludeIf&lt;/code&gt;ブロックが書かれており、同リポジトリ内の&lt;code&gt;.gitconfig.secret.ghe&lt;/code&gt;(名前を少し変えました)を読み込みます。&lt;/p&gt;
&lt;p&gt;これで、全体の使い勝手をほとんど損なうことなくどのマシンでも(dotfilesが配備済みなら)同様に設定することができました。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Makefile&lt;/code&gt;は特にdotfilesのリストを持たないよう記述しているため、新しいdotfileが増えても、特に&lt;code&gt;Makefile&lt;/code&gt;の変更をする必要も無く安心です。&lt;/p&gt;</description></item><item><title>hubコマンドにGitHub Enterprise環境を追加する</title><link>https://blog.web-apps.tech/hub-with-github-enterprise/</link><pubDate>Thu, 22 Aug 2019 10:30:00 +0000</pubDate><guid>https://blog.web-apps.tech/hub-with-github-enterprise/</guid><description>&lt;p&gt;&lt;a href="https://github.com/github/hub" target="_blank" rel="noopener"&gt;&lt;code&gt;hub&lt;/code&gt;&lt;/a&gt;
コマンドをご存じでしょうか。インストールして&lt;code&gt;alias git=hub&lt;/code&gt;と設定するだけで、&lt;code&gt;git&lt;/code&gt;コマンドからGitHubの操作ができるようになる優れものです。特に個人的には&lt;code&gt;git create&lt;/code&gt;とするだけでGitHub上にリポジトリが作成される、というのが非常に便利だと思っています。&lt;/p&gt;
&lt;p&gt;さて、皆さんの会社ではgitサーバはどのように構築されているでしょうか。いろいろな選択肢がありますが、それなりの規模だとGitHub Enterprise(以下GHE)を利用している、という会社も多いと思います。
実際、現職ではGHEを使っています。&lt;/p&gt;
&lt;p&gt;そのような場合、趣味/個人の開発ではgithub.com、会社ではGHEと使い分けることとなりますが、GHEで&lt;code&gt;hub&lt;/code&gt;が使えないとすると非常に不便です。そう考えて調べてみると、Web上では、&lt;code&gt;hub&lt;/code&gt;をGHE環境で使うには環境変数を使うとする設定例が散見されます。&lt;/p&gt;
&lt;p&gt;しかし実は、&lt;code&gt;hub&lt;/code&gt;は複数環境での使用をサポートしているんです。
設定方法は至って簡単で、&lt;code&gt;$HOME/.config/hub&lt;/code&gt;に設定を書き足すだけです。実際に見てみましょう。&lt;/p&gt;
&lt;p&gt;すでに&lt;code&gt;hub&lt;/code&gt;を使っている場合、&lt;code&gt;cat $HOME/.config/hub&lt;/code&gt;で設定を見ることができます。私の場合、次のようになっていました(&lt;code&gt;oauth_token&lt;/code&gt;は潰してありますが、実際にはトークンが入っています)。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;github.com&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;nasa9084&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;oauth_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;どんな項目かは明らかですね。ここに会社のGHEの環境に関する情報を追記します。
まず、自社のGHEのアドレス以下&lt;code&gt;/settings/tokens&lt;/code&gt;を開きます。&lt;strong&gt;Generate new token&lt;/strong&gt;ボタンをクリックし、新規でPersonal access tokenを発行します。名称はわかりやすい物を任意で付けてください。&lt;code&gt;hub&lt;/code&gt;はリポジトリを操作するコマンドですから、scopeは&lt;strong&gt;repo&lt;/strong&gt;を与えれば十分でしょう。画面下部の&lt;strong&gt;Generate token&lt;/strong&gt;ボタンをクリックすると、トークンが発行されますので、これをコピーしておきます。&lt;/p&gt;
&lt;p&gt;手元のエディタ(お好みの物を使用してください)で&lt;code&gt;$HOME/.config/hub&lt;/code&gt;を開き、設定を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;YOUR_GHE_DOMAIN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="nt"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;YOUR_USERNAME&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;oauth_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;YOUR_TOKEN&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;protocol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;オブジェクトのキーとしてGHEのドメインを、&lt;code&gt;user&lt;/code&gt;はGHEでログインに使用するユーザ名を使用します。&lt;code&gt;oauth_token&lt;/code&gt;に先ほど生成したPersonal access tokenを設定し、保存します。保存できたら、&lt;code&gt;hub&lt;/code&gt;でGHEにアクセスができるようになっているはずです。&lt;/p&gt;
&lt;p&gt;実際に使うと、次の様にどのホストを使用するか聞かれ、好きな方を選べるようになっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git create
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Select host:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 1. github.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 2. YOUR_GHE_DOMAIN
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Updating origin
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://github.com/nasa9084/REPOSITORY_NAME
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Raspberry Pi zero W + IR</title><link>https://blog.web-apps.tech/raspberry-pi-zero-w-ir/</link><pubDate>Tue, 30 Jul 2019 15:11:28 +0000</pubDate><guid>https://blog.web-apps.tech/raspberry-pi-zero-w-ir/</guid><description>&lt;p&gt;家で&lt;del&gt;転がっていた&lt;/del&gt;使われないでいたRaspberry Pi zero Wを使って、家庭内のリモコン機器を自動化しようと思い立ち、秋葉原くんだりまで行って諸々部品を買ってきました。&lt;/p&gt;
&lt;p&gt;ゴミを二つほど生成したのち、最終的に動くモノができましたので備忘録的に残しておきます。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="und" dir="ltr"&gt;&lt;a href="https://t.co/e55qxX5GL6"&gt;pic.twitter.com/e55qxX5GL6&lt;/a&gt;&lt;/p&gt;&amp;mdash; nasa9084@某某某某(0x1a) (@nasa9084) &lt;a href="https://twitter.com/nasa9084/status/1155835409131196419?ref_src=twsrc%5Etfw"&gt;July 29, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;主に「&lt;a href="https://qiita.com/takjg/items/e6b8af53421be54b62c9" target="_blank" rel="noopener"&gt;格安スマートリモコンの作り方&lt;/a&gt;
」を参考にしました。部品を購入した店は秋月電子で、商品ページの下の方にある「店舗情報」のリンクをクリックすると店内のどの棚に商品があるのかわかり便利です。どの部品も特に珍しい部品ではないため、商品自体がなくなっているようなことは(Pi zero用ユニバーサル基板をのぞき)まず無いように思えます。また、手持ちで0Ω抵抗が(なぜか)在庫してあったため、ジャンパ線代わりに使用しています。
一番見つけづらかったのがPi zero用ユニバーサル基板ですが、これは店の中ではなく、外のRaspberry Pi関連部品が置いてあるところにありました。&lt;/p&gt;
&lt;p&gt;上記のQiita記事はさほど古いモノではないため、価格も変わってなかったように思えますが、動くモノができるまでにゴミを二つほど生成した都合上、三倍程度のコストがかかりました。回路周りや半田付けがあまり得意ではない人は覚悟(というほどの額ではないですが)しておいた方が(材料を余分に買っておいた方が)良いでしょう。&lt;/p&gt;
&lt;p&gt;余談ですが部品を購入した際、近くのあきばおーでTranscendのmicro SDが安くなっていたため、大して使い道も考えずに32GBのモノを5枚ほど購入しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/raspberry-pi-zero-w-ir/images/P_20190730_233921_hu_4fa858ee4cbb1cc2.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;ほとんどの情報は参考にしたQiita記事にまとまっているため詳細は端折りますが、変更点として赤LEDを足してあります。ピカッと可視光が光るので、実行されたということを確認するのに便利です。&lt;/p&gt;
&lt;p&gt;参考記事には実際の配線図だけはなかったので、紹介します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/raspberry-pi-zero-w-ir/images/wiring_hu_fda5d3d66e4241bf.png" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;上図が部品面、下図が半田面です。MOSFET 2N7000は平らな面が図の上側、MOSFET IRFU9024NPBFは放熱板(?)が図の下側、赤外線LEDは欠けている側(カソード？)が図の右側、赤LEDは欠けている側が図の左側、赤外線受光モジュールOSRB38C9AAは受光部が図の上側を向くように配置します。私は受光モジュールは図の下方向に向けて折り、受光部が天を向くような形にしました。
ブレッドボード上で配線してそのまま基板に移植したような形になっているため、複雑な配線もなく比較的簡単かと思います。
IRFU9024NPBFの左下はジャンパなので、半田面で配線してもかまいません(私は0Ω抵抗を使用した関係で部品面を通しています)。&lt;/p&gt;
&lt;figure class="kg-gallery-card kg-width-wide"&gt;
&lt;div class="kg-gallery-container"&gt;
&lt;div class="kg-gallery-row"&gt;
&lt;div class="kg-gallery-image"&gt;
&lt;img src="https://blog.web-apps.tech/images/2019/07/P_20190730_232741.jpg" width="2094" height="1078"&gt;
&lt;/div&gt;
&lt;div class="kg-gallery-image"&gt;
&lt;img src="https://blog.web-apps.tech/images/2019/07/P_20190730_232759.jpg" width="2187" height="1012"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figcaption&gt;実際に配線したもの。右側に温度センサを追加しています&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;赤外線コードの学習・実行も参考記事通りpigpioを使用しましたが、毎度SSHしてコマンドを実行するのは面倒なため、GoでAPIサーバを実装しました。Goで赤外線をGPIOでいい感じにアレするようなパッケージが見当たらなかったので、GoからPythonのスクリプトを叩くという残念なコードになっております。いいパッケージがあれば誰か教えてください。&lt;/p&gt;
&lt;script src="https://gist.github.com/nasa9084/c482f43cc9ee0644782f8c75013fc778.js"&gt;&lt;/script&gt;
&lt;p&gt;systemdかなんかでデーモン化したりなんかして起動しておくと、例えば、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl http://raspberrypi.local/playback?key&lt;span class="o"&gt;=&lt;/span&gt;light:off
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;とかすると部屋の電気が消せます。素晴らしい。&lt;/p&gt;
&lt;p&gt;今のところ外部に公開してはいないのですが、外部に公開すると他のサービスとの連携(例えばIFTTT)ができないので、公開したい気持ちがあります。とはいえ、外からむやみに部屋の電気をあれこれされても困るし(だれもやらないとは思いますが)、そのまま公開するのも難しいな、と思っているところです。&lt;/p&gt;
&lt;p&gt;とりあえずは扇風機とか、そのあたりをなんかいい感じにアレしたいですね。&lt;/p&gt;</description></item><item><title>NATSを触ってみた</title><link>https://blog.web-apps.tech/messaging-system-nats/</link><pubDate>Wed, 06 Feb 2019 07:52:05 +0000</pubDate><guid>https://blog.web-apps.tech/messaging-system-nats/</guid><description>&lt;p&gt;&lt;a href="https://nats.io/" target="_blank" rel="noopener"&gt;NATS&lt;/a&gt;
は&lt;a href="https://www.cncf.io" target="_blank" rel="noopener"&gt;CNCF&lt;/a&gt;
(Cloud Native Computing Foundation)によってホスティングされているメッセージングシステムです。軽量で高パフォーマンスかつスケーラブルなのが特徴だそうです。オランダのSynadia社が中心となって開発を行っていますが、オープンソースソフトウェアなので&lt;a href="https://github.com/nats-io" target="_blank" rel="noopener"&gt;GitHub&lt;/a&gt;
上で今トリビュートすることもできます。
Go、NodeJS、Ruby、Java、C、C#、Nginx用のクライアントライブラリはSynadiaによってサポートされており、そのほかにもPythonやElixir用のクライアントなどが存在します。
NATSのサーバ自体(gnatsd)は&lt;a href="https://github.com/nats-io/gnatsd" target="_blank" rel="noopener"&gt;Goで書かれている&lt;/a&gt;
ため、バイナリ一つで起動できるほか、、&lt;a href="https://hub.docker.com/_/nats" target="_blank" rel="noopener"&gt;公式Dockerコンテナイメージ&lt;/a&gt;
や&lt;a href="https://github.com/nats-io/nats-operator" target="_blank" rel="noopener"&gt;Kubernetes用のOperator&lt;/a&gt;
も用意されているため、簡単に構築・運用することができます。
本記事でも、Dockerで起動したサーバを使用しています。&lt;/p&gt;
&lt;p&gt;NATSでは3種類のメッセージングモデルを利用することができます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Publish/Subscribe&lt;/li&gt;
&lt;li&gt;Request/Reply&lt;/li&gt;
&lt;li&gt;Queueing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;今回はPub/SubとRequest/Replyを試してみます。&lt;/p&gt;
&lt;h2 id="サーバを立ち上げる"&gt;サーバを立ち上げる&lt;/h2&gt;
&lt;p&gt;実験に先駆けて、まずはサーバを立ち上げます。今回はmacOS High Sierra環境のため、docker for macで起動してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run --rm -d --name nats -p 4222:4222 -p 6222:6222 -p 8222:8222 nats:1.4.0-linux
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;nats:1.4.0-linux&lt;/code&gt;は執筆時点(2019-02-06)で&lt;code&gt;nats:latest&lt;/code&gt;です。
ここで三つのポートを空けていますが、それぞれ用途は次の通りです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;:4222&lt;/code&gt;: client port&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:6222&lt;/code&gt;: route port&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:8222&lt;/code&gt;: http port&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;それぞれの詳細な説明は割愛しますが、本記事ではクライアントからの接続だけを試してみますので、4222番ポートだけの開放でも問題ありません。&lt;/p&gt;
&lt;h2 id="publishsubscribe"&gt;Publish/Subscribe&lt;/h2&gt;
&lt;p&gt;まずは標準的なPub/Subモデルから試してみます。NATSのPub/SubはRedisなどと同様、&lt;a href="https://ja.wikipedia.org/wiki/%E5%87%BA%E7%89%88-%E8%B3%BC%E8%AA%AD%E5%9E%8B%E3%83%A2%E3%83%87%E3%83%AB" target="_blank" rel="noopener"&gt;Wikipedia&lt;/a&gt;
でいうところの「トピックベース」なPub/Subです。NATSではトピックのことを&lt;strong&gt;Subject&lt;/strong&gt;とよびます。
NATSのSubjectは階層構造をとることができ、&lt;code&gt;.&lt;/code&gt;(ドット)で区切って表現します。Subscriberはこの階層構造の一部にワイルドカードとして&lt;code&gt;*&lt;/code&gt;(アスタリスク)を使用することができます。また、&lt;code&gt;&amp;gt;&lt;/code&gt;を使用して下の階層すべて、を表現することもできます。
例えば、Subscriberが&lt;code&gt;foo.bar.*&lt;/code&gt;を購読している場合、&lt;code&gt;foo.bar.baz&lt;/code&gt;や&lt;code&gt;foo.bar.qux&lt;/code&gt;などのメッセージを受け取ることができますが、&lt;code&gt;foo.bar.baz.qux&lt;/code&gt;は受け取ることができません。一方、&lt;code&gt;foo.bar.&amp;gt;&lt;/code&gt;を購読している場合、&lt;code&gt;foo.bar.baz.qux&lt;/code&gt;も受け取ることができます。&lt;/p&gt;
&lt;p&gt;サンプルコードとして、次のようなものを書いてみました。&lt;/p&gt;
&lt;h3 id="publisher"&gt;Publisher&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nats&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/nats-io/go-nats&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;localhost:4222&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;subjectFoo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bodyBar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="subscriber"&gt;Subscriber&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nats&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/nats-io/go-nats&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;localhost:4222&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;subjectFoo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Subject: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Queue: %s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;nats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;それぞれ、適当なファイルに保存し、&lt;code&gt;go run&lt;/code&gt;で起動します。あらかじめSubscriber側を起動しておくことで、Publisherを起動した際にメッセージ(今回は&amp;quot;bodyBar&amp;quot;)が(Subscriber側で)Printされるはずです。
ポイントは&lt;code&gt;*nats.Conn.Subscribe&lt;/code&gt;が非同期な関数で、メッセージを受け取った際にcallback関数が呼ばれる、というところです。
今回のサンプル中では&lt;code&gt;&amp;lt;-ch&lt;/code&gt;としてブロックしていますが、何らかの方法でブロックしないと、受け取る前にmainが終わってしまうので注意が必要です。
同期処理したい場合には、&lt;code&gt;*nats.Conn.SubscribeSync&lt;/code&gt;を使用することで次のように書き換えられます。&lt;/p&gt;</description></item><item><title>初めての自作ケーブル</title><link>https://blog.web-apps.tech/hand-made-trrs-cable/</link><pubDate>Mon, 04 Feb 2019 17:00:46 +0000</pubDate><guid>https://blog.web-apps.tech/hand-made-trrs-cable/</guid><description>&lt;p&gt;こんばんは。&lt;a href="https://blog.web-apps.tech/my-first-ergodox-ez/"&gt;以前記事にした&lt;/a&gt;
ように、現在、職場で&lt;a href="https://ergodox-ez.com/" target="_blank" rel="noopener"&gt;Ergodox EZ&lt;/a&gt;
というキーボードを使用しています。これは元々は自作キーボードの一種で、左右分割型のキーボードです。&lt;/p&gt;
&lt;p&gt;Ergodox EZでは、右のキーボードと左のキーボードは&lt;a href="https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A9%E3%83%BC%E3%83%B3%E3%83%97%E3%83%A9%E3%82%B0#4%E6%A5%B5_%28TRRS%29" target="_blank" rel="noopener"&gt;TRRSケーブル&lt;/a&gt;
という、4極のイヤホンケーブルみたいなケーブルで接続されています。今まではとりあえず購入時に付属していたケーブルを使用していたのですが、だんだん肩が開いてきて、長さが足りないなーというお気持ちになってきました。どうせならおしゃれなケーブルがいいなぁと思いながら通販サイトで探したのですが、このTRRSケーブル、あまり需要がないのか、種類が多くありません。&lt;/p&gt;
&lt;p&gt;じゃぁ自作キーボード勢はどうしてるのだろうか、と思って調査したところ、諦めて売っているものから選ぶか、自作するか、という選択肢のようでした。自作すれば自分好みの色や長さで作れるし、ケーブルくらいなら作れそう！ということで自作ケーブル沼に入門してみました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/cable_kit_hu_caa6992ed294a75d.jpg" alt="cable_kit" /&gt;
今回作ったのはこちら。&lt;a href="https://yushakobo.jp" target="_blank" rel="noopener"&gt;遊舎工房&lt;/a&gt;
さんで販売されている、自作ケーブルキットです。はじめは部材を個別にそろえて作ろうと思っていたのですが、&lt;a href="http://biacco42.hatenablog.com/entry/2017/11/17/093000" target="_blank" rel="noopener"&gt;自作キーボード界隈のDiscordサーバ&lt;/a&gt;
で聞いたところ、最初はこちらのケーブルキットが個別にパーツをそろえるよりも安くておすすめ、と言うことなので早速遊舎工房さんに向かい購入してきました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/plug_hu_25642b0259de604d.jpg" alt="plug" /&gt;
セットの内容を確認していきましょう。まずはプラグ。4極の3.5mmフォーンプラグです。Ergodox EZは向かって奥の方にジャックがあるため、L字型なのはうれしいですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/tube_hu_61162d315f658ad9.jpg" alt="tube" /&gt;
次は熱収縮チューブ。こちらは購入時に色を選ぶことができます。今回は無難に白を選択しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/paracode_hu_d51bcc1d73d1cd81.jpg" alt="paracode" /&gt;
こちらはパラコード。元々はパラシュートなどのひもに使われるらしいのですが、今回はケーブルカバー的なものとして使用します。こちらも色を選ぶことができ、黒を選択しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/sleeve_hu_6463b4cfab96bfa2.jpg" alt="sleeve" /&gt;
これはスリーブです。パラコードの上からかぶせておしゃれ感を演出します。これ、なんて調べたら売ってるのを見つけることができるんでしょうか。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/rawcable_hu_33fac70bc491e4e0.jpg" alt="rawcable" /&gt;
最後にケーブル本体。50cmです。上からパラコードをかぶせるため、なんかよくわからない色です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/insert_paracode_hu_6da8ccd0778aad91.jpg" alt="insert_paracode" /&gt;
実際に作業していきます。まずはパラコードの中にケーブルを通していきます。パラコードの中には白いひもが入っていますが、これを抜いてあいたスペースにケーブルを通します。ちょっとずつ、パラコードを縮めてひっぱってを繰り返して、ケーブルが全部入りきるまで差し込みます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/inserted_hu_745b85496088022e.jpg" alt="inserted" /&gt;
こちらが挿入し終わったもの。パラコードはケーブルより長めに用意されているのですっぽり隠れました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/inserted_sleeve_hu_3ca6054e0d42996f.jpg" alt="inserted_sleeve" /&gt;
さらに上からスリーブをかぶせます。スリーブの端は非常にほどけやすく、最初入れるのが難しかったです。要注意。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/cut_hu_312ca3d20ff43fe9.jpg" alt="cut" /&gt;
片方の恥をテープで留め、ケーブルを露出させました。露出させた長さはプラグに合わせてあります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/open_hu_44d249cdcec9f51c.jpg" alt="open" /&gt;
被覆を剥いた状態。四軸のケーブルです。非常に細いため、被覆を剥く時に切ってしまわないかドキドキでした。予算に余裕があればケーブルストリッパーを用意してもいいかもしれません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/connector_hu_261943b086e7f397.jpg" alt="connector" /&gt;
ケーブルを端子に半田付けしていきます。冒頭にも書いたように、「ケーブルくらいなら作れそう！」とか思ってましたが、これめっちゃ難しいです。3.5mmフォーンプラグなんで、端子もめっちゃ小さいです。上の方(写真中黄色の線)から付け始めてしまったので、余計難易度が増しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/connector_2_hu_b764f3ce2ccd6990.jpg" alt="connector_2" /&gt;
反対側の半田付け。これを始める前に端子のカバーと熱収縮チューブをケーブルに通しておきます。そして二度目はさすがに学び、きちんとケーブルの長さを端子にそろえる、下から半田付けを始める、などにより少しきれいにつけれるようになりました。&lt;/p&gt;
&lt;p&gt;残念なことにテスターを用意していなかったのでテストしていませんが(大丈夫か？)、この時点で導通とショートしてないかをテストしておくべきでしょう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/heated_tube_hu_552812bc996ad01c.jpg" alt="heated_tube" /&gt;
半田付けが終わったら熱収縮チューブをネジの直前まで持ってきて温めます。最初はヒートガンを買おうと思ってたのですが、秋葉原で売っていたものはamazonで売ってる安いやつより高かったのと、思ったよりサイズがあってびびったので購入には至りませんでした。Discordで聞いたところによるとドライヤーでもいける、ということだったのでドライヤーで挑戦しましたが、十分収縮しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/hand-made-trrs-cable/images/cable_hu_4d50522141f89e1e.jpg" alt="cable" /&gt;
最後にケーブルの端子カバーをはめて(ぴったりのサイズなので、熱収縮チューブをつけた後は非常に通しにくい)完成です。会社に行かないとErgodoxがないので動作確認ができていませんが、無事使えることを祈っています。&lt;/p&gt;
&lt;p&gt;このほかにも部材をいくつか購入してきてあるので、もう少しケーブル作りをやって行ってみようと思います。&lt;/p&gt;
&lt;p&gt;&lt;insert datetime=2019-02-06&gt;追記: 使えませんでした&lt;/insert&gt;&lt;/p&gt;</description></item><item><title>zero memory allocation slice filtering</title><link>https://blog.web-apps.tech/zero-memory-allocation-slice-filtering/</link><pubDate>Mon, 04 Feb 2019 07:30:29 +0000</pubDate><guid>https://blog.web-apps.tech/zero-memory-allocation-slice-filtering/</guid><description>&lt;p&gt;次のように、あるスライスをフィルタリングする関数を書くことがあると思います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;FilterFoo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;IsFoo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;簡単なベンチマークを書くとわかるように、この関数は返値となるスライスの長さ+1回のメモリアロケーションを行います。一般に、メモリアロケーションの回数は少ない方がパフォーマンスがよく、可能ならばアロケーション回数0を目指したいものです。&lt;/p&gt;
&lt;p&gt;今回の場合、次のように書くとメモリアロケーション回数0回の関数を書くことができます。&lt;/p&gt;
&lt;p&gt;&lt;ins datetime=2019-02-05&gt;&lt;em&gt;追記&lt;/em&gt;
&lt;code&gt;b := arr[:0]&lt;/code&gt;とすると、基底配列に影響が出るので一概に比較できない、とご指摘を受けました。実際に使用する際は副作用に注意しましょう。&lt;/p&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;このやりかたって引数に副作用あるので、わかってないで使うと危ないような…&lt;a href="https://t.co/iKXrXHUD3N"&gt;https://t.co/iKXrXHUD3N&lt;/a&gt; &lt;a href="https://t.co/CMrAYGJrdA"&gt;https://t.co/CMrAYGJrdA&lt;/a&gt;&lt;/p&gt;&amp;mdash; Yoichiro Shimizu (@budougumi0617) &lt;a href="https://twitter.com/budougumi0617/status/1092566248242569216?ref_src=twsrc%5Etfw"&gt;February 4, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;append は引数を弄ってしまうので動作が異なりますね。 / “zero memory allocation slice filtering” &lt;a href="https://t.co/JFFDJlfIQA"&gt;https://t.co/JFFDJlfIQA&lt;/a&gt;&lt;/p&gt;&amp;mdash; mattn (@mattn_jp) &lt;a href="https://twitter.com/mattn_jp/status/1092581160339726336?ref_src=twsrc%5Etfw"&gt;February 5, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;p&gt;&lt;em&gt;追記終わり&lt;/em&gt;&lt;/ins&gt;&lt;/p&gt;</description></item><item><title>Majextand</title><link>https://blog.web-apps.tech/majextand/</link><pubDate>Mon, 28 Jan 2019 08:55:49 +0000</pubDate><guid>https://blog.web-apps.tech/majextand/</guid><description>&lt;p&gt;ラップトップスタンド、というものをご存知でしょうか。いわゆるノートPCを傾けたり、高さを変えるために使用するアイテムです。折りたたみができるものや、PCに貼り付ける小型のものなんかもあります。
貼り付け型のものとしては、&lt;a href="https://amzn.to/2CRmzAv" target="_blank" rel="noopener"&gt;Kickflip&lt;/a&gt;
が人気です。
今回紹介するのも貼り付け型で、その名も&lt;a href="https://amzn.to/2CNbNeD" target="_blank" rel="noopener"&gt;Majextand&lt;/a&gt;
といいます。
特徴としてはとにかく薄い。そしてその薄さにも関わらず、6段階の高さ調整ができる、という点です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/majextand/images/package_hu_5a9573fe260553ac.jpg" alt="package" /&gt;
まずはパッケージ。すっきりとしたパッケージです。商品名をggって出てくるブログに掲載された写真では何やら筆文字で書かれているようなパッケージが見られますが、現行品ではなくなったようです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/majextand/images/P_20190127_163214_hu_bea996b796076745.jpg" alt="package_2" /&gt;
裏面はこんな感じ。スタンドを使用して画面を高くすることで猫背を防ぎ、頚椎の姿勢を正します。また、18インチ以下のラップトップであれば基本的には使用できます。非常に薄いため、インナーケースなどに入れる場合にも引っかかりません。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/majextand/images/P_20190127_163242_hu_2b87ec2f4ebd8ca.jpg" alt="package_3" /&gt;
パッケージ自体にテープなどは使用されておらず、Majextand本体と同じように引き出す形となっています。パッケージ自体が本体と同じような構造になっているのは素敵な感じがしますね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/majextand/images/P_20190127_163336_hu_e37445e857a184a5.jpg" alt="majextand_1" /&gt;
本体を取り出しました。非常に薄く、切れ目が入ったただの鉄板と言われても信じてしまいそうです。測ってはいないのですが、他のレビュー記事によるとだいたい10円玉と同じ厚さとのこと。薄い。
しかし、薄さに対して、若干重い気はします。スタンドという用途ですから、強度を確保するには仕方ないのかもしれませんが。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/majextand/images/P_20190127_163346_hu_e4006fd7822975fc.jpg" alt="majextand_2" /&gt;
このように引き出して使います。(本当は手前をまず引き出して、奥側は高さ調整のために使う)&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/majextand/images/P_20190127_165642_hu_77da7e0869447e0c.jpg" alt="majextand_3" /&gt;
MacBook Pro (13-inch, 2018)のスペースグレーの底面に貼り付けるとこんな感じ。両面テープは非常に強く、意図的に剥がさなければ剥がれてしまうということはなさそうです。
今回購入したMajextandはグレーで、MacBookのスペースグレーとは若干色味が違いますが、すごく目立つということはなく、安心しました。&lt;/p&gt;
&lt;p&gt;購入したばかりでまだ活用できていないのですが、これから使っていきます。&lt;/p&gt;</description></item><item><title>年越し鴨南蛮</title><link>https://blog.web-apps.tech/toshikoshi-kamo-nanban/</link><pubDate>Sat, 19 Jan 2019 05:27:16 +0000</pubDate><guid>https://blog.web-apps.tech/toshikoshi-kamo-nanban/</guid><description>&lt;p&gt;もう1月も半ばを過ぎ、まもなく2月が来る、というところで今更感を拭うことができない話題なのですが、2018年末(実は時間的には年が明けていたが)に年越しそばとして鴨南蛮を作りました。&lt;/p&gt;
&lt;p&gt;さて、鴨南蛮なので鴨肉が必要です。今回は&lt;a href="https://builderscon.io" target="_blank" rel="noopener"&gt;builderscon&lt;/a&gt;
の肉会などでお世話になっている&lt;a href="https://www.themeatguy.jp/ja/" target="_blank" rel="noopener"&gt;ミートガイ&lt;/a&gt;
さんから&lt;a href="https://www.themeatguy.jp/ja/d002.html" target="_blank" rel="noopener"&gt;鴨の胸肉&lt;/a&gt;
を購入しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/toshikoshi-kamo-nanban/images/65D353F9-A9FD-47C3-B668-9C2187DE6265-1_hu_2a2c7b18b5a69b52.jpg" alt="65D353F9-A9FD-47C3-B668-9C2187DE6265-1" /&gt;
こちらが回答した鴨肉をAnovaでやったやつです。温度は忘れたんですが、大体1~2時間くらいやったやつです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/toshikoshi-kamo-nanban/images/FAA9912D-0EA6-4E9E-A5A5-8A5560D26F7A_hu_e74ff4e617b6b12c.jpg" alt="FAA9912D-0EA6-4E9E-A5A5-8A5560D26F7A" /&gt;
軽く塩をした後、熱したフライパンで焼き目をつけていきます。皮を下にして、高めの温度でさっとやります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/toshikoshi-kamo-nanban/images/4DB89241-70A4-4DE2-B504-0002B24C59CF_hu_8013807027b20a62.jpg" alt="4DB89241-70A4-4DE2-B504-0002B24C59CF" /&gt;
焼き目をつけた鴨肉です。いい色ですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/toshikoshi-kamo-nanban/images/9204407A-C125-4EE4-A3DB-D7782D468D2C_hu_37717e0a9c42e881.jpg" alt="9204407A-C125-4EE4-A3DB-D7782D468D2C" /&gt;
油がたくさん出ます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/toshikoshi-kamo-nanban/images/91CA617A-F212-4EDC-BF36-C9E200797540_hu_ddb213c4cda990c6.jpg" alt="91CA617A-F212-4EDC-BF36-C9E200797540" /&gt;
鴨から出た油でネギを焼きましょう&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/toshikoshi-kamo-nanban/images/8CD6FB38-023B-49D9-A306-AB7976FF40DA_hu_3042ff3553c100e7.jpg" alt="8CD6FB38-023B-49D9-A306-AB7976FF40DA" /&gt;
ネギを焼いている間に鴨を切ります。幸せのため少し厚切りにしましたが、鴨はすこし薄めでもいいかもしれないです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/toshikoshi-kamo-nanban/images/A8BD9816-5A62-4776-B407-DF886C5677F8-1_hu_ce4ec685f388fadf.jpg" alt="A8BD9816-5A62-4776-B407-DF886C5677F8-1" /&gt;
最後にそばの上に盛り付けて完成。うまい。&lt;/p&gt;</description></item><item><title>jessevdk/go-assetsでファイルを埋め込む</title><link>https://blog.web-apps.tech/jessevdk-go-assets/</link><pubDate>Thu, 17 Jan 2019 07:47:13 +0000</pubDate><guid>https://blog.web-apps.tech/jessevdk-go-assets/</guid><description>&lt;p&gt;Go言語の素敵なところの一つとして、最終的な成果物を1バイナリに収めることができる、という点にあると思う。結果として、非常に簡単にコマンドラインツールなどを配布することができる。
しかし、例えばコード生成を行うようなツールでテンプレートファイルを別途持っているような場合や、アプリケーション中で使う画像などを含む場合など、Goのソースコード以外のファイルを必要とする場合、全てを1ファイルで、とはいかない。&lt;/p&gt;
&lt;p&gt;そのような場合に便利なのが&lt;a href="https://github.com/jessevdk/go-assets" target="_blank" rel="noopener"&gt;jessevdk/go-assets&lt;/a&gt;
である。以前は多くの人がgo-bindataを使用していたと思われるが、作者がやめてしまったため、使えなくなってしまった。代替としてこれが便利。
jessevdk/go-assetsを使用するには、まず&lt;a href="https://gibhut.com/jessevdk/go-assets-builder" target="_blank" rel="noopener"&gt;jessevdk/go-assets-builder&lt;/a&gt;
を使用する。これは、指定したファイルをGoのソースコードに埋め込んで、それらを扱うための&lt;code&gt;Assets&lt;/code&gt;というオブジェクトを作成してくれるツールである。&lt;/p&gt;
&lt;p&gt;インストールは簡単で、&lt;code&gt;go get&lt;/code&gt;するだけ。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get github.com/jessevdk/go-assets-builder
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;インストールできたら、次のように使う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls assets/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;foo.html.tmpl bar.png
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go-assets-builder assets -o assets.go
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;すると、&lt;code&gt;assets&lt;/code&gt;ディレクトリの内容が埋め込まれた&lt;code&gt;assets.go&lt;/code&gt;が生成される。今回は特にパッケージ名を指定していないのて、&lt;code&gt;package main&lt;/code&gt;として作成された。必要なら&lt;code&gt;-p&lt;/code&gt;オプションでパッケージ名を指定することもできる。
生成されたあとは、実際に使いたいソースコード内で次のように使う。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/assets/foo.html.tmpl&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// in production, need to handle error&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Do something with f&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ここで作成された&lt;code&gt;f&lt;/code&gt;は&lt;code&gt;os.File&lt;/code&gt;と同じインターフェースを備えている。要するに、&lt;code&gt;os.Open&lt;/code&gt;を使用したときと同じように操作することができる。&lt;/p&gt;
&lt;p&gt;また、&lt;code&gt;Assets&lt;/code&gt;という変数を別に使いたいときは、go-assets-builderでパッキングするときに&lt;code&gt;-v&lt;/code&gt;オプションで変数名を指定することもできる。ディレクトリ全体ではなく、個別のファイルを指定することもできる。&lt;/p&gt;</description></item><item><title>きちんとやるnet/http</title><link>https://blog.web-apps.tech/net-http-for-valid/</link><pubDate>Tue, 08 Jan 2019 07:31:50 +0000</pubDate><guid>https://blog.web-apps.tech/net-http-for-valid/</guid><description>&lt;p&gt;皆さん、&lt;code&gt;net/http&lt;/code&gt;パッケージは使っていますか？
Go言語の標準パッケージである&lt;code&gt;net/http&lt;/code&gt;はPythonなどの標準HTTPパッケージに比べ、人間にとっても取り扱いがしやすいため、そのまま使用している方が多いかと思います。
しかし、この&lt;code&gt;net/http&lt;/code&gt;パッケージ、簡単に使えるように見えて結構落とし穴が多いのです。&lt;/p&gt;
&lt;h2 id="1-response-bodyはクローズする必要がある"&gt;1. Response Bodyはクローズする必要がある&lt;/h2&gt;
&lt;p&gt;次のコードを見てみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://example.com/api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;クライアントライブラリなどでよく書きそうな処理ですね。何も問題ないと思いましたか？
&lt;a href="https://golang.org/pkg/net/http/#Response.Body" target="_blank" rel="noopener"&gt;公式ドキュメント&lt;/a&gt;
を見てみましょう。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is the caller&amp;rsquo;s responsibility to close Body.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Bodyをクローズするのは関数を呼んだ人の責任、とあります。そうです。&lt;code&gt;Response.Body&lt;/code&gt;は &lt;code&gt;Close()&lt;/code&gt;しなければならないのです。ちゃんとクローズされていない場合、次のリクエストでkeepaliveコネクションの再利用がされず、パフォーマンスの悪化やコネクションリークを起こす可能性があります。&lt;/p&gt;
&lt;h2 id="2-response-bodyを最後まで読む"&gt;2. Response Bodyを最後まで読む&lt;/h2&gt;
&lt;p&gt;Response Bodyをきちんとクローズするように修正したコードが次のようなコードです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;https://example.com/api&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;defer&lt;/code&gt;を使うことできちんとクローズできているはずです。
さて、問題はないでしょうか？いいえ、これだけだとまだkeepaliveコネクションの再利用がされない恐れがあります。&lt;/p&gt;</description></item><item><title>gitにもaliasの指定ができる件</title><link>https://blog.web-apps.tech/git-aliases/</link><pubDate>Wed, 12 Dec 2018 06:16:37 +0000</pubDate><guid>https://blog.web-apps.tech/git-aliases/</guid><description>&lt;h2 id="tldr"&gt;tl;dr&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.gitconfig&lt;/code&gt;にもaliasの登録ができる
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[alias]&lt;/code&gt;ブロックにaliasを登録する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tags&lt;/code&gt;で単数・複数の悩みを解消する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;discard&lt;/code&gt;で変更を取り消す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unstage&lt;/code&gt;でaddを取り消す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uncommit&lt;/code&gt;でcommitを取り消す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ignore&lt;/code&gt;で&lt;code&gt;.gitignore&lt;/code&gt;を生成する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="git-aliases"&gt;git aliases&lt;/h2&gt;
&lt;p&gt;この記事は&lt;a href="https://qiita.com/advent-calendar/2018/yumemi01_one-liner" target="_blank" rel="noopener"&gt;今すぐalias登録すべきワンライナー by ゆめみ① Advent Calendar 2018&lt;/a&gt;
の6日目の穴埋め記事です。
こちらのアドベントカレンダーは今すぐalias登録べきワンライナーということで、みなさん&lt;code&gt;.bashrc&lt;/code&gt;や&lt;code&gt;.zshrc&lt;/code&gt;のaliasについて記事を書いてらっしゃいますが、実は&lt;code&gt;.gitconfig&lt;/code&gt;という、&lt;code&gt;git&lt;/code&gt;コマンドの設定を書いておくファイルにもaliasの指定ができます。
誰もshellのaliasとは言ってない！(・・・はず)ので、いくつか&lt;code&gt;.gitconfig&lt;/code&gt;用に便利なaliasを紹介していきましょう&lt;/p&gt;
&lt;h3 id="aliasの登録方法"&gt;aliasの登録方法&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;.gitconfig&lt;/code&gt;は基本的にiniファイルです。そのため、次のように登録します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[alias]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;aliasname1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;some command 1st&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;aliasname2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;some command 2nd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;簡単ですね？ &lt;code&gt;[alias]&lt;/code&gt;というブロックを作成し、alias名=コマンドの形で記述します。
このときコマンドは&lt;code&gt;git xxx&lt;/code&gt;の形で実行される、&lt;code&gt;xxx&lt;/code&gt;の部分のみを指定します。&lt;/p&gt;
&lt;p&gt;例えば、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[alias]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;git status&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;と指定すると実際の実行時には&lt;code&gt;git git status&lt;/code&gt;という形で実行されてしまいエラーになるので注意しましょう。
&lt;code&gt;git&lt;/code&gt;のつかないコマンドを実行したい場合は頭に&lt;code&gt;!&lt;/code&gt;をつけます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[alias]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;!ls&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このように記載すると、&lt;code&gt;git ls&lt;/code&gt;で&lt;code&gt;ls&lt;/code&gt;が実行されます。&lt;/p&gt;
&lt;h3 id="git-tags"&gt;&lt;code&gt;git tags&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;git tag&lt;/code&gt;というコマンドがありまして。まぁみなさんご存知でしょうが、tagの一覧を出したり、新しいtagを作ったりするコマンドです。これ単体では特に問題がないのですが、リモートリポジトリと合わせて使うと、ちょっと悩みが発生します。
&lt;code&gt;git tag&lt;/code&gt;コマンドでタグをつけた後、リモートリポジトリにpushするときのコマンドは&lt;code&gt;git push --tags&lt;/code&gt;です。これはtagをまとめてpushするので、複数形なんでしょう。しかしです。tagの一覧を出すときに使うのも&lt;code&gt;git tag&lt;/code&gt;と単数形なんですね。
ついつい&lt;code&gt;git tags&lt;/code&gt;と打ってしまいませんか？&lt;/p&gt;
&lt;p&gt;そんなあなたはこんなaliasを登録しておきましょう&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[alias]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;tag&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;地味ですが、これで単数形か複数形か悩まずに済みます。&lt;/p&gt;</description></item><item><title>git repositoryの初期化ルーチン</title><link>https://blog.web-apps.tech/routine-make-git-repo/</link><pubDate>Fri, 07 Dec 2018 03:19:52 +0000</pubDate><guid>https://blog.web-apps.tech/routine-make-git-repo/</guid><description>&lt;p&gt;おそらくみなさんもgit repositoryを作る時、毎回だいたい同じような手順で初期化をするのではないでしょうか。
メモがてら、自分の初期化ルーチンをまとめておきます&lt;/p&gt;
&lt;h2 id="tools"&gt;tools&lt;/h2&gt;
&lt;p&gt;使用しているツールは以下の通り:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/github/hub" target="_blank" rel="noopener"&gt;&lt;code&gt;hub&lt;/code&gt;&lt;/a&gt;
: &lt;a href="https://github.com/nasa9084/dotfiles/blob/master/.zshrc#L152" target="_blank" rel="noopener"&gt;&lt;code&gt;.zshrc&lt;/code&gt;&lt;/a&gt;
で&lt;code&gt;git&lt;/code&gt;コマンドにエイリアスを張ってます&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitignore.io" target="_blank" rel="noopener"&gt;gitignore.io&lt;/a&gt;
: &lt;a href="https://blog.web-apps.tech/gitignore-from-cli/"&gt;先日記事を書いたように&lt;/a&gt;
、&lt;code&gt;git ignore&lt;/code&gt;コマンドとして使ってます&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nasa9084/git-license" target="_blank" rel="noopener"&gt;git-license&lt;/a&gt;
: 自作のサブコマンドです&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="routine"&gt;routine&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 新しいリポジトリ用のディレクトリを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir new-repository
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; new-repository
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# GitHub上にnasa9084/new-repositoryリポジトリを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# hubコマンドの機能&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git create
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# まずは空の状態で初回コミット&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s1"&gt;&amp;#39;initial commit&amp;#39;&lt;/span&gt; --allow-empty
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .gitignoreを作成(今回はgo言語プロジェクト向け)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git ignore emacs,macos,go &amp;gt; .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add .gitignore
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s1"&gt;&amp;#39;add .gitignore for emacs,macos,go&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# LICENSEを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git license -u nasa9084 mit &amp;gt; LICENSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git add LICENSE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git commit -m &lt;span class="s1"&gt;&amp;#39;add MIT License&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push -u origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ここまでがルーチンで、ここから&lt;code&gt;Makefile&lt;/code&gt;を作ったり開発したりします。&lt;/p&gt;</description></item><item><title>x/crypto/openpgpでデータを暗号化する</title><link>https://blog.web-apps.tech/x-crypto-openpgp/</link><pubDate>Mon, 26 Nov 2018 10:15:09 +0000</pubDate><guid>https://blog.web-apps.tech/x-crypto-openpgp/</guid><description>&lt;p&gt;OpenPGPはPGP(Pretty Good Privacy)をベースとした暗号化フォーマットです。
Go言語でも&lt;a href="https://godoc.org/golang.org/x/crypto/openpgp" target="_blank" rel="noopener"&gt;&lt;code&gt;golang.org/x/crypto/openpgp&lt;/code&gt;&lt;/a&gt;
という準標準パッケージで提供されています。&lt;/p&gt;
&lt;p&gt;PGPは公開鍵暗号としてメールの暗号化等でよく使用されますが、パスフレーズを用いた対称暗号として使用することもできますので、今回はこちらを紹介します。&lt;/p&gt;
&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;暗号化には&lt;code&gt;SymmetricallyEncrypt()&lt;/code&gt;を使用する&lt;/li&gt;
&lt;li&gt;復号には&lt;code&gt;ReadMessage()&lt;/code&gt;を使用する
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prompt&lt;/code&gt;次第で無限ループする恐れがあるので注意&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="暗号化"&gt;暗号化&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;x/crypto/openpgp&lt;/code&gt;パッケージでパスフレーズを用いてファイルを暗号化するには、&lt;code&gt;SymmetricallyEncrypt&lt;/code&gt;関数を使用します。
シグネチャは次のようになっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;SymmetricallyEncrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ciphertext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;passphrase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hints&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;FileHints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;packet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;plaintext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteCloser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;順番に見て行きます。まずは引数から。&lt;/p&gt;
&lt;p&gt;第一引数である&lt;code&gt;ciphertext&lt;/code&gt;には、暗号化されたテキストを出力する&lt;code&gt;io.Writer&lt;/code&gt;を与えます。&lt;code&gt;*os.File&lt;/code&gt;などを与えてもいいですが、&lt;code&gt;*bytes.Buffer&lt;/code&gt;などを与えてその後&lt;code&gt;*os.File&lt;/code&gt;にコピーする方が良いでしょう。可読なテキストではなく、バイト列が出力されます。&lt;/p&gt;
&lt;p&gt;第二引数の&lt;code&gt;passphrase&lt;/code&gt;はその名の通り、パスフレーズを与えます。&lt;/p&gt;
&lt;p&gt;第三引数の&lt;code&gt;hints&lt;/code&gt;には暗号化するファイルのメタデータなどを含むことができますが、単純に&lt;code&gt;nil&lt;/code&gt;を与えても良いです。&lt;/p&gt;
&lt;p&gt;第四引数の&lt;code&gt;config&lt;/code&gt;で暗号化方式や乱数エントロピーソース、圧縮アルゴリズムなどを設定することができます。設定しなければ乱数として&lt;code&gt;crypto/rand.Reader&lt;/code&gt;が、ハッシュ関数としてSHA-256が、暗号化関数としてAES-128が、現在時刻として&lt;code&gt;time.Now&lt;/code&gt;が、RSAのビット数として2048がそれぞれ使用されます。圧縮はされません。&lt;/p&gt;
&lt;p&gt;返り値は二値で、&lt;code&gt;io.WriteCloser&lt;/code&gt;と&lt;code&gt;error&lt;/code&gt;です。返り値の&lt;code&gt;io.WriteCloser&lt;/code&gt;に暗号化したい内容を書き込むことで暗号化が行われます。必ず&lt;code&gt;Close&lt;/code&gt;する必要があるので忘れないように注意しましょう。&lt;/p&gt;
&lt;h3 id="使用例"&gt;使用例&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;passphrase&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// omit error handling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;openpgp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SymmetricallyEncrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;passphrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="復号"&gt;復号&lt;/h2&gt;
&lt;p&gt;暗号化したファイルを復号するには、&lt;code&gt;ReadMessage&lt;/code&gt;関数を使用します。Decrypt〜のような関数ではないので注意が必要でしょう。関数のシグネチャは次のようになっています。&lt;/p&gt;</description></item><item><title>Generator Pattern</title><link>https://blog.web-apps.tech/generator-pattern/</link><pubDate>Wed, 21 Nov 2018 08:09:23 +0000</pubDate><guid>https://blog.web-apps.tech/generator-pattern/</guid><description>&lt;p&gt;Generator PatternはGo言語における並列処理パターンの一つで、goroutine-safeな値列の生成などに使用することができます。&lt;/p&gt;
&lt;p&gt;コードを見た方が早いと思いますので、コードを掲載しましょう。
次の例は複数のgoroutineから共通の連番を採番したいときに利用することができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;GenInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;返された&lt;code&gt;&amp;lt;-chan int&lt;/code&gt;から&lt;code&gt;int&lt;/code&gt;の値を取得するようにすることで、重複のない連番を取得することができます。
Go言語において、&lt;code&gt;chan&lt;/code&gt;は複数箇所から値の取り出しを行うことができますが、&lt;code&gt;chan&lt;/code&gt;に入力された一つの値はどこか一箇所からしか取り出すことができません。そのため、lock等を使用しなくとも、必ず重複無く連番を取得することができます。
lockを使用した場合、若干動作が遅いため、可能であればlockを使用しないで、&lt;code&gt;chan&lt;/code&gt;を使用して実装できるとより高速な、Goらしいコードとすることができます。&lt;/p&gt;</description></item><item><title>LINE DEVELOPER DAY 2018に参加した</title><link>https://blog.web-apps.tech/line-developer-day-2018/</link><pubDate>Wed, 21 Nov 2018 02:51:41 +0000</pubDate><guid>https://blog.web-apps.tech/line-developer-day-2018/</guid><description>&lt;p&gt;&lt;a href="https://linedevday.linecorp.com/jp/2018/" target="_blank" rel="noopener"&gt;LINE DEVELOPER DAY 2018&lt;/a&gt;
はLINEの技術に関して紹介するイベントで、2018年11月21日に開催されたので、参加してみました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/happoen_hu_25c588cb9e646618.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;開催地は白金台の八芳園です。初めて来たのですが、厳かな日本庭園なんですね。ちょっと気後れしてしまいます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/noren_hu_140241878cb99671.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;八芳園の入り口にはDEVELOPER DAYのロゴ入り暖簾が下がっていました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/E481DC13-1BD6-488D-A8AE-BEDA3FA84C3E_hu_6049a50fba5e2268.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/46F96701-3EE9-45B4-88CB-7C766867748A_hu_d5c0f33866326fd8.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;会場の建物に向かうには庭園を抜ける必要があり、八芳園を少しですが楽しめるのはなかなか良かったように思います。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/B5755916-5A4B-4D09-B0EB-F5EFD469E2B0_hu_2c3a72f5f9fa172d.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/957469D0-DA94-4716-9EAE-F347E45E75EE_hu_d7b2321c6a6e4669.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/83CC9462-2532-4EB2-B2B8-6D44CA3F1484_hu_925bae259d849b93.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;受付は外にあり、非常に良い雰囲気でした。雨だったとしても建物の中でやれる様なプランはあったのでしょうが、雰囲気が大きく変わっていたと思いますので、雨じゃ無くて良かったですね。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/E21B0720-C9B3-4F2A-A7DD-49E4E3DF520C_hu_35475da245027c01.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/B4E9E049-B536-45E1-B9A8-3DB30B5F6402_hu_34c2a254947bc32e.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;GitHubのイベントに行ったときなんかも思ったのですが、会場の壁でこういうことをできるのは企業主体のカンファレンスのすごいところだなーと思います。
これだけで雰囲気が結構違うとは思うんですが、コミュニティ主体だとここにお金をかける意味はあんまり無いので、やろうという話にもならないことが多い気がします。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/3AEEF842-8CD5-4AF6-B8CC-2D1691B06EAF_hu_43f95548cc4d8f42.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;写真を撮った時点ではまだオープニングセッションの最中だったので稼働はしていなかったのですが、会場では通常の発表の他、ポスターセッションも行われるようでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/line-developer-day-2018/images/4C617425-0074-4632-B87A-5DD1905C37F0-1_hu_59944867a9ec0a32.jpg" alt="" /&gt;
&lt;/p&gt;
&lt;p&gt;カメラを向けても止まってはくれなかったのでちょっとぶれちゃってますが、歴戦のカンファレンススタッフであるとりいさんもスタッフ参加とのこと。&lt;/p&gt;
&lt;p&gt;LINE DEVELOPER DAY 2018は参加費無料で、約1300人の動員(予定)だそうです。&lt;/p&gt;</description></item><item><title>git ignoreコマンドで.gitignoreを取得する</title><link>https://blog.web-apps.tech/gitignore-from-cli/</link><pubDate>Tue, 13 Nov 2018 02:07:39 +0000</pubDate><guid>https://blog.web-apps.tech/gitignore-from-cli/</guid><description>&lt;p&gt;割とみんな知ってるのかもしれないですが。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git-xxx&lt;/code&gt;という名称で実行可能ファイルをパスの通ったところに配置すると、&lt;code&gt;git xxx&lt;/code&gt;という&lt;code&gt;git&lt;/code&gt;のサブコマンドの形で実行することができるようになります。これを利用したのが拙作&lt;a href="https://github.com/nasa9084/git-license" target="_blank" rel="noopener"&gt;git-license&lt;/a&gt;
で、&lt;code&gt;git license [option] license_name &amp;gt; LICENSE&lt;/code&gt;の形で実行すると&lt;code&gt;LICENSE&lt;/code&gt;ファイルを簡単に作成することができます。
その他、&lt;code&gt;git config&lt;/code&gt;でエイリアスを指定して、サブコマンドとして登録することも可能です。&lt;/p&gt;
&lt;p&gt;同様にして、&lt;code&gt;git ignore&lt;/code&gt;で`.gitignoreファイルを簡単に取得できるようにしてみましょう。&lt;/p&gt;
&lt;p&gt;おそらく現代では多くの人が&lt;code&gt;.gitignore&lt;/code&gt;の生成やテンプレート化をして、あるいはテンプレート化されたものを利用しているのではないでしょうか。GitHubのWUI上でリポジトリを作成するときにも生成することができますし、そのさい使用される&lt;code&gt;.gitignore&lt;/code&gt;ファイルとして&lt;a href="https://github.com/github/gitignore" target="_blank" rel="noopener"&gt;github/gitignore&lt;/a&gt;
が提供されています。&lt;/p&gt;
&lt;p&gt;今回紹介するのは&lt;a href="https://www.gitignore.io" target="_blank" rel="noopener"&gt;gitignore.io&lt;/a&gt;
というサービスです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/gitignore-from-cli/images/gitignoreio_hu_eeab6e18475409ab.png" alt="gitignore.io" /&gt;
&lt;/p&gt;
&lt;p&gt;gitignore.ioはその名の通り、&lt;code&gt;.gitignore&lt;/code&gt;ファイルを生成するサービスです。
基本的な使い方は非常に簡単で、ブラウザでアクセスして、テキストボックスに必要な言語、OS、エディタやIDEなどを指定していくだけです。指定が終わったら&lt;strong&gt;Create&lt;/strong&gt;ボタンを押すことで、選択した対象用の&lt;code&gt;.gitignore&lt;/code&gt;テンプレートを全て含んだ&lt;code&gt;.gitignore&lt;/code&gt;ファイルが作成されます。これを保存すれば良いですね。&lt;/p&gt;
&lt;p&gt;しかし、その他の作業をコマンドラインから行なっていると、いちいちブラウザでアクセスして、マウスで操作して・・・というのが非常に面倒に感じます。&lt;/p&gt;
&lt;p&gt;大丈夫です！gitignore.ioではもちろんAPIを提供しています(というか、WUIで生成された&lt;code&gt;.gitignore&lt;/code&gt;のURLがそのままAPIのURL)。
次のように実行してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl https://www.gitignore.io/api/go,emacs,macos
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;https://www.gitignore.io/api/&lt;/code&gt;の後ろに、カンマ区切りで必要なものを列挙して行くだけで、簡単にコマンドラインから&lt;code&gt;.gitignore&lt;/code&gt;ファイルを取得できます。&lt;/p&gt;
&lt;p&gt;ここまでやったらもう少し簡単にしたいですね？いちいちURLを打つのは面倒ですし、忘れてしまうかもしれません。せっかくなので&lt;code&gt;git&lt;/code&gt;のサブコマンドとして&lt;code&gt;git ignore&lt;/code&gt;とできるようにしてみましょう。次のコマンドを実行してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git config --global alias.ignore &lt;span class="s1"&gt;&amp;#39;!gi() { curl -L -s https://www.gitignore.io/api/$@ ;}; gi&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;もしくは、&lt;code&gt;~/.gitconfig&lt;/code&gt;ファイルの&lt;code&gt;[alias]&lt;/code&gt;のセクションに次のように設定しても良いでしょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ini" data-lang="ini"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;[alias]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt;ignore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;!curl -L -s https://www.gitignore.io/api/$@&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;$@&lt;/code&gt;は引数をそのまま渡すという変数です。このように設定をすることで、&lt;code&gt;git ignore&lt;/code&gt;としてgitignore.ioのAPIを利用することができるようになります。実際に使用する時は次のように使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git ignore go,emacs,macos
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;言語や環境のリストは全てまとめて一つの引数のため、カンマの後にスペースを入れないことに注意です。指定できる環境の一覧は&lt;code&gt;git ignore list&lt;/code&gt;とすることで表示できます。&lt;/p&gt;
&lt;p&gt;標準出力をそのままリダイレクトして、&lt;code&gt;.gitignore&lt;/code&gt;ファイルに書き込めばプロジェクトの初期設定として使用できるでしょう。&lt;/p&gt;</description></item><item><title>jessevdk/go-flagsでサブコマンドを実装する</title><link>https://blog.web-apps.tech/subcommand-using-jessevdk-go-flags/</link><pubDate>Tue, 06 Nov 2018 05:01:49 +0000</pubDate><guid>https://blog.web-apps.tech/subcommand-using-jessevdk-go-flags/</guid><description>&lt;p&gt;Go言語を用いてコマンドラインツールを開発する際、皆さんはフラグのパースやサブコマンドの実装にどんなパッケージを使用していますか？標準の&lt;code&gt;flag&lt;/code&gt;パッケージのほか、、&lt;a href="https://github.com/spf13/cobra" target="_blank" rel="noopener"&gt;&lt;code&gt;spf13/cobra&lt;/code&gt;&lt;/a&gt;
、&lt;a href="https://github.com/alecthomas/kingpin" target="_blank" rel="noopener"&gt;&lt;code&gt;alecthomas/kingpin&lt;/code&gt;&lt;/a&gt;
などもよく使われているようです。
私は専ら、&lt;a href="https://github.com/jessevdk/go-flags" target="_blank" rel="noopener"&gt;&lt;code&gt;jessevdk/go-flags&lt;/code&gt;&lt;/a&gt;
(以下&lt;code&gt;go-flags&lt;/code&gt;)を使用しています。
&lt;code&gt;go-flags&lt;/code&gt;はその名の通り、基本的にはオプション/フラグの解析用パッケージで、&lt;a href="https://godoc.org/github.com/jessevdk/go-flags" target="_blank" rel="noopener"&gt;ドキュメント&lt;/a&gt;
もフラグ解析に関するものがほとんどです。
しかし、&lt;code&gt;go-flags&lt;/code&gt;では、サブコマンドの実装も可能です。今回はこれに焦点を当ててご紹介していきます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;go-flags&lt;/code&gt;では、親コマンドにサブコマンドを登録する、という形でサブコマンドを実装していきます。サブコマンドは構造体として実装し、それぞれがオプションを格納する構造体を兼ねる形となります。
終端の、実際に何かの動作をするコマンドは &lt;code&gt;Commander&lt;/code&gt; interfaceを実装している必要がありますが、中間のサブコマンド(&lt;code&gt;docker container&lt;/code&gt;のような、グルーピングのためのサブコマンド)はこれを実装していなくても構いません。
&lt;code&gt;Commander&lt;/code&gt; interfaceの定義は次のようになっています。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Commander&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;非常に単純ですね。&lt;code&gt;args&lt;/code&gt;にはコマンドでパースされなかったあまりの引数が渡されます。
実際の実装例を見てみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;subcommand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;verbose&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`short:&amp;#34;v&amp;#34; long:&amp;#34;verbose&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;subcommand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// some exec&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;サブコマンドを実装したら、親のコマンドにサブコマンドとして登録します。
ドキュメントを見ると、&lt;code&gt;Command&lt;/code&gt;構造体に登録する関数があること、&lt;code&gt;Parser&lt;/code&gt;構造体は&lt;code&gt;Command&lt;/code&gt;構造体が埋め込まれていること、がわかります。
通常、&lt;code&gt;go-flags&lt;/code&gt;パッケージを使用する場合はパッケージグローバルの&lt;code&gt;Parse&lt;/code&gt;関数を使用することが多いと思うのですが、サブコマンドを実装する場合はトップレベルのパーサーを自分で作る必要があります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// global option&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;subcmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;subcommand&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;subcmd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;subcommand&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;subcmd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ErrHelp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このように登録することで、&lt;code&gt;subcmd&lt;/code&gt;という名前のサブコマンドが使用できるようになりました。&lt;code&gt;go run main.go subcmd&lt;/code&gt;などとすると、&lt;code&gt;subcommand.Execute&lt;/code&gt;関数が実行されます。
実際には&lt;code&gt;Parser.AddSubCommand&lt;/code&gt;のエラーをハンドリングしたりなど、もう少しやらなければならないことはあると思いますが、基本的には以上です。&lt;/p&gt;</description></item><item><title>Ergodox EZを購入した</title><link>https://blog.web-apps.tech/my-first-ergodox-ez/</link><pubDate>Wed, 31 Oct 2018 05:57:26 +0000</pubDate><guid>https://blog.web-apps.tech/my-first-ergodox-ez/</guid><description>&lt;p&gt;割と今更感もなくはないのですが、Ergodox EZという分割キーボードを購入しました。
Ergodoxは基本的には自分でパーツを揃えて組み立てる、いわゆる自作キーボードの一つですが、オープンソースで設計などが公開されており、その設計を使って完成品を販売しているのがErgodox EZです。
今回は&lt;a href="https://ergodox-ez.com/" target="_blank" rel="noopener"&gt;公式サイト&lt;/a&gt;
から購入しました。&lt;/p&gt;
&lt;p&gt;構成は次のようなものです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Color: BLACK&lt;/li&gt;
&lt;li&gt;Tilt kit/Wing Rest: YES&lt;/li&gt;
&lt;li&gt;Keycap: Blank&lt;/li&gt;
&lt;li&gt;Switches: Cherry MX Blue&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以上で$325、日本円で37,125円でした。送料がかかるという情報も多かったのですが、送料は無料で、関税が2000円ちょいくらいかかりました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/my-first-ergodox-ez/images/56e74246-0485-4121-9391-285ebb6957fe_hu_3239ada060adf5b9.jpg" alt="box of wing rest" /&gt;
&lt;/p&gt;
&lt;p&gt;wing restの箱は凹んでいました。。。
まぁ、ペラッペラのビニールだけの状態で渡航して来たので、こんなものでしょう。
箱自体はしっかりしており、多少凹んでも中の本体には影響ありませんでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/my-first-ergodox-ez/images/2e827bb4-bf25-4a2a-9a6b-f21fd9e944cb_hu_c8990acddaf5aa47.jpg" alt="ergodox ez" /&gt;
&lt;/p&gt;
&lt;p&gt;いつ使うのかよくわからないワッシャーと、キートップ・スイッチの交換に使う道具、謎のステッカーがついていました。
web上には日本語の情報がなく、ごく最近のことだと思うのですが、現在販売されているErgodox EZには&lt;a href="https://ergodox-ez.com/pages/change-it-yourself" target="_blank" rel="noopener"&gt;CIY&lt;/a&gt;
という機構が組み入れられています。キースイッチが半田付けされておらず、いわゆるソケットのようなものに刺さっているため、自分でキースイッチを交換できる、というものです。
このため、自作のErgodoxか、キーボードの故障を覚悟の上での改造のみで可能だった、一部のキースイッチのみ交換する、などが簡単に行えるようになっています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/my-first-ergodox-ez/images/cb36c90a-91ab-434e-92e3-b0b7ece0ae2d_hu_6b338b844d085653.jpg" alt="ergodox in office" /&gt;
&lt;/p&gt;
&lt;p&gt;現在は会社で使っています。
やはりエンターキー周りがなれず、slackでちょいちょい誤爆しますね。
できるだけJIS配列に近づけた構成にしており、現在のファームウェアは&lt;a href="https://github.com/nasa9084/qmk_firmware" target="_blank" rel="noopener"&gt;nasa9084/qmk_firmware&lt;/a&gt;
のdevelopブランチで管理しています。
今の所レイヤーはうまく使いこなせていないため、いいかんじの知見があれば教えてほしいところです。&lt;/p&gt;
&lt;p&gt;ファームウェアのコンパイル時、arch linuxの場合、&lt;code&gt;sudo pacman -S avr-libc&lt;/code&gt;する必要があったほか、macosの場合、&lt;code&gt;brew install avr-gcc&lt;/code&gt;する必要があったのですこしハマりました&lt;/p&gt;</description></item><item><title>Ceph RBDをKubernetesのStorageClassとして登録する</title><link>https://blog.web-apps.tech/ceph-rbd-storageclass/</link><pubDate>Tue, 23 Oct 2018 07:08:35 +0000</pubDate><guid>https://blog.web-apps.tech/ceph-rbd-storageclass/</guid><description>&lt;p&gt;Kubernetesで何らかの永続データを保存する場合、通常PersistentVolumeと呼ばれる永続ストレージを使用します。Persistent VolumeはNFSなどのネットワークストレージを直接指定することもできますが、ボリュームを手動で用意する必要があり、非常に面倒です。
そのため、ブロックストレージサービスをバックエンドとしてdynamic provisioningと呼ばれる、自動でボリュームを作成する機能も用意されています。&lt;/p&gt;
&lt;p&gt;dynamic provisioningを使用する場合、バックエンドのprovisionerをStorageClassと呼ばれるリソースに登録しておきます。クラウドでKubernetesを使用している場合はAWS EBSなどを使用するでしょう。&lt;/p&gt;
&lt;p&gt;オンプレミスや自宅でKubernetesを使用している場合、GlusterFSやCeph RBDを使用することができます。今回はCephを使用してPersistentVolumeを作成するまでの流れを説明しましょう。&lt;/p&gt;
&lt;h2 id="下準備"&gt;下準備&lt;/h2&gt;
&lt;p&gt;今回はOpenNebula上にCentOS 7のVM(2GB RAM/1Core CPU)を3台用意し、構築を行いました。バージョンはmimicです。&lt;code&gt;/dev/vdb&lt;/code&gt;にCeph用のディスクがあるとします。
それぞれ、Chronyで時刻同期の設定、firewalld無効化、SELinux無効化状態で構成しました(本番ではちゃんと設定してくださいね！)。
また、&lt;code&gt;ceph-1&lt;/code&gt; &lt;code&gt;ceph-2&lt;/code&gt; &lt;code&gt;ceph-3&lt;/code&gt;という名称でアクセスできるよう、hostsファイルを書いて、SSHの鍵もコピーしました。&lt;/p&gt;
&lt;h2 id="インストール"&gt;インストール&lt;/h2&gt;
&lt;p&gt;まずは&lt;a href="http://docs.ceph.com/docs/mimic/install/get-packages/" target="_blank" rel="noopener"&gt;公式サイト&lt;/a&gt;
を参考に各サーバへリポジトリの追加をします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/root@ceph-N# rpm --import &lt;span class="s1"&gt;&amp;#39;https://download.ceph.com/keys/release.asc&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;/root@ceph-N# cat &amp;lt; EOF &amp;gt; /etc/repos.d/ceph.repo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;ceph&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ceph packages &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;$basearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;baseurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://download.ceph.com/rpm-mimic/el7/&lt;span class="nv"&gt;$basearch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;gpgkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://download.ceph.com/keys/release.asc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;ceph-noarch&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ceph noarch packages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;baseurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://download.ceph.com/rpm-mimic/el7/noarch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;gpgkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://download.ceph.com/keys/release.asc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;[&lt;/span&gt;ceph-source&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Ceph &lt;span class="nb"&gt;source&lt;/span&gt; packages
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;baseurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://download.ceph.com/rpm-mimic/el7/SRPMS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;enabled&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;gpgkey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://download.ceph.com/keys/release.asc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;EOF
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;リポジトリの追加ができたら、各サーバへ&lt;code&gt;ceph-deploy&lt;/code&gt;をインストールします。&lt;/p&gt;</description></item><item><title>調布技研でKubernetesの薄い本を出します</title><link>https://blog.web-apps.tech/chofu-tech-k8s-book/</link><pubDate>Tue, 25 Sep 2018 11:04:55 +0000</pubDate><guid>https://blog.web-apps.tech/chofu-tech-k8s-book/</guid><description>&lt;p&gt;調布技研、という怪しい団体がありまして、私はそこに所属しています。調布技研は主にSlack上で与太話をしている集団で、インフラとかの検証なんかを共同でやっていたりします。&lt;/p&gt;
&lt;p&gt;来る10月08日に、&lt;a href="https://techbookfest.org/" target="_blank" rel="noopener"&gt;技術書典&lt;/a&gt;
という、技術系同人誌のイベントが開催されますので、そこで「&lt;a href="https://techbookfest.org/event/tbf05/circle/53000003" target="_blank" rel="noopener"&gt;色んなところでKubernetesを動かす本&lt;/a&gt;
」という同人誌を出す予定です。&lt;/p&gt;
&lt;p&gt;先ほど、無事入稿が完了しました。&lt;/p&gt;
&lt;p&gt;私は「おうちKubernetesの作り方」と題して、自宅を含むオンプレでKubernetes環境を作るためのあれやこれやを執筆しました。ベースとなっているのは「&lt;a href="https://blog.web-apps.tech/my-infra-with-k8s/"&gt;趣味サーバーのインフラをKubernetesで整えた件&lt;/a&gt;
」でもご紹介した私の自宅Kubernetes環境で、小規模ならばプロダクションにも使える環境です。&lt;/p&gt;
&lt;p&gt;物理本1冊500円(電子版つき)、電子版のみは400円での頒布となる予定ですので、ぜひお買い求めください。場所は&lt;strong&gt;か16&lt;/strong&gt;です。&lt;/p&gt;
&lt;p&gt;なお、冒頭の画像はタイトルをミスった表紙です。&lt;/p&gt;</description></item><item><title>日本仮想化技術(株)を退職します</title><link>https://blog.web-apps.tech/change-job-2018/</link><pubDate>Tue, 18 Sep 2018 09:19:26 +0000</pubDate><guid>https://blog.web-apps.tech/change-job-2018/</guid><description>&lt;h2 id="レギュレーション"&gt;レギュレーション&lt;/h2&gt;
&lt;blockquote class="twitter-tweet"&gt;&lt;p lang="ja" dir="ltr"&gt;タイトルで煽らない、かしこまった見出しもつけない、ウィッシュリストのせない、東亜飯店張らない、fromとtoを両方書く。職場崩壊を暴露しない。キラキラしない。これが私の求める退職エントリです。&lt;/p&gt;&amp;mdash; laiso?? (@laiso) &lt;a href="https://twitter.com/laiso/status/892403727079923712?ref_src=twsrc%5Etfw"&gt;August 1, 2017&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;h2 id="本題"&gt;本題&lt;/h2&gt;
&lt;p&gt;私事ですが、2018-09-20を以て日本仮想化技術株式会社を退職し、2018-10-01付けでLINE株式会社へ就職します。&lt;/p&gt;
&lt;p&gt;以上。&lt;/p&gt;</description></item><item><title>ingress-nginxで諸々設定する</title><link>https://blog.web-apps.tech/configure-ingress-nginx/</link><pubDate>Sun, 16 Sep 2018 17:06:14 +0000</pubDate><guid>https://blog.web-apps.tech/configure-ingress-nginx/</guid><description>&lt;p&gt;&lt;a href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener"&gt;ingress-nginx&lt;/a&gt;
を使用している際に、nginxに何か設定をしたいと思ったとき。
例えば、nginxは初期状態では、アップロードできるファイルの上限は1MBなのですが、これをもっと大きくしたいとき、nginxでは次のように設定します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code class="language-conf" data-lang="conf"&gt;client-max-body-size 5m;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;これをingress-nginxでも設定したいと思ったとき、どうしたら良いか。&lt;/p&gt;
&lt;p&gt;まぁ、簡単な話で、&lt;a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/" target="_blank" rel="noopener"&gt;annotation&lt;/a&gt;
で設定値を与えてあげれば良いです。
この場合だと、次のようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;nginx.ingress.kubernetes.io/proxy-body-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;5m&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;設定できる値は&lt;a href="https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/" target="_blank" rel="noopener"&gt;ingress-nginxのドキュメント&lt;/a&gt;
に記載されています。
&lt;code&gt;client-max-body-size&lt;/code&gt;を指定するのに&lt;code&gt;proxy-body-size&lt;/code&gt;と設定することに注意です。&lt;/p&gt;</description></item><item><title>builderscon tokyo 2018</title><link>https://blog.web-apps.tech/builderscon-tokyo-2018/</link><pubDate>Mon, 10 Sep 2018 06:10:44 +0000</pubDate><guid>https://blog.web-apps.tech/builderscon-tokyo-2018/</guid><description>&lt;p&gt;過日、かねてより準備してきた&lt;a href="https://builderscon.io/tokyo/2018" target="_blank" rel="noopener"&gt;builderscon tokyo 2018&lt;/a&gt;
が開催され、そして終了しました。&lt;/p&gt;
&lt;h3 id="opening"&gt;Opening&lt;/h3&gt;
&lt;p&gt;例年、buildersconでは主催の&lt;a href="https://twitter.com/lestrrat" target="_blank" rel="noopener"&gt;@lestrrat&lt;/a&gt;
さんがオープニングでお話をしているのですが、今年はなんと動画を作りました。&lt;/p&gt;
&lt;p&gt;それがこちら。&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/82T0XpODXyw?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;オープニングムービーなので7分程度ですが、かなり気合いの入った動画となっております。詳しい情報は&lt;a href="https://medium.com/@lestrrat/builderscon-tokyo-2018-%E3%82%AA%E3%83%BC%E3%83%97%E3%83%8B%E3%83%B3%E3%82%B0%E4%BD%9C%E6%88%90%E3%81%AE%E8%A3%8F%E5%81%B4-b8fac8390aca" target="_blank" rel="noopener"&gt;「builderscon tokyo 2018 オープニング作成の裏側」&lt;/a&gt;
で紹介されています。&lt;/p&gt;
&lt;p&gt;記事中でも解説されていますが、この動画、「The Stanley Parable」というゲームのオマージュとなっています。残念ながら開催時点で私はプレイしたことがなかったのですが、昨日プレイしました。面白い。ナレーションがナレーションのくせにこう、感情的なんですよね。怒ったり、悲しんだり。是非皆さんもプレイして(もしくはYoutubeとかでプレイ動画をみて)みてください。&lt;/p&gt;
&lt;h3 id="talk"&gt;Talk&lt;/h3&gt;
&lt;p&gt;2016年の初開催からコアスタッフとしてやってきた私ですが、今年は&lt;a href="https://builderscon.io/tokyo/2018/session/0e224762-b349-4d44-9ece-6f2d8b2f2e4b" target="_blank" rel="noopener"&gt;スピーカーとしても参加することが出来ました&lt;/a&gt;
(スライドは&lt;a href="https://gitpitch.com/nasa9084/slides/builderscon18" target="_blank" rel="noopener"&gt;こちら&lt;/a&gt;
)。残念ながら一度は落選しており、キャンセルされた枠に滑り込む形でしたが、2016年はCfP落選、2017年は業務都合で当日参加出来ず、そして2018年は穴埋め登壇と、着実に進歩しています。来年は是非、きちんと「通った」スピーカーとして参加したい・・・！&lt;/p&gt;
&lt;p&gt;twitterで私が話している時間帯のツイートを見ると、「Kubernetesがゲシュタルト崩壊」と複数の方に書かれていて、メダパニを書けてしまった気分です。しかし話題が話題なだけに仕方なかったんや！&lt;/p&gt;
&lt;h3 id="スタッフとして"&gt;スタッフとして&lt;/h3&gt;
&lt;p&gt;上でも書きましたが、今年は三年目のコアスタッフ参加でした。初年は北海道からのリモート参加、去年は当日に絡む仕事は出来ず、だったので、実質まともに参加したのは初めてです。
いくつかoctav(buildersconウェブサイトのバックエンドAPIサーバ)の修正を書き(マージされたとは言っていない)、当日スタッフのまとめ役をしたりしました。&lt;/p&gt;
&lt;p&gt;当日スタッフのまとめは正直上手く出来たとは言えず、他のスタッフ(Discordの設定とか当日スタッフの担当割りの細かい調整をしてくれたtoriiさん、諸々印刷などしてくれたuessyさんに多大なる感謝を・・・)の助けを得てなんとか大きな問題無く終えることが出来ました。&lt;/p&gt;
&lt;p&gt;タスクはまだ残っているので、これから一週間くらいかけてがしがしやっていきます。&lt;/p&gt;
&lt;p&gt;来年は今年よりももっとコミットしていきたい所存です。&lt;/p&gt;
&lt;h3 id="来年に向けて"&gt;来年に向けて&lt;/h3&gt;
&lt;p&gt;buildersconのコアスタッフSlackでは、すでに来年の企画に向けて侃々諤々といった様相です。buildersconは他のカンファレンスに比べ、自由度が高い(と思っています)ので、何か面白いことをやりたい、と思ったかたは是非スタッフに参加してみてください。(そのうちスタッフ募集が始まる・・・はず)&lt;/p&gt;</description></item><item><title>fitbit versa三日目レビュー</title><link>https://blog.web-apps.tech/fitbit-versa-3days/</link><pubDate>Tue, 04 Sep 2018 14:46:50 +0000</pubDate><guid>https://blog.web-apps.tech/fitbit-versa-3days/</guid><description>&lt;p&gt;&lt;a href="https://www.fitbit.com/jp/versa" target="_blank" rel="noopener"&gt;fitbit versa&lt;/a&gt;
を&lt;a href="https://blog.web-apps.tech/fitbit-versa/"&gt;使い始めて&lt;/a&gt;
3日ほど経ったので、現時点での感想をば。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;電池の持ちは前情報通り1日で20%〜25%減る程度
&lt;ul&gt;
&lt;li&gt;常時接続・Keep-AliveウィジェットはともにON&lt;/li&gt;
&lt;li&gt;夜にお風呂/シャワー上がってから、翌日お風呂/シャワーに入るまで、で1日。
&lt;ul&gt;
&lt;li&gt;お風呂/シャワーの間に充電100%&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;画面つける動作の反応が悪い、という情報があったが、そんなに気にならない&lt;/li&gt;
&lt;li&gt;歩数計は少し過敏な様で、実際歩いた歩数より多い気がする
&lt;ul&gt;
&lt;li&gt;PCでの作業でも反応してる気がする&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;本体が防水でも、バンドが水を吸うと水に過敏になる
&lt;ul&gt;
&lt;li&gt;明日からはCLASSIC BANDに取り替えてみる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;結構変な方向を向いてしまう
&lt;ul&gt;
&lt;li&gt;ベルトをもう一つ締めれば回らなくなるけど、今度は少しきつい&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amzn.to/2LVLB40" target="_blank" rel="noopener"&gt;安い画面保護ガラスフィルム&lt;/a&gt;
を買った
&lt;ul&gt;
&lt;li&gt;一部のレビュー通り、縁が若干浮いている様だけど、気にならないレベル&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;腕時計をつける習慣が無かったことは、お風呂の時以外常時つけていると案外気にならない&lt;/li&gt;
&lt;li&gt;Androidアプリは若干バグってる
&lt;ul&gt;
&lt;li&gt;後述。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;versa上で動くアプリはあんまり無い
&lt;ul&gt;
&lt;li&gt;もっと増えたら楽しいのに・・・・(しかしどんなアプリが欲しいかというと思いつかない)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;versaの時計盤の種類も(よさげなのは)そんなに多くない
&lt;ul&gt;
&lt;li&gt;まぁ、頑張ろう&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;階数カウントは何を基準にカウントしてるのか謎。&lt;/li&gt;
&lt;li&gt;天気予報、スマホ側で設定できる画面があるけど結局現在地しか表示できてない。
&lt;ul&gt;
&lt;li&gt;よくわからん。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;アラーム、もう少し長く鳴って欲しい&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="androidアプリのバグ"&gt;Androidアプリのバグ&lt;/h2&gt;
&lt;p&gt;Android用のfitbitアプリが若干バグってました。すでに報告済みですが、まぁパッとは治らない様子。仕方ない。
具体的には、睡眠のページを開き(このときは問題ない)、睡眠の日別詳細を開いて戻ると、なんとデータの一覧が増殖する。
尚動作環境はZenfone 5Z、Android 8.0.0。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fitbit-versa-3days/images/1_hu_6ef88615a20c9bfd.jpg" alt="1" /&gt;
睡眠のページ。問題はなさそうに見える。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fitbit-versa-3days/images/2_hu_fa986494560f6c2c.jpg" alt="2" /&gt;
睡眠の日別詳細ページを開いて戻ってきた画面。同じデータだが、画面表示が増えている。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fitbit-versa-3days/images/3_hu_2407ae9733563c3d.jpg" alt="3" /&gt;
もう一度詳細を開いて戻ってきた画面。増える。増える・・・。&lt;/p&gt;</description></item><item><title>EC2インスタンスからEKS上のアプリケーションにアクセスしたい</title><link>https://blog.web-apps.tech/eks-internal-lb/</link><pubDate>Sun, 02 Sep 2018 03:04:50 +0000</pubDate><guid>https://blog.web-apps.tech/eks-internal-lb/</guid><description>&lt;h2 id="trdr"&gt;TR;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Kubernetesの&lt;code&gt;Service&lt;/code&gt;で、Internal LoadBalancerってのがあるので、それを使うと良い&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="internal-loadbalancer"&gt;Internal LoadBalancer&lt;/h2&gt;
&lt;p&gt;皆さんはEKS、もう使ってますか？私は使っています。業務システムをリプレースで新規開発する的な案件で、新システムの基盤がEKSという感じです。EKSはネットワークが素敵に気持ち悪い感じになっており、普通はKubernetesのクラスタ内部っていうのは、外側と別のサブネットを作る訳なんですが、なんとEKSが所属するVPCと同じサブネットで接続できるようになっています。&lt;/p&gt;
&lt;p&gt;そんなわけで、同一VPCに存在したり、VPC PeeringしたりなんかしちゃってるEC2インスタンスとEKS上の&lt;code&gt;Pod&lt;/code&gt;はIPアドレスベースでは普通に接続がとれちゃったりするんです。
EKS上のアプリケーションから、EC2インスタンスへアクセスしたいときは、普通にEC2インスタンスのIPアドレスやら内部エンドポイントへアクセスすれば良いですね。EC2インスタンスが動きっぱなしならまぁさほどIPも変わらんでしょう(雑)。&lt;/p&gt;
&lt;p&gt;しかし逆は問題です。&lt;code&gt;Pod&lt;/code&gt;のIPは勿論割り振られてはいますけれど、これは&lt;code&gt;Pod&lt;/code&gt;が再生成されると勿論変わってしまいます。アプリケーションは動きっぱなしだから変わらない、なんて言うこともできないです。EC2インスタンスはインスタンス上でアプリケーションの更新なんかもしちゃうかもしれないですけど、EKS上の&lt;code&gt;Pod&lt;/code&gt;に乗ったアプリケーションの更新は普通、&lt;code&gt;Pod&lt;/code&gt;の再作成が伴います。&lt;code&gt;Pod&lt;/code&gt;の再作成が起きると、勿論IPが変わります。&lt;/p&gt;
&lt;p&gt;そうすると、やはり考えるのは&lt;code&gt;Service&lt;/code&gt;をつくることですね。外部からアクセスするためにはそうしますから、同じように考えるのが普通です。
しかし、ここで問題が発生します。普通に外部向けに公開するのと同じように&lt;code&gt;Service&lt;/code&gt;を作成すると、グローバルIPが当たってしまい、プライベートIPベースで接続できる状況では接続ができないのです。困った。&lt;/p&gt;
&lt;p&gt;まぁドキュメントちゃんと読めよって話なんですが、&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/" target="_blank" rel="noopener"&gt;Kubernetesのドキュメント&lt;/a&gt;
を読むと、Internal LoadBalancerってのがちゃんと書いてあります。AWSの方のドキュメントには無かったのでちょっと盲点でした。annotationで次の様に指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;my-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;annotations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;service.beta.kubernetes.io/aws-load-balancer-internal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0.0.0.0&lt;/span&gt;&lt;span class="l"&gt;/0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# ...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;これだけで、&lt;code&gt;type: LoadBalancer&lt;/code&gt;で作成されるELBが内部向けのものになります。internal-なんちゃらみたいなエンドポイントです。IPアドレスもしっかりプライベートIPです。最高。後ろの&lt;code&gt;0.0.0.0/0&lt;/code&gt;のところで、アクセスできるIPレンジ制限できるのかなーなんて希望的観測を持ちましたが、全然関係ありませんでした。
ちょっと気持ち悪いのは、普通にパブリックDNSで名前引きができてしまうことですかね。全然関係ない外部のネットワークとかでも(パブリックDNSに名前があるので)名前解決ができてしまって、かつプライベートのアドレスが帰って来るという不思議な体験をすることができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ nslookup internal-xxxxx.us-west-2.elb.amazonaws.com 1.1.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server: 1.1.1.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address: 1.1.1.1#53
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Non-authoritative answer:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: internal-xxxxx.us-west-2.elb.amazonaws.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address: 192.168.187.214
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: internal-xxxxx.us-west-2.elb.amazonaws.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address: 192.168.222.128
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Name: internal-xxxxx.us-west-2.elb.amazonaws.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Address: 192.168.109.84
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;うーん、まぁ実害は無いんでしょうけど。&lt;/p&gt;</description></item><item><title>fitbit versaを購入したので開封の儀</title><link>https://blog.web-apps.tech/fitbit-versa/</link><pubDate>Sat, 01 Sep 2018 14:48:35 +0000</pubDate><guid>https://blog.web-apps.tech/fitbit-versa/</guid><description>&lt;p&gt;スマートウォッチ的なものが欲しいなーと思ったので、&lt;a href="https://www.fitbit.com/jp/versa" target="_blank" rel="noopener"&gt;fitbit versa&lt;/a&gt;
を購入しました。
fitbit versaはその名の通り、&lt;a href="https://www.fitbit.com/jp/home" target="_blank" rel="noopener"&gt;fitbit&lt;/a&gt;
が今年(2018)の6月に発売したスマートウォッチです。トップの写真からもわかるように、若干&lt;a href="https://www.apple.com/jp/watch/" target="_blank" rel="noopener"&gt;Apple Watch&lt;/a&gt;
に似ています。
元々、&lt;a href="https://www.google.com/search?q=Huawei&amp;#43;Watch&amp;#43;1&amp;amp;safe=off&amp;amp;client=firefox-b-ab&amp;amp;source=lnms&amp;amp;tbm=isch&amp;amp;sa=X&amp;amp;ved=0ahUKEwibufDF_ZndAhVGGsAKHd0QA0oQ_AUICygC&amp;amp;biw=1366&amp;amp;bih=706" target="_blank" rel="noopener"&gt;Huawei Watch&lt;/a&gt;
が欲しいなーと数年前に思っていたんですが、(当然ながら)&lt;a href="https://consumer.huawei.com/jp/wearables/watch2/" target="_blank" rel="noopener"&gt;新しいモデル&lt;/a&gt;
が出ており、これがまた初代のHuawei Watchとは全く方向性の違うスポーツタイプ。これはちょっと・・・と言うことで&lt;a href="https://gigazine.net/news/20151004-pebble-time-round/" target="_blank" rel="noopener"&gt;Pebble&lt;/a&gt;
もいいな、と探してみると、いつの間にやらサポートが終わってしまっていました。よくよく調べると、Pebbleは&lt;a href="http://healthcare.itmedia.co.jp/hc/articles/1612/23/news005.html" target="_blank" rel="noopener"&gt;fitbitに買収された&lt;/a&gt;
とのことでした。かといってApple Watchを買うかというと、私は&lt;a href="https://www.android.com/" target="_blank" rel="noopener"&gt;Android&lt;/a&gt;
ユーザですから、そういう選択肢はありませんでした。&lt;/p&gt;
&lt;p&gt;そうこう考えながらいろいろ検索したりなんかしていたんですが、fitbit versaが実質的にPebbleの後継であるという情報を見たり&lt;a href="http://rebuild.fm/209/" target="_blank" rel="noopener"&gt;聞いたり&lt;/a&gt;
しました。お値段もお手頃で、これならまぁいざ微妙でも、買い換えもできるかな、という気持ちもあり、購入に踏み切りました。(fossilの新しいやつもよさげなんですが、ドルで見た金額と円で見た金額が大幅に違って萎えました)&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fitbit-versa/images/4F3EBB43-D9E2-4D2D-A408-8CB751ACFDFE_hu_8b74a992efbf28c2.jpg" alt="outsitde_box" /&gt;
外箱はこんな感じです。fitbit versaは、通常モデル(シリコン？ゴム？のバンド)が3種類と、SPECIAL EDITION(布バンド)が2種類の計5種類で展開されています。元々海外モデルではSPECIAL EDITIONにのみNFCが搭載されているという違いがあったようなのですが、日本版では機能的違いは無いようです。
通常モデルの黒と、SPECIAL EDITIONのグレーですごく悩みました。本体の色はグラファイトの方が良さそうだし、バンドも布の方がよさげに見えたんですが、布バンドは濡れたら乾くまで時間かかりそうなので、ゴムバンドのほうが良いのかな・・・と・・・(店頭で悩み続けたので若干怪しかったかも？)。でもまぁ、本体の色はブラックよりグラファイトの方がよさげでしたし、ゴムバンドは純正の交換バンドとして売ってるから、後で買うこともできるか、ということでSPECIAL EDITIONのグレーにしました。今回ビックカメラで買ったんですが、ビックカメラではカードの様なものをレジに持って行くんです。で、商品を受け取ってみたら箱の右下に「PLUS EXTRA CLASSIC BAND」の文字・・・。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fitbit-versa/images/492831AA-30E8-443F-ACD3-5C530E3F572E_hu_ddd92d37e4d8cc0f.jpg" alt="EXTRA BAND" /&gt;
帰ってから開封してみたら、案の定通常モデルと同じクラシックバンドが付属してました。ついてるなら早めに言ってほしかった・・・あれだけ店頭で悩んだ私の時間とは・・・。!&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fitbit-versa/images/B658E26C-E76D-43C2-AC7E-44FC69657626_hu_66988d8ea9dbd35e.jpg" alt="film" /&gt;
本体の画面を保護していたフィルムを取ってみて気づいたんですが、小さなクッションのようなものがついてました。ボタンが押ささらない様にとの配慮なんでしょうけど、こういう細かい気遣いは初めて見たので少しだけ感動しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/fitbit-versa/images/10D458F1-4F09-451B-B04D-3A1DFA129DFB_hu_c39158a3f590365b.jpg" alt="versa" /&gt;
非常に軽く、そしてエッジが削られているので薄く見えるため、非常にスマートです。写真で見る限りではベゼルが結構幅広なのが気にかかった(最近はZenfone 5Zを使っていることもあり、ベゼルは小さい方がいいなーと思っていた)のですが、実際画面をつけてみると、意外と気になりませんでした。&lt;/p&gt;
&lt;p&gt;元々腕時計など、腕に何かをつけるという習慣がないので、どうなるかわかりませんが、しばらく使ってみようと思います。&lt;/p&gt;</description></item><item><title>趣味サーバーのインフラをKubernetesで整えた件</title><link>https://blog.web-apps.tech/my-infra-with-k8s/</link><pubDate>Thu, 23 Aug 2018 04:53:46 +0000</pubDate><guid>https://blog.web-apps.tech/my-infra-with-k8s/</guid><description>&lt;p&gt;趣味でサーバー運用をしています。札幌在住の大学生時代から運用を開始し、引っ越しに伴い朝霞へ移設、現在はコミュニティで使用している自宅外のラックへ移設されましたが、変わらず動いています。
この「趣味サーバー」は購入当初からKVMをベースとした(&lt;a href="https://opennebula.org/" target="_blank" rel="noopener"&gt;OpenNebula&lt;/a&gt;
を使用しています)プライベートクラウド基盤として使用してきました。今も変わらずベースはOpenNebula/KVMなのですが、この度晴れて&lt;a href="https://kubernetes.io/" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
を中心とした構成に組み替えたのでご紹介します。
尚、サーバ台・電気代・インターネット代を除くソフトウェア料金は基本的に無料で済んでいます。&lt;/p&gt;
&lt;h2 id="物理層"&gt;物理層&lt;/h2&gt;
&lt;p&gt;このプライベートクラウド基盤は3層で構成されています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/my-infra-with-k8s/images/3-layered_hu_a476b73faa0136e1.png" alt="3-layered" /&gt;
&lt;/p&gt;
&lt;p&gt;その最も下の層が物理層です。その名の通り物理サーバそのものですね。物理サーバとしてDELLのR410(ヤフオクで1万弱で購入・4コア8スレッド×2、メモリ16GB)とDL360Gen6一号機(会社の処分品をもらってきた・4コア4スレッド×2、メモリ24GB)、DL360Gen6二号機(会社の処分品をもらってきた・4コア8スレッド×2、メモリ24GB)の三台で、それぞれubuntu 16.04LTSがインストールされています。落ち着いたら18.04LTSにアップデートしたい。
基本的に電源やLANは冗長化されておらず、電源やNICに問題があると即死亡となります。&lt;/p&gt;
&lt;h2 id="vm層"&gt;VM層&lt;/h2&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/my-infra-with-k8s/images/vms_hu_660e7a7175f46733.png" alt="vms" /&gt;
&lt;/p&gt;
&lt;p&gt;物理層の上に構成されているのがVM層です。OpenNebula/KVMを使用しており、Web UIからポチポチッとVMを作成できます。今回Kubernetesで整える前は、VMとして&lt;a href="https://nginx.org/en/" target="_blank" rel="noopener"&gt;nginx&lt;/a&gt;
インスタンスを作成し、外からの80/443ポートへのアクセスを捌くリバースプロキシとして使用していました。本ブログも長らく単体VM上の&lt;a href="https://www.docker.com/" target="_blank" rel="noopener"&gt;Docker&lt;/a&gt;
コンテナとして稼働していました。基本的にVMにはCentOS 7をインストールしています。
今回の構成変更で、VMは基本的にKubernetesのノードとして使うように変更、直接VM上で動作しているのはオブジェクトストレージを提供する&lt;a href="https://www.minio.io/" target="_blank" rel="noopener"&gt;minio&lt;/a&gt;
とブロックストレージを提供する&lt;a href="https://github.com/gluster/glusterdocs/" target="_blank" rel="noopener"&gt;GlusterFS&lt;/a&gt;
のみとなりました。
尚、GlusterFSクラスタの構成には&lt;a href="https://github.com/heketi/heketi" target="_blank" rel="noopener"&gt;heketi&lt;/a&gt;
を使用しました。&lt;/p&gt;
&lt;h2 id="コンテナ層"&gt;コンテナ層&lt;/h2&gt;
&lt;p&gt;最も上の層がコンテナ層です。ここまでの話からわかるように、Kubernetesクラスタを構成しています。四台のCentOS 7をクラスタノードとして使用、Kubernetes自体の構成管理は&lt;a href="https://github.com/kubernetes-incubator/kubespray" target="_blank" rel="noopener"&gt;kubespray&lt;/a&gt;
を使用しています。現在はKubernetes 1.11.1です。本ブログもKubernetes上のコンテナとして動いています。
Persistent VolumeとしてVM上に構成したGlusterFSを使用、本ブログ等のバックアップ先としてminioを使用しています。
当初はVM上に構成したnginxインスタンスをそのままリバースプロキシとして使用していましたが、本ブログを含めたアプリケーションを順次Kubernetesクラスタ上のコンテナとして移設していった結果、nginxのVMだけ別になっていることに不便を感じるようになりました(リバースプロキシの設定は手作業で設定しなければなりませんし・・・)。しかし、VM上のnginxリバースプロキシを廃するためには、二つの問題点がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;素Kubernetesでは&lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" target="_blank" rel="noopener"&gt;&lt;code&gt;Ingress&lt;/code&gt;&lt;/a&gt;
が使用できないため、ホスト名ベースの振り分けが出来ない&lt;/li&gt;
&lt;li&gt;&lt;a href="https://letsencrypt.org/" target="_blank" rel="noopener"&gt;Let&amp;rsquo;s Encrypt&lt;/a&gt;
の証明書を管理するVMがいなくなる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらを解決しないことにはnginx VMを削除できません。
解決のためにまず、&lt;code&gt;kind: Ingress&lt;/code&gt;を使用するための実装として&lt;a href="https://kubernetes.github.io/ingress-nginx/" target="_blank" rel="noopener"&gt;ingress-nginx&lt;/a&gt;
を&lt;a href="https://blog.web-apps.tech/ingress-nginx-on-prem/"&gt;使用することにしました&lt;/a&gt;
。&lt;code&gt;Ingress&lt;/code&gt;が使用できるようになることで、クラスタ外のリバースプロキシを挟まずともホスト名ベースの振り分けが出来るようになります。
ingress-nginxは&lt;code&gt;Service type: NodePort&lt;/code&gt;でも使用できるのですが、折角なので&lt;code&gt;Service type: LoadBalancer&lt;/code&gt;を使用したいですよね？&lt;code&gt;type: LoadBalancer&lt;/code&gt;を使用するための実装として&lt;a href="https://metallb.universe.tf/" target="_blank" rel="noopener"&gt;MetalLB&lt;/a&gt;
を&lt;a href="https://blog.web-apps.tech/type-loadbalancer_by_metallb/"&gt;使用することにしました&lt;/a&gt;
。これにより、ingress-nginxに対してクラスタ外のIPアドレスを割り当てることが出来るようになります。&lt;/p&gt;
&lt;p&gt;次に、Let&amp;rsquo;s Encryptの証明書を管理するため、&lt;a href="https://github.com/jetstack/cert-manager" target="_blank" rel="noopener"&gt;cert-manager&lt;/a&gt;
を導入しました。cert-managerはkubesprayの導入時にアドオンとしても導入することが出来、今回はkubesprayのアドオンとして導入しました。これはその名の通り、証明書をKubernetesのリソースとして管理することが出来るツールです。最初はLet&amp;rsquo;s Encryptのacme api v02に上手くアクセスできない、ワイルドカードでの証明書取得が出来ないなど躓きましたが、Let&amp;rsquo;s Encryptに上手くアクセスできない問題は最近のkubesprayで比較的新しいバージョンのcert-managerを導入することで解決できました。ワイルドカードでの証明書が取得できない問題は、元々webroot(HTTP01)で証明書を取得していたのが原因のため、DNS01へ切り替えました。&lt;a href="https://www.gehirn.jp/dns/" target="_blank" rel="noopener"&gt;Gehirn DNS&lt;/a&gt;
を使用していましたが、上手くいかなかったため&lt;a href="https://www.cloudflare.com/ja-jp/" target="_blank" rel="noopener"&gt;Cloudflare DNS&lt;/a&gt;
に切り替え、事なきを得ました。&lt;/p&gt;
&lt;p&gt;これらにより、nginx VMを廃し、ルーターでの80/443のNAPT設定をすべてKubernetesクラスタへと向けることが出来るようになりました(OpenNebulaやminio等へのアクセスは&lt;code&gt;type: ExternalName&lt;/code&gt;を使用)。
VMがぐっと減り、ストレージ用途以外のVMを直接触らなければいけないことも減りました。めでたしめでたし。&lt;/p&gt;
&lt;h2 id="使っているものまとめ"&gt;使っているものまとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.ubuntulinux.jp/home" target="_blank" rel="noopener"&gt;Ubuntu&lt;/a&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://www.centos.org/" target="_blank" rel="noopener"&gt;CentOS&lt;/a&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
(&lt;a href="https://github.com/kubernetes/kubernetes" target="_blank" rel="noopener"&gt;GitHub&lt;/a&gt;
)&lt;/p&gt;</description></item><item><title>confd + initContainerでAlertmanagerの設定をSecretに逃がす</title><link>https://blog.web-apps.tech/alertmanager-config-to-secret-with-confd/</link><pubDate>Mon, 20 Aug 2018 08:06:47 +0000</pubDate><guid>https://blog.web-apps.tech/alertmanager-config-to-secret-with-confd/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Alertmanagerの設定には一部Secretが含まれる
&lt;ul&gt;
&lt;li&gt;バージョン管理システムに入れたくない&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;initContainerでconfdを使って設定ファイルを生成する
&lt;ul&gt;
&lt;li&gt;Alertmanagerの設定の一部をSecretに格納できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="confd"&gt;confd&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/kelseyhightower/confd" target="_blank" rel="noopener"&gt;kelseyhightower/confd&lt;/a&gt;
は非常に軽量な設定ファイル管理ツールです。基本的にはテンプレートエンジンですが、多くのバックエンドデータストアからデータを持ってきて、設定ファイルに書き出すことが出来ます。
また、事前処理や事後処理を行うことが出来るので、例えば設定ファイルを書き換えたあと、リロードする、というところまで&lt;code&gt;confd&lt;/code&gt;で行うことが出来ます。&lt;/p&gt;
&lt;h3 id="install"&gt;Install&lt;/h3&gt;
&lt;p&gt;Go言語で書かれているため、インストールは非常に簡単で、バイナリをダウンロードしてきて実行権限を与え、パスの通ったところに置くだけです。バイナリは&lt;a href="https://github.com/kelseyhightower/confd/releases" target="_blank" rel="noopener"&gt;リリースページ&lt;/a&gt;
からダウンロードすることが出来ます。&lt;/p&gt;
&lt;h3 id="使用方法"&gt;使用方法&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;confd&lt;/code&gt;を使用するためには、三つのものを用意する必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;テンプレートリソース&lt;/li&gt;
&lt;li&gt;テンプレート&lt;/li&gt;
&lt;li&gt;データストア&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="テンプレートリソース"&gt;テンプレートリソース&lt;/h4&gt;
&lt;p&gt;テンプレートリソースには、どのテンプレートを使用して、どんなキーでデータストアからデータを取り出し、完成した設定ファイルをどこに置くのか、事前処理・事後処理はどんなものかを記述します。書式はTOMLで、慣れ親しんだ(慣れ親しんでない？)iniファイルの様に気軽に書くことが出来ます。&lt;code&gt;/etc/confd/conf.d&lt;/code&gt;以下に配置します。&lt;/p&gt;
&lt;h4 id="テンプレート"&gt;テンプレート&lt;/h4&gt;
&lt;p&gt;テンプレートはその名の通り、設定ファイルのテンプレートです。ここに、データストアから取り出したデータを合わせて設定ファイルを作成します。書式はGo言語の&lt;a href="https://golang.org/pkg/text/template/#pkg-overview" target="_blank" rel="noopener"&gt;&lt;code&gt;text/template&lt;/code&gt;&lt;/a&gt;
に準じます。&lt;code&gt;/etc/confd/templates&lt;/code&gt;以下に配置します。&lt;/p&gt;
&lt;h4 id="データストア"&gt;データストア&lt;/h4&gt;
&lt;p&gt;そして、データストアにデータを入れる必要があります。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;confd&lt;/code&gt;は、データストアとして、次のものをサポートしています(2018/08/20現在)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coreos.com/etcd/" target="_blank" rel="noopener"&gt;etcd&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/coreos/etcd" target="_blank" rel="noopener"&gt;coreos/etcd&lt;/a&gt;
)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.consul.io/" target="_blank" rel="noopener"&gt;consul&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/hashicorp/consul" target="_blank" rel="noopener"&gt;hashicorp/consul&lt;/a&gt;
)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/jp/dynamodb/" target="_blank" rel="noopener"&gt;dynamodb&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://redis.io" target="_blank" rel="noopener"&gt;redis&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/antirez/redis" target="_blank" rel="noopener"&gt;antirez/redis&lt;/a&gt;
)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.vaultproject.io/" target="_blank" rel="noopener"&gt;vault&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/hashicorp/vault" target="_blank" rel="noopener"&gt;hashicorp/vault&lt;/a&gt;
)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zookeeper.apache.org/" target="_blank" rel="noopener"&gt;zookeeper&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/apache/zookeeper" target="_blank" rel="noopener"&gt;apache/zookeeper&lt;/a&gt;
)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rancher.com/" target="_blank" rel="noopener"&gt;rancher&lt;/a&gt;
&lt;a href="https://github.com/rancher/metadata" target="_blank" rel="noopener"&gt;metadata-service&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/rancher/rancher" target="_blank" rel="noopener"&gt;rancher/rancher&lt;/a&gt;
, &lt;a href="https://github.com/rancher/metadata" target="_blank" rel="noopener"&gt;rancher/metadata&lt;/a&gt;
)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/jp/systems-manager/" target="_blank" rel="noopener"&gt;AWS Systems Manager パラメータストア&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;環境変数&lt;/li&gt;
&lt;li&gt;ファイル&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="alertmanager"&gt;Alertmanager&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/prometheus/alertmanager" target="_blank" rel="noopener"&gt;Alertmanager&lt;/a&gt;
は&lt;a href="https://github.com/prometheus/prometheus" target="_blank" rel="noopener"&gt;Prometheus&lt;/a&gt;
からのアラートを受け取り、適切にハンドルするためのアプリケーションです。Alertmanagerの設定はYAMLで記述するのですが、SMTPのパスワードや&lt;a href="https://slack.com" target="_blank" rel="noopener"&gt;Slack&lt;/a&gt;
の&lt;a href="https://api.slack.com/incoming-webhooks" target="_blank" rel="noopener"&gt;Incoming Webhook URL&lt;/a&gt;
等、平文でバージョン管理システムに入れるのは躊躇われるデータを含みます。しかし、環境変数などから設定をすることも出来ないため、平文で記述するか、何らかの方法で設定ファイルを編集してから使う必要があります。
特に、Prometheus/Alertmanagerは&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
と併せて使用されることが多いため、出来ればKubernetesのSecret機能を使用したいところです。
そこで&lt;code&gt;confd&lt;/code&gt;をinitContainerで使用して、設定ファイルを生成します。&lt;/p&gt;
&lt;p&gt;まず、テンプレートを作成します。Alertmanagerの設定ファイルを用意し、後から挿入したい部分をテンプレート文字列で置換しておきます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;slack_api_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;{{&lt;span class="l"&gt;getenv &amp;#34;ALERTMANAGER_SLACK_URL&amp;#34;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;slack&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;receivers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;slack&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;slack_configs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;#alert&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;今回は例なので、細かい設定の一切を省いた形にしました。上記の内容で、&lt;code&gt;alertmanager.yml.tmpl&lt;/code&gt;として保存しました。&lt;/p&gt;</description></item><item><title>ファイナルカツカレーをつくった</title><link>https://blog.web-apps.tech/final-katsu-curry/</link><pubDate>Wed, 15 Aug 2018 14:04:46 +0000</pubDate><guid>https://blog.web-apps.tech/final-katsu-curry/</guid><description>&lt;p&gt;連休も終わりで、明日から出社するのがつらいのでファイナルカツカレーを作りました。
ファイナルカツカレーは要するに、ファイナルカレーにカツを乗せたものです。
ファイナルカレーは&lt;a href="https://amzn.to/2BdlmG1" target="_blank" rel="noopener"&gt;いちばんおいしい家カレーをつくる&lt;/a&gt;
に書かれているカレーで、我らがバイブルである&lt;a href="https://amzn.to/2BcQ3en" target="_blank" rel="noopener"&gt;めしにしましょう(4)&lt;/a&gt;
で紹介されています。
素晴らしいカレーであるとのことなので、やはりカツは素晴らしいカツを乗せたいものと思いますので、&lt;a href="https://blog.web-apps.tech/super-katsudoon/"&gt;超級カツ丼&lt;/a&gt;
の時にもやった、低温調理カツでやっていきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_191603_hu_4c5389e64f56ab41.jpg" alt="onion" /&gt;
&lt;/p&gt;
&lt;p&gt;まずはタマネギを炒めていきます。これは一個分です。結構大きめのタマネギを買ってきました。
割とざっくりした粗みじん切りです。昨日包丁を研いだので目が痛くない。
強火で炒めて、焦げ付きそうになったら少し水を足す、という作業を繰り返します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_193217_hu_51727066a38e4cb0.jpg" alt="add-vegi" /&gt;
&lt;/p&gt;
&lt;p&gt;良い感じになったら香味野菜類を追加します。にんじん・セロリ・ニンニク・ショウガ・ホールトマトですね。めしにしましょうではミキサーでやっていく風に書かれていましたが、我が家にはミキサーが無く、このために買うのも何かと思ったので、にんじんはみじん切り、セロリとニンニク・ショウガはすりおろしてみました。ニンニクをすりおろす小さいおろし金でセロリみたいな大きいものをすりおろすのはつらいです。ホールトマトは缶でしか売ってなかったので余りました。どうしよう。
ここでバターをちょいと加えます。切れてるバターが便利でした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_193459_hu_9b129dfce4df6bd4.jpg" alt="spice" /&gt;
&lt;/p&gt;
&lt;p&gt;水分が飛んできたらスパイスを足します。ターメリック・レッドチリ・クミン・コリアンダーです。これらは&lt;a href="https://getnews.jp/archives/1781558" target="_blank" rel="noopener"&gt;基本のカレー&lt;/a&gt;
を作るのにも使える、基本的なスパイスなので、まぁ買っておいても良いでしょう。我が家は以前基本のカレーを作るのに買ったので、冷蔵庫に入ってました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_193604_hu_b62a63ed0992ec7d.jpg" alt="paste" /&gt;
&lt;/p&gt;
&lt;p&gt;もうペーストです。ドライカレーとかの方が近い見た目。鍋を振るとひっくり返せます&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_193707_hu_fbf2440965fa3b9e.jpg" alt="pork" /&gt;
&lt;/p&gt;
&lt;p&gt;肉です。豚肩ロースを適当な大きさに切り、梅酒と少々の醤油につけたものです。1時間くらい前につけて冷蔵庫にぶち込みました。梅酒は自家製です。今年つけたのを使いました。カツを乗せるので肉はいらないかとも思ったのですが、一応。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_193819_hu_d6b9bbb0bc191e49.jpg" alt="add-pork" /&gt;
&lt;/p&gt;
&lt;p&gt;ペーストに肉をぶち込みます。つけ汁もそのまま。ちょっと緩くなります。
このまま少し炒めます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_194220_hu_16d0ae33c8063f02.jpg" alt="consome" /&gt;
&lt;/p&gt;
&lt;p&gt;良い感じになったのでコンソメ汁を投入。300mlのお湯にコンソメキューブを溶かしたものです。300ml入る良い感じのマグカップが無くて難儀。ローリエとはちみつ、醤油を加えて煮込みます。45分ほど煮込んだら、カレールゥを適当に突っ込みます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_203038_hu_439a4290ea759c8c.jpg" alt="pork_sous" /&gt;
&lt;/p&gt;
&lt;p&gt;煮込んでいる間にカツをやっていきます。カレーにカツをのせることで人間は幸せになるのです。これは昨晩仕込んだ豚肩ロースで、&lt;a href="https://anovaculinary.com/" target="_blank" rel="noopener"&gt;Anova&lt;/a&gt;
を使用して、62度で24時間やったものです。めしにしましょうではカツをやるのに63度12時間でしたが、24時間やるつもりだったので1度下げました。それにしてもまずそうである。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_203129_hu_f056a21263ae535a.jpg" alt="cut_pork" /&gt;
&lt;/p&gt;
&lt;p&gt;切ったもの。断面は素晴らしいですね。カツにしましょう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_204726_hu_2c2e1af96477bb60.jpg" alt="fried" /&gt;
&lt;/p&gt;
&lt;p&gt;カツです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_204804_hu_a5d9ebc502c7dfce.jpg" alt="cut_fried" /&gt;
&lt;/p&gt;
&lt;p&gt;断面。スマホです。むしろこのまま食べたくなってきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/final-katsu-curry/images/P_20180815_205622_hu_29feab3a5c339c92.jpg" alt="curry" /&gt;
&lt;/p&gt;
&lt;p&gt;実は以前にも一度、&lt;a href="http://www.gotoken.hakodate.jp/" target="_blank" rel="noopener"&gt;五島軒&lt;/a&gt;
のカレー缶を使ってカツカレーを作ったのですが、超級カツを乗せるとカレーが見えなくなるのが欠点です。左上のお茶はジャスミン茶です。沖縄でさんぴん茶を飲んでから飲めるようになりました。というかむしろハマってます。&lt;/p&gt;
&lt;p&gt;ファイナルカツカレーは、罪の味がします。人間が幸せになるためにはやはりカレーにカツをのせねばならないと、そう感じるものです。ファイナルカレー自体は少し薄い味というか、もういっこカレールゥを足してもよかったかもしれないです。&lt;/p&gt;</description></item><item><title>外部サービスをIngress backendとして使用する</title><link>https://blog.web-apps.tech/use-external-service-for-ingress-backend/</link><pubDate>Tue, 07 Aug 2018 02:20:57 +0000</pubDate><guid>https://blog.web-apps.tech/use-external-service-for-ingress-backend/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Service type: ExternalName&lt;/code&gt;を使用する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="external-service"&gt;External Service&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
では、&lt;a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" target="_blank" rel="noopener"&gt;&lt;code&gt;Ingress&lt;/code&gt;&lt;/a&gt;
を使用することで、ホスト名ベースのロードバランシング/リバースプロキシを行うことが出来ます。その際、プロキシ先としてKubernetes上の&lt;a href="https://kubernetes.io/docs/concepts/services-networking/service/" target="_blank" rel="noopener"&gt;&lt;code&gt;Service&lt;/code&gt;&lt;/a&gt;
を指定するのですが、場合によってはKubernetesクラスタ外のサービスをプロキシ先としたい場合があります。例えば、弊宅の環境では、次の様にプロキシしています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/use-external-service-for-ingress-backend/images/arch-1_hu_47ef548059485d87.png" alt="arch-1" /&gt;
&lt;/p&gt;
&lt;p&gt;基盤であるOpenNebulaのダッシュボード以外は&lt;code&gt;*.web-apps.tech&lt;/code&gt;として、Kubernetesへとルーティングしています。&lt;/p&gt;
&lt;p&gt;ところで、本ブログは現在Kubernetes上へ移行作業中です。今のところはまだ、Kubernetes上へ載せていません。しかし、折角プロキシの設定が減っているので、&lt;code&gt;blog.web-apps.tech&lt;/code&gt;も&lt;code&gt;Ingress&lt;/code&gt;リソースとして管理したいです。&lt;/p&gt;
&lt;p&gt;そこで使用できるのが&lt;code&gt;Service type: ExternalName&lt;/code&gt;です。&lt;code&gt;ExternalName&lt;/code&gt;として外部サービスを登録することで、&lt;code&gt;Ingress&lt;/code&gt;のバックエンドとして使用できるようになります。&lt;/p&gt;
&lt;h2 id="設定"&gt;設定&lt;/h2&gt;
&lt;p&gt;設定はごく簡単で、次の様にします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Namespace&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;external-services&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ghost&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;external-services&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ExternalName&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;externalName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;192.168.1.41&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 本ブログのローカルIP&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;今後も何かの拍子でKubernetesに載せたくないサービスが増える可能性もあるため、&lt;code&gt;external-services&lt;/code&gt;として名前空間を分離しました。このように設定すると、&lt;code&gt;kubectl&lt;/code&gt;からは次の様に見えます。&lt;/p&gt;</description></item><item><title>ingress-nginxを使用してオンプレでもIngressを使用する</title><link>https://blog.web-apps.tech/ingress-nginx-on-prem/</link><pubDate>Mon, 06 Aug 2018 05:37:02 +0000</pubDate><guid>https://blog.web-apps.tech/ingress-nginx-on-prem/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ingress-nginxを使用するとオンプレでも&lt;code&gt;Ingress&lt;/code&gt;を使用出来る&lt;/li&gt;
&lt;li&gt;MetalLBと組み合わせる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ingress"&gt;Ingress&lt;/h2&gt;
&lt;p&gt;Ingressは&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
の機能の一つで、L7 LoadBalancerの機能を持ちます。&lt;a href="https://blog.web-apps.tech/type-loadbalancer_by_metallb/"&gt;先日紹介した&lt;/a&gt;
&lt;code&gt;type LoadBalancer&lt;/code&gt;は、L4 LoadBalancerで、クラスタ内のDNSで名前解決をし、IP制限などをすることが出来ます。それに対し、&lt;code&gt;Ingress&lt;/code&gt;では、HTTPSの終端となることが出来、ホスト名ベース・パスベースのルーティングを行うことが出来ます。&lt;/p&gt;
&lt;p&gt;通常、オンプレでKubernetesを構築した場合、Ingress Controllerと呼ばれる、Ingressを作成する機能が無いために&lt;code&gt;Ingress&lt;/code&gt;を使用することが出来ません。
しかし、折角Kubernetesを使用しているのに、ホスト名ベースのルーティングをクラスタ外のロードバランサーに設定するのは面倒です。
どうせなら&lt;code&gt;Ingress&lt;/code&gt;、使いたいですね？&lt;/p&gt;
&lt;p&gt;そこで使用できるのが&lt;a href="https://kubernetes.github.io/ingress-nginx/" target="_blank" rel="noopener"&gt;ingress-nginx&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener"&gt;kubernetes/ingress-nginx&lt;/a&gt;
)です。ingress-nginxはその名のとおり、nginxを使用したIngress Controllerです。&lt;code&gt;Ingress&lt;/code&gt;リソースの作成時に、nginxの設定を&lt;code&gt;ConfigMap&lt;/code&gt;として保存することで&lt;code&gt;Ingress&lt;/code&gt;の作成を実現します。&lt;/p&gt;
&lt;h2 id="install"&gt;Install&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://blog.web-apps.tech/type-loadbalancer_by_metallb/"&gt;MetalLBをインストール&lt;/a&gt;
している場合、次の二つのコマンドを実行することでインストールできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/cloud-generic.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;二行目のコマンドは&lt;a href="https://kubernetes.github.io/ingress-nginx/deploy/" target="_blank" rel="noopener"&gt;ドキュメント上では&lt;/a&gt;
docker for macのコマンドとして記載されていますが、&lt;code&gt;type: LoadBalancer&lt;/code&gt;が使用できるクラスタ一般で使用できます。&lt;/p&gt;
&lt;p&gt;インストールが完了したら、ingress-nginxのサービスにIPアドレスが割当たります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl get svc -n ingress-nginx
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME TYPE CLUSTER-IP EXTERNAL-IP PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt; AGE
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;default-http-backend ClusterIP 10.233.50.56 &amp;lt;none&amp;gt; 80/TCP 2d
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ingress-nginx LoadBalancer 10.233.47.246 192.168.1.100 80:30431/TCP,443:30017/TCP 2d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;実際にブラウザでingress-nginxのIPアドレスにアクセスしてみて、&lt;strong&gt;default backend - 404&lt;/strong&gt;と表示されれば正常に動作しています。&lt;/p&gt;</description></item><item><title>MetalLBを使用してオンプレでもtype: LoadBalancerを使用する</title><link>https://blog.web-apps.tech/type-loadbalancer_by_metallb/</link><pubDate>Sun, 05 Aug 2018 15:02:11 +0000</pubDate><guid>https://blog.web-apps.tech/type-loadbalancer_by_metallb/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;MetalLBを使用することでオンプレ(not on OpenStack)に構築したk8sでも&lt;code&gt;type: LoadBalancer&lt;/code&gt;を使用できる&lt;/p&gt;
&lt;h2 id="type-loadbalancer"&gt;type: LoadBalancer&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/kubernetes-incubator/kubespray" target="_blank" rel="noopener"&gt;kubespray&lt;/a&gt;
等を使用して、&lt;a href="https://k8s.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
をオンプレ(on OpenStackを除く)で構築した場合、通常、&lt;a href="https://k8s.io/docs/concepts/services-networking/service/#loadbalancer" target="_blank" rel="noopener"&gt;type: LoadBalancer&lt;/a&gt;
を使用することができません。これは、&lt;code&gt;type: LoadBalancer&lt;/code&gt;は通常CloudProviderにより管理されており、オンプレ(on OpenStackを除く)でk8sを構築した場合にはCloudProvider連携が無いためです。&lt;/p&gt;
&lt;p&gt;しかし、k8sを使用するからには&lt;code&gt;type: LoadBalancer&lt;/code&gt;も使用したいですよね？NodePortなどで代用するにも、ポートがバラバラになってしまって面倒です。
そこで使用できるのが&lt;a href="https://metallb.universe.tf/" target="_blank" rel="noopener"&gt;MetalLB&lt;/a&gt;
(GitHub: &lt;a href="https://github.com/google/metallb" target="_blank" rel="noopener"&gt;google/metallb&lt;/a&gt;
)です。
MetalLBを使用すると、&lt;code&gt;type LoadBalancer&lt;/code&gt;の作成をフックしてアドレス割り当てとアドレスの広報を行ってくれます。&lt;/p&gt;
&lt;h2 id="layer-2-mode"&gt;Layer 2 mode&lt;/h2&gt;
&lt;p&gt;MetalLBにはLayer 2 mode(以下L2 mode)とBGP modeがあります。これらのモードはアドレス広報の仕方が違い、L2 modeではARP/NDPで、BGP modeではその名の通りBGPでアドレスの広報を行います。通常、自宅を含むオンプレ環境ではBGPを使用していないと思いますので、L2 modeについて解説します。&lt;/p&gt;
&lt;p&gt;L2 modeでは、特定のノードへアクセスを集中させ、kube-proxyによって各サービスへトラフィックを分配します。そのため、実態としてはロードバランサーが実装されている訳ではないことに注意が必要です。単体ノードにアクセスが集中するため、これがボトルネックとなり得ますし、アクセスが集中することになるノードが何らかの理由でアクセスできなくなった場合、フェイルオーバーに10秒程度かかる可能性があります。&lt;/p&gt;
&lt;h3 id="requirements--installation"&gt;requirements &amp;amp; installation&lt;/h3&gt;
&lt;p&gt;導入は非常に簡単ですが、以下の要件を満たしている必要があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;他にネットワークロードバランシングの機能が無いKubernetes 1.9.0以降&lt;/li&gt;
&lt;li&gt;&lt;a href="https://metallb.universe.tf/installation/network-addons/" target="_blank" rel="noopener"&gt;MetalLB対応表&lt;/a&gt;
に記載のあるネットワークで設定されていること&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これに加え、MetalLBで使用することのできるIPv4アドレスを用意しておく必要があります。
私の環境ではk8sのノードが&lt;code&gt;192.168.1.0/24&lt;/code&gt;にあるため、&lt;code&gt;192.168.1.100&lt;/code&gt;から&lt;code&gt;192.168.1.159&lt;/code&gt;までの60個のアドレスをMetalLB用としました。&lt;/p&gt;
&lt;p&gt;要件を満たしていることが確認できたら、MetalLBのインストールを行います。
MetalLBをインストールするには、次のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.7.2/manifests/metallb.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;a href="https://helm.sh/" target="_blank" rel="noopener"&gt;Helm&lt;/a&gt;
を使用してインストールすることもできますが、Chartが最新版ではないので注意しましょう。&lt;/p&gt;
&lt;p&gt;次に、次のようなConfigMapを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ConfigMap&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;metallb-system&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;config&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; address-pools:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; - name: default
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; protocol: layer2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; addresses:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; - 192.168.1.100-192.168.1.159&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;これでMetalLBのセットアップは完了です。パブリッククラウドで使用するように、&lt;code&gt;type: LoadBalancer&lt;/code&gt;を作成するとアドレスプールからIPアドレスが割り当てられ、アクセスできるようになります。
アドレスプールは複数用意することができ、特定のアドレスプールからIPを割り当てたい場合は&lt;code&gt;type: LoadBalancer&lt;/code&gt;のアノテーションに&lt;code&gt;metallb.universe.tf/address-pool: &amp;lt;ADDRESS_POOL_NAME&amp;gt;&lt;/code&gt;を追加します。&lt;/p&gt;</description></item><item><title>Liveness/Readiness Probe</title><link>https://blog.web-apps.tech/liveness-readiness-probe/</link><pubDate>Thu, 26 Jul 2018 05:09:35 +0000</pubDate><guid>https://blog.web-apps.tech/liveness-readiness-probe/</guid><description>&lt;p&gt;&lt;a href="https://kubernetes.io" target="_blank" rel="noopener"&gt;Kubernetes&lt;/a&gt;
によるヘルスチェックには、Liveness ProbeとReadiness Probeと呼ばれる二つのものがあります。これらは混乱しがちな一方、日本語による情報が多くない(2018/07/26現在で、Google検索の1ページ目にヒットするのが4件ほど)ため、ここで一つ情報をまとめておきます。&lt;/p&gt;
&lt;h2 id="共通"&gt;共通&lt;/h2&gt;
&lt;p&gt;Liveness ProbeとReadiness Probeの設定は共通で、&lt;code&gt;Deployment&lt;/code&gt;や&lt;code&gt;Pod&lt;/code&gt;のマニフェスト内で、&lt;code&gt;containers&lt;/code&gt;の中に&lt;code&gt;livenessProbe&lt;/code&gt;と&lt;code&gt;readinessProbe&lt;/code&gt;としてそれぞれ&lt;a href="https://v1-10.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/#probe-v1-core" target="_blank" rel="noopener"&gt;&lt;code&gt;Probe&lt;/code&gt; spec&lt;/a&gt;
を記述します。&lt;/p&gt;
&lt;p&gt;次の項目を設定することが出来ます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;failureThreshold&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Success&lt;/code&gt;状態の時、何回失敗したら&lt;code&gt;Failure&lt;/code&gt;になるか。最小で1回。&lt;/li&gt;
&lt;li&gt;Default: 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;initialDelaySeconds&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;コンテナが起動してからヘルスチェックを始めるまでの秒数。&lt;/li&gt;
&lt;li&gt;Default: 0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;periodSeconds&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;ヘルスチェックの間隔。最小で1秒&lt;/li&gt;
&lt;li&gt;Default: 10&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;successThreshold
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Failure&lt;/code&gt;状態の時、何回成功したら&lt;code&gt;Success&lt;/code&gt;になるか。最小で1回。&lt;/li&gt;
&lt;li&gt;Default: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;timeoutSeconds
&lt;ul&gt;
&lt;li&gt;ヘルスチェックのタイムアウト秒数。最小で1秒。&lt;/li&gt;
&lt;li&gt;Default: 1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;httpGet
&lt;ul&gt;
&lt;li&gt;ヘルスチェックでアクセスするhttpエンドポイントの情報を書く。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;httpGet&lt;/code&gt;の項目は次の様な項目を持ったobjectを書きます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;host&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;対象のホスト名。&lt;/li&gt;
&lt;li&gt;Default: PodのIP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;httpHeaders&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;リクエストのカスタムヘッダ指定。&lt;code&gt;{name: HEADER_NAME, value: HEADER_VALUE}&lt;/code&gt;の形のオブジェクトの配列で書く。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;port&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;アクセスするポート番号または名称&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;path&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;アクセスするパス。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scheme&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;アクセスする際のスキーム。&lt;/li&gt;
&lt;li&gt;Default: HTTP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="liveness-probe"&gt;Liveness Probe&lt;/h2&gt;
&lt;p&gt;一つ目は&lt;strong&gt;Liveness Probe&lt;/strong&gt;です。&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes" target="_blank" rel="noopener"&gt;公式ドキュメント&lt;/a&gt;
には次の様に書いてあります。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;livenessProbe&lt;/code&gt;: Indicates whether the Container is running. If the liveness probe fails, the kubelet kills the Container, and the Container is subjected to its &lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy" target="_blank" rel="noopener"&gt;restart policy&lt;/a&gt;
. If a Container does not provide a liveness probe, the default state is &lt;code&gt;Success&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Future Pattern</title><link>https://blog.web-apps.tech/future-pattern/</link><pubDate>Wed, 04 Jul 2018 15:33:02 +0000</pubDate><guid>https://blog.web-apps.tech/future-pattern/</guid><description>&lt;p&gt;Future Patternは非同期処理パターンの一つで、ある処理を別のスレッドなどで実行し、結果を後で(=未来で)受け取るような処理に用いられるデザインパターンです。
特徴としては、外側に見えている関数などの処理を実行するオブジェクトは、処理を別スレッドに委譲し、後で結果を得ることの出来るFutureと呼ばれるオブジェクトを即座にメインロジックへと返却することです。&lt;/p&gt;
&lt;p&gt;言葉で書いても、何だかよくわからないので、コードを見てみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* package, import part */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// この時点では結果は得られない&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ここで結果を得る&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Futureオブジェクト&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;main&lt;/code&gt;関数から呼び出された&lt;code&gt;Double&lt;/code&gt;関数は、与えられた数を二倍する関数ですが、二倍する処理は呼び出された時点では実行せず、即座にchannelを返します。この、変数名&lt;code&gt;out&lt;/code&gt;のchannelが&lt;strong&gt;Futureオブジェクト&lt;/strong&gt;です。
そのため、数を二倍した結果は、Double関数を呼び出した時点では得られず、後で&lt;code&gt;out&lt;/code&gt;channelから得ることとなります。&lt;/p&gt;</description></item><item><title>array/sliceに対する存在確認関数のベンチマーク</title><link>https://blog.web-apps.tech/benchmark_in_func/</link><pubDate>Tue, 26 Jun 2018 08:30:22 +0000</pubDate><guid>https://blog.web-apps.tech/benchmark_in_func/</guid><description>&lt;p&gt;Pythonでいうところの、次の様な条件式を実現する関数を書きたかった。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;baz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;baz&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;FOOBAR!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;対象がリストの時、普段なら普通にfor文を回すのですが、今回やりたかったのは定数値の一覧にあるかどうか、だったのと、定数の数も少なかったので、とりあえずで以下の様に実装していました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;baz&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;value invalid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;流石に雑すぎるので、リファクタリングしよう、と思ったのですが、「はて、for文挟んだら遅くなったりしないだろうか」などと考えてしまったのでベンチマークを取りました。&lt;/p&gt;
&lt;h3 id="tl-dr"&gt;TL; DR&lt;/h3&gt;
&lt;p&gt;素直にfor文を回しても大して問題はなさそう&lt;/p&gt;
&lt;h3 id="result"&gt;result&lt;/h3&gt;
&lt;p&gt;今回取ったベンチマークは6種類です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;for-range文を回す&lt;/li&gt;
&lt;li&gt;for文を回す&lt;/li&gt;
&lt;li&gt;&lt;code&gt;map[string]struct{}&lt;/code&gt;を集合として取り扱ってみる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;でつなぐ&lt;/li&gt;
&lt;li&gt;switch文を使う&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sort.SearchStrings()&lt;/code&gt;を使う&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;6番目の&lt;code&gt;sort.SearchStrings()&lt;/code&gt;を使う方法は&lt;a href="https://stackoverflow.com/questions/15323767/does-golang-have-if-x-in-construct-similar-to-python" target="_blank" rel="noopener"&gt;stackoverflow&lt;/a&gt;
に書いてあった方法で、二分探索をしてくれるというのでやってみました。&lt;/p&gt;
&lt;p&gt;結果は次の通り。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;BenchmarkInByForRange-4 200000000 9.34 ns/op 0 B/op 0 allocs/op
BenchmarkInByFor-4 100000000 10.1 ns/op 0 B/op 0 allocs/op
BenchmarkInByMap-4 200000000 7.79 ns/op 0 B/op 0 allocs/op
BenchmarkInByAnd-4 1000000000 2.85 ns/op 0 B/op 0 allocs/op
BenchmarkInBySwitch-4 2000000000 1.39 ns/op 0 B/op 0 allocs/op
BenchmarkInBySortSearchStrings-4 10000000 179 ns/op 32 B/op 1 allocs/op
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;まぁ予想通りではあるものの、&lt;code&gt;sort.SearchStrings()&lt;/code&gt;を使う方法は遅いですね。これはこの関数の「事前にリストがソート済みであること」という条件のために関数内でソートをしてるからだと思われます。(実際、ソート済みのリストを使って、関数内でソートをしないようにすると1/4くらいにはなる)&lt;/p&gt;</description></item><item><title>Amazon EKSがGAだと言うので触ってみた</title><link>https://blog.web-apps.tech/amazon-eks-is-now-ga/</link><pubDate>Wed, 06 Jun 2018 02:52:04 +0000</pubDate><guid>https://blog.web-apps.tech/amazon-eks-is-now-ga/</guid><description>&lt;p&gt;AWSのmanaged Kubernetesで、これまでプライベートベータだった&lt;a href="https://console.aws.amazon.com/eks" target="_blank" rel="noopener"&gt;Elastic Container Service for Kubernetes&lt;/a&gt;
が&lt;a href="https://aws.amazon.com/jp/about-aws/whats-new/2018/06/amazon-elastic-container-service-for-kubernetes-eks-now-ga/" target="_blank" rel="noopener"&gt;GAになった&lt;/a&gt;
ということなので、さくっとクラスタを作成してみました。&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;参考にしたのはAWS公式、&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html" target="_blank" rel="noopener"&gt;EKSのGetting Started Guide&lt;/a&gt;
です。&lt;/p&gt;
&lt;p&gt;まずはEKSのページを見てみようとしたところ・・・
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/eks_top_ja_hu_142539013442122f.png" alt="eks_top_ja" /&gt;
ぶっ壊れてますね！これはなんかアレですね。
gettext的なのが上手くいっていないように見えるので、画面下から英語にしてみます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/eks_top_en_hu_efabeb0e93cc05b8.png" alt="eks_top_en" /&gt;
無事、正しいと思われるページが表示されました。
なんか、How it worksの説明の図がちょっとぼやけて見えるのは環境のせいでしょうか。&lt;/p&gt;
&lt;p&gt;扨、ここからGetting Startedしていきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/create_iam_hu_474e39e25d8b4d61.png" alt="create_iam" /&gt;
まずはEKS用のIAMロールを作っていきます。
IAMロール作成画面のサービスリストにEKSが追加されていますので、これを選択します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/eks_usecase_hu_a82e04adad2afb58.png" alt="eks_usecase" /&gt;
ユースケースは一つしかなく、選択済みになっています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/eks_permission_hu_ef58f8b87462b9c7.png" alt="eks_permission" /&gt;
フムー。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/iam_created_hu_59efb1ae8bfed64c.png" alt="iam_created" /&gt;
IAMロールが出来ました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/cf_template_hu_5c0fe8db095f3750.png" alt="cf_template" /&gt;
CloudFormationでクラスタを組んでいきます。
今のところ、EKSが使えるリージョンはUS West(Oregon) (us-west-2)とUS East(N.Virginia) (us-east-1)の二カ所です。今回はUS Eastでやっていきます。&lt;/p&gt;
&lt;p&gt;CloudFormationでCreate Stackをやっていきましょう。
S3 template URLが用意されていますので、これを入力します。
template URLは&lt;code&gt;https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-06-05/amazon-eks-vpc-sample.yaml&lt;/code&gt;です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/cf_template_view_hu_8b1b3f4b587d21df.png" alt="cf_template_view" /&gt;
Viewしてみるとこんな感じです。なるほど。&lt;/p&gt;
&lt;p&gt;細かい設定的なところは全くいじらず、さくさく進めていきます。Stack nameは&lt;code&gt;GettingStarted&lt;/code&gt;にしました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/cf_stack_complete_hu_f1ae54b26c86216a.png" alt="cf_stack_complete" /&gt;
できた。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/amazon-eks-is-now-ga/images/cf_stack_output-1_hu_2a1833050cb6e1db.png" alt="cf_stack_output-1" /&gt;
Outputのタグを選択して、SecurityGroupsとVpcIdとSubnetIdsを(一応)メモっておきます。&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;次にkubectlの設定をしておきます。
最新のkubectl(1.10以降)をインストールしておいてください。まだインストールしていない場合はEKS側でも配信しているようなのでそれを使ってもOKです。&lt;/p&gt;
&lt;p&gt;EKSでは認証にheptio-authenticator-awsを使用するようなので、こちらもドキュメントに従い導入します。
私はいろいろ考えるのが面倒だったため、&lt;code&gt;go get&lt;/code&gt;しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get -u -v github.com/heptio/authenticator/cmd/heptio-authenticator-aws
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ヘルプを表示して、正常に導入出来たかざっくり確認します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ heptio-authenticator-aws &lt;span class="nb"&gt;help&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ここで注意なのですが、ガイドでは&lt;strong&gt;Download and Install the Latest AWS CLI&lt;/strong&gt;のところに&lt;strong&gt;Optional&lt;/strong&gt;ってついてるんですが、これはほぼ必須です。
AWS CLIがないとクラスタに接続出来ないので、AWS CLIをインストールしておきます。&lt;/p&gt;</description></item><item><title>超級カツ丼をAnovaでやった</title><link>https://blog.web-apps.tech/super-katsudoon/</link><pubDate>Mon, 04 Jun 2018 10:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/super-katsudoon/</guid><description>&lt;p&gt;&lt;a href="https://amzn.to/2J8onek" target="_blank" rel="noopener"&gt;めしにしましょう&lt;/a&gt;
に出ていた、超級カツ丼をAnovaを使ってやってみました。&lt;/p&gt;
&lt;iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=nasa9084-22&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=as_ss_li_til&amp;asins=B01N8Q8DA7&amp;linkId=acf882d00d695d1ad1796d9ee199c920"&gt;&lt;/iframe&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180530_211744_hu_918f91472ac87646.jpg" alt="preheating" /&gt;
まずはお湯を予熱しておきます。58度です。
給湯器で温度を上げたお湯を使うと調理開始が早くなる、ということを学びました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180530_211854_hu_6599f116446869e2.jpg" alt="pork" /&gt;
今回のお肉はこちら。近所の西友で97円/100gのアメリカ産豚肩ロース522gです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180530_212656_hu_defa8b36b4d7205e.jpg" alt="packing" /&gt;
適当にIKEAのジップロックっぽいやつに入れて空気を抜いておきます。
&lt;a href="https://blog.web-apps.tech/anova-hello-world/"&gt;前回&lt;/a&gt;
に比べて重いせいか大きいせいか、あまり上手く空気を抜けませんでした。
ちょっと不安だったものの、まぁイケるでしょとそのままやっていきです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180530_212807_hu_71c3643f3473c6c0.jpg" alt="heating" /&gt;
投入。今回は24時間(!)やっていきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180531_205323_hu_ce6ac3eb617c997b.jpg" alt="heated" /&gt;
24時間たったお肉がこちら。おいしくなさそう。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180531_202055_hu_2a6e3039c01ae7b8.jpg" alt="onion" /&gt;
タマネギをスライス(スライサーなどないので包丁で薄切り)していきます。指を少しそぎました。痛い。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180531_205431_hu_8eb07bc18245a41.jpg" alt="cut_pork" /&gt;
肉は四分割しました。
ブロックの向きによっては二枚でも良かったんですが、油の方向的にこうなりました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180531_210933_hu_9b7de65f9187824b.jpg" alt="coating" /&gt;
衣をつけた様子。塩こしょうを振って、小麦粉→卵→パン粉→卵→パン粉です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180531_211840_hu_f6c42dc22db61c58.jpg" alt="fried" /&gt;
揚げました。200度の油で20秒です。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180531_212641_hu_2a4cad52df0237d8.jpg" alt="done" /&gt;
卵でとじて御飯の上にドーンしたのがこちら。卵でとじる作業は戦争なので写真を撮っていませんでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/super-katsudoon/images/IMG_20180531_213153_hu_79d119afc109097a.jpg" alt="thick" /&gt;
アツい。&lt;/p&gt;
&lt;p&gt;大変柔らかく、おいしかったです。
一部筋っぽいのが残ってたところもあったので、下処理とかした方が良かったのかもしれないですね。
あと、二人分にしては多かったので次はもう少し人数を確保した方がよいと思いました。&lt;/p&gt;</description></item><item><title>Anovaが届いたのでHello Worldした</title><link>https://blog.web-apps.tech/anova-hello-world/</link><pubDate>Wed, 30 May 2018 13:24:37 +0000</pubDate><guid>https://blog.web-apps.tech/anova-hello-world/</guid><description>&lt;p&gt;去る5月12日、肉の祭典であるところの&lt;a href="https://medium.com/@lestrrat/builderscon-%E4%BD%8E%E6%B8%A9%E8%AA%BF%E7%90%86%E8%82%89%E4%BC%9A-2018-spring-8c09ea955372" target="_blank" rel="noopener"&gt;builderscon 低温調理肉会 2018 Spring&lt;/a&gt;
が開催されました。
その名の通り、Anovaで低温調理された肉をひたすら食うというイベントで、大変に楽しみにしていました。
が、家を出るぞ！という段になって&lt;a href="https://blog.web-apps.tech/i-went-to-kubecon-cloudnativecon-eu-2018/"&gt;KubeCon&lt;/a&gt;
の時にやらかしたぎっくり腰を再発し、行くことかなわず、気づいたら&lt;a href="https://amzn.to/2IXM4Gc" target="_blank" rel="noopener"&gt;Anova&lt;/a&gt;
をポチってしまっていました。&lt;/p&gt;
&lt;iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="//rcm-fe.amazon-adsystem.com/e/cm?lt1=_blank&amp;bc1=000000&amp;IS2=1&amp;bg1=FFFFFF&amp;fc1=000000&amp;lc1=0000FF&amp;t=nasa9084-22&amp;o=9&amp;p=8&amp;l=as4&amp;m=amazon&amp;f=ifr&amp;ref=as_ss_li_til&amp;asins=B00XV556OQ&amp;linkId=1a430911d48ae55d1c7045f4c8dc0b6f"&gt;&lt;/iframe&gt;[^amzn]
&lt;p&gt;そのAnovaが我が家に届いたので、真空低温調理のHello Worldとも言えるローストビーフをつくりました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_155448_hu_d07e9171c92ee391.jpg" alt="anova_box" /&gt;
&lt;/p&gt;
&lt;p&gt;ネット上でブログ記事とか見てると、筒状の箱に入っている写真も多いのですが、最近は普通の箱に入ってくるようです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_155529_hu_ea79f3a0250a18e6.jpg" alt="anova_paper" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_155548_hu_8db01c10c1ebcc9d.jpg" alt="anova_paper_rev" /&gt;
中に入ってた紙には基本的な加熱時間なんかも書いてあります&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_155614_hu_e696ee7568c6a0c3.jpg" alt="anova1" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_155705_hu_2f972f364266df3f.jpg" alt="anova2" /&gt;
Anovaさんとご対面。かれこれ一年近く買うか悩んでたので、ようやく、といったお気持ちです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_184843_hu_7037e6191a136cdf.jpg" alt="bucket" /&gt;
我が家にあった鍋だと、使えなくはないのですがもう少し余裕がほしいと感じたのでAnovaさんの異名を持つ&lt;a href="https://twitter.com/lestrrat" target="_blank" rel="noopener"&gt;@lestrratさん&lt;/a&gt;
の&lt;a href="https://medium.com/makisanch/%E3%83%91%E3%83%B3%E3%83%89%E3%83%A9%E3%81%AE%E7%AE%B1-anova%E3%81%AB%E3%82%88%E3%82%8B%E4%BD%8E%E6%B8%A9%E8%AA%BF%E7%90%86-%E3%82%92%E9%96%8B%E3%81%91%E3%81%9F-a619877bd388" target="_blank" rel="noopener"&gt;ブログ記事を参考&lt;/a&gt;
にして、バケツを購入してきました。
近所(と言っても徒歩10分からのバスで10分程度かかる)ホームセンターで、&lt;a href="https://amzn.to/2slSuDG" target="_blank" rel="noopener"&gt;トンボ ニューセレクトバケツ15L&lt;/a&gt;
を購入(余談ですが、このバケツは食品衛生法適合商品なので調理に使うことに何の問題もありません)。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_185535_hu_bb955213631e8687.jpg" alt="set_anova" /&gt;
お湯を張ってanovaをセット。温度表示も摂氏に変更しました。
58度にセットして余熱しておきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_185617_hu_c91e9ca27a0bb080.jpg" alt="beef_pack" /&gt;
今回調理したのはこちらの牛肉モモブロック862円。近所の西友で購入しました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_190114_hu_ddc794ab751e7add.jpg" alt="beef_spice" /&gt;
適当に筋を取ってからスパイスをまぶしていきます。
今回はローストビーフ用スパイスなるものが牛肉に付属していたので、それを使ってみました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_190535_hu_8ddc6aecd779cb19.jpg" alt="packing" /&gt;
&lt;a href="https://www.ikea.com/jp/ja/catalog/products/60340412/" target="_blank" rel="noopener"&gt;IKEAのジップロック的な袋&lt;/a&gt;
に入れて、空気を適当に抜きました。&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_200038_hu_9b81f39bea95733a.jpg" alt="warming" /&gt;
肉を投入。クリップなんかで袋を止めると良い、みたいな記事が多かったのですが、ぱっと使えそうなクリップが無かったのでどこのご家庭にもあるであろう緑の養生テープでとめておきました。
この状態で2時間やっていきます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_220439_hu_8043ba025c5b34cb.jpg" alt="warmed" /&gt;
できあがったものがこちら。見た目は良くないです。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180526_221028_hu_67ff521190f2b56f.jpg" alt="fire" /&gt;
フライパンで焼き目をつけていきます。
ガスバーナーがほしい。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180527_110415_hu_1b13a2abd7977f40.jpg" alt="cut" /&gt;
切ってみました。素晴らしいピンク色。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180527_110802_hu_7da3ce14cfd8da07.jpg" alt="slice" /&gt;
スライスしたものがこちら。ローストビーフを良い感じに薄くスライスするの、難しいですね。
誰かこつを教えてください。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/anova-hello-world/images/IMG_20180527_220827_hu_3925268921cd0df.jpg" alt="IMG_20180527_220827" /&gt;
最終的に御飯の上でドーンな感じになりました。
温玉もanovaでやったやつ。ちょっと堅かった気がします。&lt;/p&gt;
&lt;p&gt;おいしかった。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;袋を水につけて(水が入らないように)、空気を抜くとそこそこ真空っぽい感じになります。&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>slimduetを使って海外でインターネット接続を確保する</title><link>https://blog.web-apps.tech/using-slimduet/</link><pubDate>Mon, 07 May 2018 08:50:39 +0000</pubDate><guid>https://blog.web-apps.tech/using-slimduet/</guid><description>&lt;p&gt;先日、&lt;a href="https://blog.web-apps.tech/i-went-to-kubecon-cloudnativecon-eu-2018/"&gt;初めて海外に行ってきた&lt;/a&gt;
んですが、その際、&lt;a href="https://www.slimduet.net/" target="_blank" rel="noopener"&gt;slimduet&lt;/a&gt;
というeSIM(ソフトウェア的な設定で通信事業者を変更出来るSIM)を使用してネットワーク通信をしたので、設定方法などをまとめておきます。&lt;/p&gt;
&lt;h2 id="前提"&gt;前提&lt;/h2&gt;
&lt;p&gt;端末は&lt;a href="https://www.freetel.jp/product/smartphone/kiwami2/" target="_blank" rel="noopener"&gt;FREETELのKiwami 2&lt;/a&gt;
(Androidのバージョンは6)、行き先はデンマーク/コペンハーゲンです。&lt;/p&gt;
&lt;h2 id="設定"&gt;設定&lt;/h2&gt;
&lt;h3 id="simを購入する"&gt;SIMを購入する&lt;/h3&gt;
&lt;p&gt;slimduetを使用するには専用のeSIMが必要ですので、&lt;a href="https://www.slimduet.net/" target="_blank" rel="noopener"&gt;公式サイト&lt;/a&gt;
やAmazon(記事執筆時点では在庫なし)から購入しておきます。&lt;/p&gt;
&lt;p&gt;SIMカードの価格はは2000円を切る程度です。&lt;/p&gt;
&lt;h3 id="slimduetのアプリをインストールする"&gt;slimduetのアプリをインストールする&lt;/h3&gt;
&lt;p&gt;slimduetを使用するには、専用のアプリをインストールする必要があります。
Google Playで&lt;a href="https://play.google.com/store/apps/details?id=com.greenroam.slimduet" target="_blank" rel="noopener"&gt;slimduet&lt;/a&gt;
と検索し、インストールします。&lt;/p&gt;
&lt;p&gt;勿論、この段階では別途データ通信が出来る必要があります。&lt;/p&gt;
&lt;h3 id="プランを購入する"&gt;プランを購入する&lt;/h3&gt;
&lt;p&gt;slimduet SIMを端末に挿入してから、行き先に併せたプランを購入します。
この段階では、Wi-Fiなどのデータ通信が出来る必要がありますので、空港やホテルのWi-Fi等を使用するか、日本国内にいる内に購入しておきます。&lt;/p&gt;
&lt;p&gt;slimduetアプリを起動すると、行き先の検索画面が表示されますので、行き先を入力し検索します。
今回はデンマークですので、「デンマーク」と入力し、&lt;strong&gt;検索バー横のルーペボタンを押します&lt;/strong&gt;(キーボードの&lt;strong&gt;Go&lt;/strong&gt;や&lt;strong&gt;Done&lt;/strong&gt;、エンターなどでは検索されないので注意)。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200639_hu_be3b3f5f7bca12fb.png" alt="search_screen" /&gt;
&lt;/p&gt;
&lt;p&gt;おすすめプラン、ということでデンマークで使えるプランが表示されますので、選択します。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180505-104656_hu_59a553927b110a6a.png" alt="plan" /&gt;
&lt;/p&gt;
&lt;p&gt;国別プランを選択すると画面が変わり、1日間、3日間などのプランが表示されますので、日程にあわせた期間のプランを選択します。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200652_hu_1d820c851365ebb.png" alt="plan_detail" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200701_hu_aa3d330b94ed97d6.png" alt="purchase" /&gt;
&lt;/p&gt;
&lt;p&gt;クレジットカードなどで購入手続きをした後、画面下部の「私の電話番号」を押し、購入したプランが表示されていることを確認します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200731_hu_1664cfb8f7ba51ca.png" alt="my_phone_num" /&gt;
&lt;/p&gt;
&lt;p&gt;また、この段階でSMSで購入したプランについてメッセージが来るはずです。&lt;/p&gt;
&lt;h3 id="電話番号を切り替える"&gt;電話番号を切り替える&lt;/h3&gt;
&lt;p&gt;自動電話番号切り替えに対応した端末では、プランの「詳細」から、「携帯電話番号の切り替え」を押すことで切り替えることが出来ます。&lt;/p&gt;
&lt;p&gt;Kiwami 2は対応していないため、SIM Toolkitを使用して番号の切り替えを行います。
AndroidのアプリドロワーからSIM Toolkitを起動します。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200747_hu_9bb3e0559afd7cc0.png" alt="drawer" /&gt;
&lt;/p&gt;
&lt;p&gt;SIM Toolkitを起動すると、SIMの一覧が表示されるので、slimduetかな？と思われるものを選択します。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200751-1_hu_63b1b4c8e1f0097.png" alt="sim_toolkit_1" /&gt;
&lt;/p&gt;
&lt;p&gt;SIMを選択したら、「携帯電話番号を切り替え」、「ご利用する携帯電話番号を選択してください」の順で選択します。
「携帯電話番号を切り替え」のあと、「設定」を選択したくなりますが、こちらではないため注意します(図の赤枠で示した部分を選択します)。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200803_hu_1ccbea886ebfdfbe.png" alt="sim_toolkit_2" /&gt;
&lt;/p&gt;
&lt;p&gt;購入したプランが表示されますので、選択します。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200806-1_hu_500c1fdde67cfd93.png" alt="sim_toolkit_3" /&gt;
&lt;/p&gt;
&lt;h3 id="apnの設定をする"&gt;APNの設定をする&lt;/h3&gt;
&lt;p&gt;電話番号の切り替えが出来たら、APNの設定をします。
Androidの設定から、「SIMカードとモバイル通信」の設定画面を開きます。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200817_hu_f4feff90fe61f5c9.png" alt="settings" /&gt;
&lt;/p&gt;
&lt;p&gt;「モバイルネットワーク設定」を開き、データ通信を有効にする、データローミング、にそれぞれチェックを入れます。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200821_hu_d2219d1eba32e76.png" alt="settings_sim" /&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200824-1_hu_e298465085a7241e.png" alt="data" /&gt;
&lt;/p&gt;
&lt;p&gt;「アクセスポイント名」の設定画面を開き、右上の &lt;strong&gt;+&lt;/strong&gt; からAPNの設定を追加します。
名前は適当なもの(slimduetなど)を入力し、APNを &lt;code&gt;uinternet&lt;/code&gt;として保存します。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200835_hu_dcd73a3d0835287d.png" alt="set_ap" /&gt;
&lt;/p&gt;
&lt;p&gt;保存したら、作成したAPN設定を選択します。
&lt;img loading="lazy" src="https://blog.web-apps.tech/using-slimduet/images/Screenshot_20180502-200827_hu_a92daf2e1c53e6c4.png" alt="choose_ap" /&gt;
この時点でデータ通信が出来るようになっているハズです。&lt;/p&gt;
&lt;p&gt;この時点でデータ通信が出来ない場合、通信事業者を適切なものに設定する必要がある可能性があります。&lt;/p&gt;</description></item><item><title>KubeCon + CloudNativeCon Europe 2018にいってきた</title><link>https://blog.web-apps.tech/i-went-to-kubecon-cloudnativecon-eu-2018/</link><pubDate>Mon, 07 May 2018 07:08:58 +0000</pubDate><guid>https://blog.web-apps.tech/i-went-to-kubecon-cloudnativecon-eu-2018/</guid><description>&lt;p&gt;過ぎし5月1日〜5月6日、出張で&lt;a href="https://events.linuxfoundation.org/kubecon-eu-2018/" target="_blank" rel="noopener"&gt;KubeCon + CloudNativeCon Europe 2018&lt;/a&gt;
に行ってきました！&lt;/p&gt;
&lt;p&gt;KubeConは&lt;a href="https://kubernetes.io/" target="_blank" rel="noopener"&gt;Kubernetes(k8s)&lt;/a&gt;
のイベントで、&lt;a href="https://www.cncf.io/" target="_blank" rel="noopener"&gt;Cloud Native Computing Foundation(CNCF)&lt;/a&gt;
が主催するCloudNativeConと併せた開催でした。
今回の開催地はデンマークはコペンハーゲンのBella Centerで、実に4000人以上が参加したとのことです。
twitterハッシュタグは&lt;a href="https://twitter.com/hashtag/kubecon" target="_blank" rel="noopener"&gt;#kubecon&lt;/a&gt;
で、一部&lt;a href="https://twitter.com/hashtag/cloudnativecon" target="_blank" rel="noopener"&gt;#cloudnativecon&lt;/a&gt;
も使われていたようです。&lt;/p&gt;
&lt;p&gt;私個人としては初海外で、初日の移動で腰をぎっくりするなど、トラブルに見舞われながらも、なんとかこんとか行ってきました。&lt;/p&gt;
&lt;h2 id="finnair"&gt;finnair&lt;/h2&gt;
&lt;p&gt;今回、飛行機は&lt;a href="https://www.finnair.com/jp/jp/" target="_blank" rel="noopener"&gt;Finnair&lt;/a&gt;
を使用しました。
成田空港からヘルシンキ、ヘルシンキからコペンハーゲンの一回乗り継ぎです。
成田空港からヘルシンキは約10時間、ヘルシンキからコペンハーゲンは約1.5時間のフライトです。&lt;/p&gt;
&lt;p&gt;成田空港からヘルシンキのフライトでは、機内に備え付けのヘッドホンがノイズキャンセラー付きで、意外と音もよく、また、機内食もそこそこおいしかったため、比較的お勧め出来る航空会社かと思います。
成田空港からヘルシンキのフライトはJALも含めたコードシェア便だったため、機内の放送では日本語でも放送される点が安心感があって良いなと感じました。&lt;/p&gt;
&lt;h2 id="the-square"&gt;The Square&lt;/h2&gt;
&lt;p&gt;今回とったホテルはコペンハーゲンの繁華街にほど近い&lt;a href="https://www.thesquarecopenhagen.com/" target="_blank" rel="noopener"&gt;The Square&lt;/a&gt;
というホテルです。
繁華街に近いため、観光にも困らず、飲み会をした後にも戻りやすい立地でした。&lt;/p&gt;
&lt;p&gt;近所には&lt;a href="https://netto.dk/" target="_blank" rel="noopener"&gt;NETTO&lt;/a&gt;
という24時間営業の比較的安いスーパーや、お土産の購入等にも便利な&lt;a href="https://irma.dk/" target="_blank" rel="noopener"&gt;Irma&lt;/a&gt;
という高級スーパーもあり、買い物には困ることがありませんでした。&lt;/p&gt;
&lt;p&gt;繁華街まで脚を伸ばせば、&lt;a href="http://www.hardrock.com/cafes/copenhagen/" target="_blank" rel="noopener"&gt;Hard Rock Cafe&lt;/a&gt;
や、国内でも一時期話題となったSuperdry&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;などもあります。&lt;/p&gt;
&lt;p&gt;また、今回のKubeConのパーティーが&lt;a href="https://www.tivoli.dk/en/" target="_blank" rel="noopener"&gt;Tivoli garden&lt;/a&gt;
での開催だったため、パーティー会場がホテルの隣のブロック、という点でも非常に良い立地でした。&lt;/p&gt;
&lt;p&gt;ホテルそのものも、おしゃれで、清潔な感じのホテルでした。
シャワーが出ないということもありませんでしたし、最低限のアメニティも揃っていました。&lt;/p&gt;
&lt;p&gt;冷蔵庫が壊れていたのか、中の飲み物等を冷やしてくれないのだけが少々残念でした。&lt;/p&gt;
&lt;h2 id="kubecon--cloudnativecon-europe-2018"&gt;KubeCon + CloudNativeCon Europe 2018&lt;/h2&gt;
&lt;p&gt;KubeCon + CloudNativeCon Europe 2018は非常に多くのトラックがあり、その多くのスライドがPDFで公開されています。&lt;/p&gt;
&lt;p&gt;スライドは&lt;a href="https://kccnceu18.sched.com/" target="_blank" rel="noopener"&gt;スケジュール&lt;/a&gt;
からダウンロードすることができます。
また、&lt;a href="https://twitter.com/superbrothers" target="_blank" rel="noopener"&gt;@superbrothers&lt;/a&gt;
さんが一気にダウンロードするスクリプトを書いてくださっているので、こちらを使用することも出来ます。&lt;/p&gt;
&lt;blockquote class="twitter-tweet" data-lang="ja"&gt;&lt;p lang="en" dir="ltr"&gt;I created a script that downloads all KubeCon + CloudNativeCon Europe 2018 slides from Sched! ? &lt;a href="https://t.co/FyD1zhJbNk"&gt;https://t.co/FyD1zhJbNk&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/KubeCon?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#KubeCon&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Kubernetesのセキュリティのベストプラクティス by Ian Lewis</title><link>https://blog.web-apps.tech/k8s-security-best-practices-by-ianlewis/</link><pubDate>Thu, 19 Apr 2018 05:18:30 +0000</pubDate><guid>https://blog.web-apps.tech/k8s-security-best-practices-by-ianlewis/</guid><description>&lt;p&gt;&lt;a href="https://containerdays.jp/" target="_blank" rel="noopener"&gt;Japan Container Days v18.04&lt;/a&gt;
で表題のセッションを聞いたので、まとめました。&lt;/p&gt;
&lt;h2 id="スライド資料"&gt;スライド資料&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://speakerdeck.com/ianlewis/kubernetesfalsesekiyuriteifalsebesutopurakuteisu" target="_blank" rel="noopener"&gt;Kubernetesのセキュリティのベストプラクティス(SpeakerDeck)&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="apiサーバへの攻撃を防ぐ"&gt;APIサーバへの攻撃を防ぐ&lt;/h2&gt;
&lt;h3 id="rbacでpodに付与される権限を絞る"&gt;RBACでPodに付与される権限を絞る&lt;/h3&gt;
&lt;p&gt;Podにはシークレットが自動でマウントされるため、不正アクセスにより読み込まれてしまうと危ない&lt;/p&gt;
&lt;h3 id="firewallでapiサーバへのアクセスについてip制限を付与する"&gt;FirewallでAPIサーバへのアクセスについてIP制限を付与する&lt;/h3&gt;
&lt;p&gt;いざ、シークレットが漏れた場合でも、APIサーバにアクセスされてしまわないように、ファイアウォールでIP制限をかけておくと良い&lt;/p&gt;
&lt;h3 id="networkpolicyでdbへの接続が許可されるpodを制限する"&gt;NetworkPolicyでDBへの接続が許可されるPodを制限する&lt;/h3&gt;
&lt;p&gt;大体の場合、重要なデータはDBに有るため、DBへのアクセスを絞ることで安全性を上げる&lt;/p&gt;
&lt;h4 id="example"&gt;example:&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;NetworkPolicy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;networking.k8s.io/v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;redis&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;podSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;redis&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ingress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;podSelector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;matchLabels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;guestBook&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="ホストへの攻撃を防ぐ"&gt;ホストへの攻撃を防ぐ&lt;/h2&gt;
&lt;p&gt;次の三つを併用すると良い&lt;/p&gt;
&lt;h3 id="non-rootユーザでpodを実行する"&gt;non-rootユーザでPodを実行する&lt;/h3&gt;
&lt;h4 id="example-1"&gt;example:&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;security-context-demo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;securityContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runAsUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="読み込み専用ファイルシステムを使用する"&gt;読み込み専用ファイルシステムを使用する&lt;/h3&gt;
&lt;h4 id="example-2"&gt;example:&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Pod&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;apiVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;v1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;security-context-demo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;securityContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="no_new_privs"&gt;no_new_privs&lt;/h3&gt;
&lt;p&gt;forkしたプロセスが強い権限を持てないようにする&lt;/p&gt;</description></item><item><title>Raspberry PiのヘッドレスインストールでWi-Fiを設定する</title><link>https://blog.web-apps.tech/raspberry-pi-headless-wifi-setup/</link><pubDate>Wed, 18 Apr 2018 09:17:54 +0000</pubDate><guid>https://blog.web-apps.tech/raspberry-pi-headless-wifi-setup/</guid><description>&lt;p&gt;uzullaさんがブログでこんなことを書いてた。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;しかし…/boot/のどこかに起動後実行されるスクリプトがあれば楽なのにな…（そこで無理やりwifi情報を書き込めば良いわけで）
&lt;a href="http://uzulla.hateblo.jp/entry/2018/04/17/134526" target="_blank" rel="noopener"&gt;ヘッドレスRaspberry Pi Zero w(h)のコンソールやネットワークなど初期設定についてメモ - uzullaがブログ&lt;/a&gt;
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;私も過去何度かRaspberry Pi Zeroのヘッドレスインストールをしてまして、実はヘッドレスインストールの時にWi-Fi情報を書き込めるファイルがあるのです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/boot/wpa_supplicant.conf&lt;/code&gt;というファイルで、ここにWi-Fiの設定を書き込んで起動すると、raspbianが&lt;code&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/code&gt;に良い感じにコピーしてくれます。&lt;/p&gt;
&lt;p&gt;上記uzullaさんのブログでいうと、「&lt;strong&gt;microSDのファイルを編集&lt;/strong&gt;」の時に一緒に書き込んでおくと、起動時にその情報を使ってWi-Fiをつかんでくれます。
あとは&lt;code&gt;nmap&lt;/code&gt;するなり、ルータやらDHCPサーバやらのリース状況を確認するなりでラズパイに割当たったIPをゲットして&lt;code&gt;ssh pi@xxx.xxx.xxx.xxx&lt;/code&gt;的にSSHするか、avahi/bonjourをつかって&lt;code&gt;ssh pi@raspberrypi.local&lt;/code&gt;的にSSHするかでログインできます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;wpa_supplicant.conf&lt;/code&gt;の書き方は、上記uzullaさんのブログ記事の、「&lt;strong&gt;Raspberry Pi Zero wにWifiを設定する&lt;/strong&gt;」ってところを見るか、&lt;a href="https://steveedson.co.uk/tools/wpa/" target="_blank" rel="noopener"&gt;ここ&lt;/a&gt;
とか&lt;a href="https://mascii.github.io/wpa-supplicant-conf-tool/" target="_blank" rel="noopener"&gt;ここ&lt;/a&gt;
にジェネレータを作ってくれてる人がいるので、利用して生成すると良いと思います。
パスワードは平文でOKなので、適当な文字列を突っ込んで手元で書き換えると安心かもしれないです。&lt;/p&gt;
&lt;p&gt;なお、NOOBSでやるときは、&lt;code&gt;wpa_supplicant.conf&lt;/code&gt;と&lt;code&gt;ssh&lt;/code&gt;は&lt;code&gt;/boot&lt;/code&gt;ではなく、ルートディレクトリにおけばOKです。
さらに、&lt;code&gt;recovery.cmdline&lt;/code&gt;と言うファイルの&lt;code&gt;quiet&lt;/code&gt;という部分を&lt;code&gt;vncinstall&lt;/code&gt;に書き換えることで起動したNOOBSにVNC接続できるようになります。&lt;/p&gt;</description></item><item><title>TOTPを実装する</title><link>https://blog.web-apps.tech/implementing_totp/</link><pubDate>Fri, 30 Mar 2018 17:03:45 +0000</pubDate><guid>https://blog.web-apps.tech/implementing_totp/</guid><description>&lt;p&gt;ここ数年で多くのサービスで採用されてきている二要素認証ですが、皆さん使っているでしょうか。
私は実は最近までは面倒であまり使っていなかったのですが、ようやく重い腰を上げてあちこち設定しました。
そのうち、近年特によく使われているのがTOTP(Time-Based One-Time Password)と呼ばれるアルゴリズムです。
TOTPアルゴリズムは&lt;a href="https://tools.ietf.org/html/rfc6238" target="_blank" rel="noopener"&gt;RFC6238&lt;/a&gt;
で定義されたアルゴリズムで、サーバとクライアントが共有する秘密鍵および現在時刻から確認用のコードを生成するものです。
RFCや&lt;a href="https://en.wikipedia.org/wiki/Time-based_One-time_Password_algorithm" target="_blank" rel="noopener"&gt;Wikipedia&lt;/a&gt;
を見てわかるよう、かなり簡素なアルゴリズムで、一つ一つ理解していけば比較的簡単に実装することができます。
Go言語のコードを実例に、サンプルコードを実装してみます。&lt;/p&gt;
&lt;h2 id="hotpとtotp"&gt;HOTPとTOTP&lt;/h2&gt;
&lt;p&gt;TOTPアルゴリズムとよく似たものに、HOTP(HMAC-Based One-Time Password)と呼ばれるアルゴリズムがあります。
これは、サーバとクライアントが共有する秘密鍵と、「何回目の認証か」から確認用のコードを生成するアルゴリズムです。
HOTPアルゴリズムは(勿論)アルゴリズムですから、ある計算手順であり、秘密鍵と認証回数を引数にとって認証用コードを返す関数として表すことができます。
この、認証回数という引数に対して、現在時刻を入力したものがTOTPです。
認証「回数」というくらいですから、値は正の整数値です。時刻を整数として入力するため、UnixTimeを使用します。&lt;/p&gt;
&lt;p&gt;実際にはUnixTimeそのままで入力すると1秒ごとに認証用コードが変わってしまい実用できではありませんから、ある秒数を一周期として、現在が何周期目なのか、という値を入力します。&lt;/p&gt;
&lt;h2 id="totpを実装する"&gt;TOTPを実装する&lt;/h2&gt;
&lt;p&gt;扨、前置きはこれくらいにしてTOTPアルゴリズムを実装します。
次の式で表されます。&lt;/p&gt;
&lt;p&gt;\begin{eqnarray*}
TOTP(K, T_0, X) &amp;amp;=&amp;amp; HOTP(K, T(T_0, X)) \\
T(T_0, X) &amp;amp;=&amp;amp; \frac{(CurrentUnixTime - T_0)}{X}
\end{eqnarray*}&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$K$は共有秘密鍵です。&lt;/li&gt;
&lt;li&gt;$T_0$は数えはじめの時間で、通常はUnix epoch、すなわち0を使用します。&lt;/li&gt;
&lt;li&gt;$X$は一周期の秒数で、規定値は30秒です。(実際、多くのサービスが30秒ベースです)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;プログラム実装は以下の様に書いてみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;TOTP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;HOTP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;T&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;T&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;Unix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;簡単ですね。上記の内、定義されていないのは&lt;code&gt;HOTP(K, T)&lt;/code&gt;だけとなりました。&lt;/p&gt;</description></item><item><title>Golang: 配列からスライスに変換する</title><link>https://blog.web-apps.tech/golang-array-to-slice/</link><pubDate>Fri, 16 Mar 2018 02:19:13 +0000</pubDate><guid>https://blog.web-apps.tech/golang-array-to-slice/</guid><description>&lt;ul&gt;
&lt;li&gt;TL;DR: &lt;code&gt;slice := array[:]&lt;/code&gt;で変換できる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Go言語にはリストの様なものが二つあります。配列(固定長)とスライス(可変長)です。
一般に、Go言語で配列を扱うことは多くないでしょう。
実際、多くのパッケージ(標準パッケージを含む)が要求するのはスライスです。&lt;/p&gt;
&lt;p&gt;とは言っても一部のパッケージでは配列を取り扱っているものがあります。
例えば、&lt;a href="https://golang.org/pkg/crypto/sha512/" target="_blank" rel="noopener"&gt;&lt;code&gt;crypto/sha512&lt;/code&gt;を見てみる&lt;/a&gt;
と、以下の様な関数が存在します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Sum512&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ここで、&lt;code&gt;Size&lt;/code&gt;は同パッケージ内で宣言されている定数で、値は64です。
つまり、この関数は64バイトの長さを持った配列を返します。&lt;/p&gt;
&lt;p&gt;この関数は与えられたデータからSHA512チェックサムを計算するものです。
勿論、返ってきた値をそのまま使用することもあるとは思いますが、そのままの値は人間可読な値では無いため、hexdigestを得たいと思うでしょう。&lt;/p&gt;
&lt;p&gt;Go言語にはもちろんのことながら、&lt;code&gt;encoding/hex&lt;/code&gt;パッケージが存在し、簡単に16進文字列を得ることができます。
16進表記の文字列を得るためには、次の関数を使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;引数に注目します。
要求されているのは&lt;code&gt;byte&lt;/code&gt;のスライスです。&lt;/p&gt;
&lt;p&gt;Goでは、配列とスライスは基本的に別物ですから、以下の様に書くことはできません。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sha512&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sum512&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;foobar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 型エラーが発生する&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;そうは言っても、配列とスライスは非常に似ています。
次のように書きたくなりますね。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sha512&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sum512&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;foobar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;EncodeToString&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 配列をスライスに変換したい&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;しかし、次のようなエラーを生じます。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cannot convert sha512.Sum512(&amp;#34;foobar&amp;#34;) (type [64]byte) to type []byte
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;型変換はできないようです。
どうしたら良いのでしょうか。&lt;/p&gt;
&lt;p&gt;Go言語では、配列の範囲インデックスを使った場合、返される値はスライスとなります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;baz&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// sはスライス&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;また、インデックスを省略することもできます。
開始値を省略すれば、0を与えたものと見なされますし、終了値を省略すれば、配列の最後までを切り取ります。&lt;/p&gt;</description></item><item><title>Let's Encryptでワイルドカード証明書を取得する</title><link>https://blog.web-apps.tech/lets-encrypt-wildcard/</link><pubDate>Tue, 13 Mar 2018 23:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/lets-encrypt-wildcard/</guid><description>&lt;p&gt;先日twitterでサポートされたと発表されたLet&amp;rsquo;s Encryptのワイルドカード証明書ですが、本日未明、正式にcertbotがワイルドカード証明書に対応したと&lt;a href="https://community.letsencrypt.org/t/acme-v2-and-wildcard-certificate-support-is-live/55579" target="_blank" rel="noopener"&gt;発表されました&lt;/a&gt;
!&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;早速ですが、実際にワイルドカード証明書を取得してみます。&lt;/p&gt;
&lt;p&gt;尚、今回対象とした環境は以下のとおりです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CentOS 7&lt;/li&gt;
&lt;li&gt;リバースプロキシとしてnginx&lt;/li&gt;
&lt;li&gt;DNSはGehirn DNS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;では、作業していきます。&lt;/p&gt;
&lt;p&gt;CentOS 7でcertbotを使用する場合、大抵はyumでcertbotをインストールしていると思いますので、まずはアップデートします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sudo yum update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;出力は省略しますが、certbotが0.22.0にアップデートされます。
0.22.0はワイルドカード対応バージョンですので、問題ないですね！&lt;/p&gt;
&lt;p&gt;公式のマニュアルでは、&lt;a href="https://certbot.eff.org/lets-encrypt/centosrhel7-nginx" target="_blank" rel="noopener"&gt;dns-pluginを使うよう書いてあり&lt;/a&gt;
ますが、Gehirn DNSのプラグインは無いため、今回は手動で行きます。
以下のコマンドを実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# certbot certonly --manual --preferred-challenges dns -d *.web-apps.tech --server https://acme-v02.api.letsencrypt.org/directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Saving debug log to /var/log/letsencrypt/letsencrypt.log
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Plugins selected: Authenticator manual, Installer None
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter email address &lt;span class="o"&gt;(&lt;/span&gt;used &lt;span class="k"&gt;for&lt;/span&gt; urgent renewal and security notices&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;Enter &lt;span class="s1"&gt;&amp;#39;c&amp;#39;&lt;/span&gt; to
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cancel&lt;span class="o"&gt;)&lt;/span&gt;: nasa.9084.bassclarinet@gmail.com
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Starting new HTTPS connection &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;: acme-v02.api.letsencrypt.org
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please &lt;span class="nb"&gt;read&lt;/span&gt; the Terms of Service at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;agree in order to register with the ACME server at
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://acme-v02.api.letsencrypt.org/directory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;A&lt;span class="o"&gt;)&lt;/span&gt;gree/&lt;span class="o"&gt;(&lt;/span&gt;C&lt;span class="o"&gt;)&lt;/span&gt;ancel: a
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Would you be willing to share your email address with the Electronic Frontier
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Foundation, a founding partner of the Let&lt;span class="s1"&gt;&amp;#39;s Encrypt project and the non-profit
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;organization that develops Certbot? We&amp;#39;&lt;/span&gt;d like to send you email about EFF and
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;our work to encrypt the web, protect its users and defend digital rights.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;Y&lt;span class="o"&gt;)&lt;/span&gt;es/&lt;span class="o"&gt;(&lt;/span&gt;N&lt;span class="o"&gt;)&lt;/span&gt;o: y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Starting new HTTPS connection &lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;: supporters.eff.org
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Obtaining a new certificate
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Performing the following challenges:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dns-01 challenge &lt;span class="k"&gt;for&lt;/span&gt; web-apps.tech
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NOTE: The IP of this machine will be publicly logged as having requested this
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;certificate. If you&lt;span class="s1"&gt;&amp;#39;re running certbot in manual mode on a machine that is not
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;your server, please ensure you&amp;#39;&lt;/span&gt;re okay with that.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Are you OK with your IP being logged?
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;Y&lt;span class="o"&gt;)&lt;/span&gt;es/&lt;span class="o"&gt;(&lt;/span&gt;N&lt;span class="o"&gt;)&lt;/span&gt;o: y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Please deploy a DNS TXT record under the name
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;_acme-challenge.web-apps.tech with the following value:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;qiGA8Vep17l0nYJ1O1AdF68D9iT7bL5Mpoe3j7-Caag
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Before continuing, verify the record is deployed.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-------------------------------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Press Enter to Continue
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上記のようにTXTレコードを追加するようにメッセージが出たら、指定された値をDNSに追加します。
Gehirnでは以下のような形になります。&lt;/p&gt;</description></item><item><title>sygを使用したgraceful shutdown serverパターン</title><link>https://blog.web-apps.tech/graceful-shutdown-with-syg/</link><pubDate>Sat, 10 Mar 2018 15:42:54 +0000</pubDate><guid>https://blog.web-apps.tech/graceful-shutdown-with-syg/</guid><description>&lt;p&gt;&lt;a href="https://github.com/nasa9084/syg" target="_blank" rel="noopener"&gt;&lt;code&gt;github.com/nasa9084/syg&lt;/code&gt;&lt;/a&gt;
を使用すると、手軽にシグナルとコールバック関数のマッピングを行うことができます&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;これを使用し、SIGINTを受けてgraceful shutdownできるHTTPサーバを実装してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/nasa9084/syg&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;closed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;longlongHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// os.Interrupt　= syscall.SIGINT&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Interrupt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;closed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;longlongHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// なんか長い処理のつもり&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;mainからは以下の様に呼びます。&lt;/p&gt;</description></item><item><title>Golang: 手軽にシグナルをListenしてcallback関数を呼ぶ</title><link>https://blog.web-apps.tech/go-signal-more-simply/</link><pubDate>Tue, 06 Mar 2018 14:32:00 +0000</pubDate><guid>https://blog.web-apps.tech/go-signal-more-simply/</guid><description>&lt;p&gt;Go言語でシグナルを取り扱いたい場合、&lt;code&gt;os&lt;/code&gt;パッケージおよび&lt;code&gt;os/signal&lt;/code&gt;パッケージ、&lt;code&gt;syscall&lt;/code&gt;パッケージを使用します。&lt;/p&gt;
&lt;p&gt;具体的には、以下のようにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sigCh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;doneCh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sigCh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;sigCh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// (1)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doneCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;実際には、(1)の様に受け取ったシグナルを出力するだけではなく、何らかの処理を行うことになるでしょうし、goroutineのリークを避けるためにシグナルの待受をキャンセルする必要が有りますから、&lt;code&gt;context&lt;/code&gt;を使用してfor-selectループを書くことにもなるでしょう。&lt;/p&gt;
&lt;p&gt;例として、HTTPサーバをシャットダウンするような処理を考えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sigCh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;doneCh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithCancel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sigCh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;syscall&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SIGINT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DefaultServeMux&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;sigCh&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;sigCh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doneCh&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ErrServerClosed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;doneCh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;シグナルを受け取って、関数の呼び出し(ここでは&lt;code&gt;s.Shutdown()&lt;/code&gt;)をしたいだけなのに、チャンネルを作って、goroutineを立ち上げて、となんとも大仰です。
goroutineで呼び出す関数の中でfor-selectループを使っているため、行数も長くなってしまっています。&lt;/p&gt;</description></item><item><title>strings.Builderとbytes.BufferのWrite系関数のベンチマーク</title><link>https://blog.web-apps.tech/strings-builder-vs-bytes-buffer/</link><pubDate>Mon, 05 Mar 2018 15:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/strings-builder-vs-bytes-buffer/</guid><description>&lt;h2 id="tl-dr"&gt;TL; DR&lt;/h2&gt;
&lt;p&gt;平均して見ると&lt;code&gt;strings.Builder#WriteXXX&lt;/code&gt;の方が速そう&lt;/p&gt;
&lt;h2 id="stringsbuilder"&gt;strings.Builder&lt;/h2&gt;
&lt;p&gt;Go 1.10から&lt;code&gt;strings.Builder&lt;/code&gt;構造体が追加されました。
公式ドキュメントには、&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A Builder is used to efficiently build a string using Write methods. It minimizes memory copying. The zero value is ready to use. Do not copy a non-zero Builder.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;と説明が書かれています。
おそらく、これまで文字列の組み立てをする際には&lt;code&gt;bytes.Buffer&lt;/code&gt;を使っている場合が多かったと思われますが、そういった目的の選択肢として作られたようです。
が、説明を読んでもいまいち違いがわかりません。&lt;/p&gt;
&lt;p&gt;とりあえず、&lt;code&gt;bytes.Buffer&lt;/code&gt;と&lt;code&gt;strings.Builder&lt;/code&gt;では速度面で違いがあるのか調べるべく、ベンチマークを実施しました。&lt;/p&gt;
&lt;h3 id="条件"&gt;条件&lt;/h3&gt;
&lt;h4 id="実行した環境"&gt;実行した環境&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;MacBook Air
&lt;ul&gt;
&lt;li&gt;MacOS Sierra 10.12.6&lt;/li&gt;
&lt;li&gt;CPU: Core i7 1.7GHz&lt;/li&gt;
&lt;li&gt;メモリ: 8GB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="実行する関数"&gt;実行する関数&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WriteByte&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WriteRune&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WriteString&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="exec"&gt;exec&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;span class="lnt"&gt;60
&lt;/span&gt;&lt;span class="lnt"&gt;61
&lt;/span&gt;&lt;span class="lnt"&gt;62
&lt;/span&gt;&lt;span class="lnt"&gt;63
&lt;/span&gt;&lt;span class="lnt"&gt;64
&lt;/span&gt;&lt;span class="lnt"&gt;65
&lt;/span&gt;&lt;span class="lnt"&gt;66
&lt;/span&gt;&lt;span class="lnt"&gt;67
&lt;/span&gt;&lt;span class="lnt"&gt;68
&lt;/span&gt;&lt;span class="lnt"&gt;69
&lt;/span&gt;&lt;span class="lnt"&gt;70
&lt;/span&gt;&lt;span class="lnt"&gt;71
&lt;/span&gt;&lt;span class="lnt"&gt;72
&lt;/span&gt;&lt;span class="lnt"&gt;73
&lt;/span&gt;&lt;span class="lnt"&gt;74
&lt;/span&gt;&lt;span class="lnt"&gt;75
&lt;/span&gt;&lt;span class="lnt"&gt;76
&lt;/span&gt;&lt;span class="lnt"&gt;77
&lt;/span&gt;&lt;span class="lnt"&gt;78
&lt;/span&gt;&lt;span class="lnt"&gt;79
&lt;/span&gt;&lt;span class="lnt"&gt;80
&lt;/span&gt;&lt;span class="lnt"&gt;81
&lt;/span&gt;&lt;span class="lnt"&gt;82
&lt;/span&gt;&lt;span class="lnt"&gt;83
&lt;/span&gt;&lt;span class="lnt"&gt;84
&lt;/span&gt;&lt;span class="lnt"&gt;85
&lt;/span&gt;&lt;span class="lnt"&gt;86
&lt;/span&gt;&lt;span class="lnt"&gt;87
&lt;/span&gt;&lt;span class="lnt"&gt;88
&lt;/span&gt;&lt;span class="lnt"&gt;89
&lt;/span&gt;&lt;span class="lnt"&gt;90
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="k"&gt;for&lt;/span&gt; i in &lt;span class="o"&gt;{&lt;/span&gt;1..10&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; go &lt;span class="nb"&gt;test&lt;/span&gt; -bench . &lt;span class="p"&gt;|&lt;/span&gt; tail -n +4 &lt;span class="p"&gt;|&lt;/span&gt; head -n &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; echo&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;129&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 6.47 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 7.61 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 92.4 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;196&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 300000000 9.40 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 200000000 8.18 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 50000000 &lt;span class="m"&gt;217&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;189&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 100000000 10.5 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 100000000 10.4 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 &lt;span class="m"&gt;157&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;238&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 100000000 19.9 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 100000000 15.5 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 30000000 &lt;span class="m"&gt;422&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;131&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 7.58 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 8.48 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 &lt;span class="m"&gt;113&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;199&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 100000000 10.4 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 200000000 12.0 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 50000000 &lt;span class="m"&gt;382&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;122&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 7.45 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 8.44 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 &lt;span class="m"&gt;155&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;264&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 200000000 7.08 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 200000000 10.1 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 30000000 &lt;span class="m"&gt;413&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 20000000 &lt;span class="m"&gt;117&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 6.81 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 6.87 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 50000000 &lt;span class="m"&gt;219&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 20000000 &lt;span class="m"&gt;101&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 200000000 6.22 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 200000000 12.2 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 50000000 &lt;span class="m"&gt;513&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;161&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 8.36 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 8.24 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 &lt;span class="m"&gt;109&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;296&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 100000000 10.6 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 100000000 11.4 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 50000000 &lt;span class="m"&gt;484&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;133&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 7.16 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 8.10 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 &lt;span class="m"&gt;194&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;190&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 200000000 5.51 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 200000000 8.72 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 50000000 &lt;span class="m"&gt;281&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;136&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 11.4 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 50000000 28.0 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 10000000 &lt;span class="m"&gt;119&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 20000000 &lt;span class="m"&gt;144&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 100000000 16.0 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 200000000 8.43 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 50000000 &lt;span class="m"&gt;248&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;130&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 7.83 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 7.13 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 99.0 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;202&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 200000000 10.7 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 100000000 13.8 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 50000000 &lt;span class="m"&gt;452&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWrite-4 10000000 &lt;span class="m"&gt;146&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuiderWriteByte-4 200000000 7.89 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteRune-4 200000000 8.24 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBuilderWriteString-4 30000000 &lt;span class="m"&gt;122&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWrite-4 50000000 &lt;span class="m"&gt;248&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteByte-4 100000000 31.7 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteRune-4 100000000 25.4 ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBufferWriteString-4 30000000 &lt;span class="m"&gt;413&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="source"&gt;Source&lt;/h3&gt;
&lt;p&gt;ベンチマークスクリプトのソースは以下の様になっています。&lt;/p&gt;</description></item><item><title>Go言語で文字列を処理する</title><link>https://blog.web-apps.tech/string-processing-in-go/</link><pubDate>Mon, 05 Mar 2018 14:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/string-processing-in-go/</guid><description>&lt;p&gt;Go言語の&lt;code&gt;regexp&lt;/code&gt;パッケージを使用した正規表現の処理は、一般的なスクリプト言語の処理速度と同程度で、正規表現を使用しない処理に比べてパフォーマンスがよくありません&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。
そのため、可能であるなら&lt;code&gt;regexp&lt;/code&gt;パッケージを使用しないようにすべきです。
しかし、すべての処理を自分で書くのは大変です。
標準パッケージにも文字列を処理する関数が数多く用意されています。&lt;/p&gt;
&lt;h1 id="strings-パッケージ"&gt;&lt;code&gt;strings&lt;/code&gt; パッケージ&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;strings&lt;/code&gt;パッケージはその名の通り、文字列を取り扱うパッケージです。
UTF-8でエンコードされた文字列(普通の文字列)をそのまま取り扱います。&lt;/p&gt;
&lt;h2 id="判別系"&gt;判別系&lt;/h2&gt;
&lt;h3 id="contains"&gt;&lt;code&gt;Contains&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;substr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;Contains&lt;/code&gt;関数は、&lt;code&gt;s&lt;/code&gt;の中に&lt;code&gt;substr&lt;/code&gt;が存在するかどうかを返します。
Pythonで言うところの&lt;code&gt;substr in s&lt;/code&gt;に相当します。
正規表現ならば、&lt;code&gt;substr&lt;/code&gt;とのmatchで真偽値をとることに相当します。&lt;/p&gt;
&lt;h4 id="example"&gt;example&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fuga&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Output: true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Output: false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="containsany"&gt;&lt;code&gt;ContainsAny&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;ContainsAny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;ContainsAny&lt;/code&gt;関数は&lt;code&gt;s&lt;/code&gt;の中に、&lt;code&gt;chars&lt;/code&gt;に含まれる文字のいずれかが存在するかどうかを返します。
つまり、&lt;code&gt;chars&lt;/code&gt;は文字列ですが、扱いとしては文字の配列であると考えた方が良いでしょう。&lt;/p&gt;
&lt;p&gt;正規表現で表すなら、&lt;code&gt;/[${chars}]/&lt;/code&gt;の様な表現と考えられます(${chars}は置き換える)。&lt;/p&gt;
&lt;h4 id="example-1"&gt;example&lt;/h4&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsAny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;abcd&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Output: true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ContainsAny&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hogefugapiyo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1234&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Output: false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="hasprefix"&gt;&lt;code&gt;HasPrefix&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;HasPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;HasPrefix&lt;/code&gt;関数は、&lt;code&gt;s&lt;/code&gt;の頭が&lt;code&gt;prefix&lt;/code&gt;と等しいかどうかを判別します。
正規表現で&lt;code&gt;^&lt;/code&gt;を使った文字列マッチに相当します。&lt;/p&gt;</description></item><item><title>YAPC::Okinawa 2018 ONNASONに行ってきました</title><link>https://blog.web-apps.tech/yapc_okinawa_2018/</link><pubDate>Sun, 04 Mar 2018 13:44:24 +0000</pubDate><guid>https://blog.web-apps.tech/yapc_okinawa_2018/</guid><description>&lt;p&gt;&lt;a href="https://yapcjapan.org/2017fukuoka/" target="_blank" rel="noopener"&gt;YAPC::Fukuoka 2017 HAKATA&lt;/a&gt;
(行ってきたときの記事は&lt;a href="https://blog.web-apps.tech/yapc_fukuoka_2017"&gt;こちら&lt;/a&gt;
)に引き続き、&lt;a href="http://yapcjapan.org/2018okinawa/" target="_blank" rel="noopener"&gt;YAPC::Okinawa 2018 ONNASON&lt;/a&gt;
に行ってきました。
YAPCはPerlのイベントで、&amp;ldquo;Yet Another Perl Conference&amp;quot;の略です。twitterハッシュタグは前回に引き続き&lt;a href="https://twitter.com/hashtag/yapcjapan" target="_blank" rel="noopener"&gt;#yapcjapan&lt;/a&gt;
でした(&lt;a href="https://twitter.com/hashtag/yapcokinawa" target="_blank" rel="noopener"&gt;#yapcokinawa&lt;/a&gt;
もよく使われていたようです)。&lt;/p&gt;
&lt;p&gt;沖縄は昨年6月に&lt;a href="https://www.ospn.jp/osc2017-okinawa/" target="_blank" rel="noopener"&gt;OSC 2017 Okinawa&lt;/a&gt;
で行って以来二度目です。
YAPC当日はすごい雨で、YAPC::Hokkaidoで大雪だったことを思い出し、「端っこでYAPCをやると何かが起きるのでは」などと言われる具合でした。&lt;/p&gt;
&lt;p&gt;今回は直前までホテルが取れなかったものの、過去のYAPCでホテルを取らずに行って適当になんとかなったので、なんとかなるだろうと思っていましたが、直前に東横インを確保できたので、宿無し旅行ではありませんでした。&lt;/p&gt;
&lt;h2 id="yapcokinawa-2018-onnason"&gt;YAPC::Okinawa 2018 ONNASON&lt;/h2&gt;
&lt;p&gt;今回は会場が&lt;a href="https://www.oist.jp/ja" target="_blank" rel="noopener"&gt;OIST&lt;/a&gt;
だったため(OISTは那覇市内から車で約一時間)、多くの人がスタッフが手配した往復バスでの参加となりました。
そのため、寝坊する人は少なく(いなくはなかったようです)、私もオープニングから参加できました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_okinawa_2018/images/DXUy35dVoAEkQne.jpg-large_hu_a55c276db5cd3e88.jpg" alt="オープニング" /&gt;
&lt;/p&gt;
&lt;p&gt;オープニングは&lt;a href="https://twitter.com/codehex" target="_blank" rel="noopener"&gt;CodeHex&lt;/a&gt;
氏。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_okinawa_2018/images/DXUpGixUMAAOpZj_hu_d0dccf00841c402.jpg" alt="A会場" /&gt;
&lt;/p&gt;
&lt;p&gt;オープニングを行ったA会場は非常に広く、なんと全席にコンセントがついているという素晴らしいホールでした。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_okinawa_2018/images/54633d19-4e99-459c-9c91-53227a76917b_hu_8996a82a1a9c106a.jpg" alt="YAPC::Okinawaノベルティ" /&gt;
&lt;/p&gt;
&lt;p&gt;ノベルティはこんな感じ。特筆すべきはDeNAさんのQi充電器でしょうか。しかし私はQi対応端末を持っていないので使えないのが残念・・・・
毎度恒例、ネコトーストラボさんのサイリュームもあります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_okinawa_2018/images/DXVLQA5V4AIGsir_hu_8a9865f77ecf760a.jpg" alt="スタンプラリーフルコンプ！" /&gt;
&lt;/p&gt;
&lt;p&gt;YAPC::Hokkaidoから行われてきたチェックインスタンプラリーもココで一区切り。
コンプリート特典として、JPAのラクダさんのシャチハタスタンプをいただきました。&lt;/p&gt;
&lt;p&gt;トークでは、「レイヤー0(電波)からレイヤー8(交渉事)までできる人を募集しています」や、「無曖昧でない」など、会場がどっと沸く名言(迷言？)がいくつか飛び出ました。&lt;/p&gt;
&lt;p&gt;個人的には、&lt;a href="https://twitter.com/moznion" target="_blank" rel="noopener"&gt;@moznionさん&lt;/a&gt;
のInlineモジュールの話や、&lt;a href="https://twitter.com/sinya8282" target="_blank" rel="noopener"&gt;新屋さん&lt;/a&gt;
の正規表現の話が非常に面白かったと思います。
特に、正規表現の話ではバックトラックと曖昧な正規表現の相性が悪い、といった技術的な話にとどまらず、文脈自由文法など、計算理論にまで踏み込んだトークとなっており、OISTという会場でのトークに相応しい素晴らしい内容だったと思います。&lt;/p&gt;
&lt;h2 id="次回のお話"&gt;次回のお話&lt;/h2&gt;
&lt;p&gt;次回YAPCは&lt;a href="http://yapcjapan.org/2018tokyo/" target="_blank" rel="noopener"&gt;東京&lt;/a&gt;
だそうです！現在はまだテザーサイトがある程度で、日程、会場は調整中とのことでした。&lt;/p&gt;</description></item><item><title>cut vs. parameter expansion</title><link>https://blog.web-apps.tech/cut-vs-parameter-expansion/</link><pubDate>Mon, 26 Feb 2018 08:07:11 +0000</pubDate><guid>https://blog.web-apps.tech/cut-vs-parameter-expansion/</guid><description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;:: bash/zsh parameter expansion is faster than cut.&lt;/p&gt;
&lt;h2 id="which-is-faster"&gt;which is faster?&lt;/h2&gt;
&lt;p&gt;Consider you want to take out hostname from URL or IP with port like &lt;code&gt;some.mysql.server:3306&lt;/code&gt; or &lt;code&gt;192.168.1.10:3306&lt;/code&gt; using bash/zsh.
There are some way to do this.&lt;/p&gt;
&lt;p&gt;The first way is using &lt;code&gt;cut&lt;/code&gt; command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nv"&gt;TARGET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;192.168.1.10:3306&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TARGET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; cut -d &lt;span class="s2"&gt;&amp;#34;:&amp;#34;&lt;/span&gt; -f &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now printed &lt;code&gt;192.168.1.10&lt;/code&gt; on your screen.&lt;/p&gt;
&lt;p&gt;The second way is using &amp;ldquo;shell parameter expansion&amp;rdquo;, which is functions of bash/zsh built-in.
You can use shell parameter expansion like below:&lt;/p&gt;</description></item><item><title>Goでコマンドラインオプションを処理する</title><link>https://blog.web-apps.tech/go-cmdline-option-jessevdk-go-flags/</link><pubDate>Sat, 24 Feb 2018 03:22:28 +0000</pubDate><guid>https://blog.web-apps.tech/go-cmdline-option-jessevdk-go-flags/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;github.com/jessevdk/go-flags&lt;/code&gt;が便利&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="flagパッケージ"&gt;flagパッケージ&lt;/h2&gt;
&lt;p&gt;コマンドライン・ツールを作ろうと考えたとき、避けては通れないのがコマンドラインオプションを如何に処理するか、ということです。&lt;/p&gt;
&lt;p&gt;Go言語では、標準パッケージに&lt;code&gt;flag&lt;/code&gt;というパッケージが存在し、これを用いることでコマンドラインオプションをパースすることが出来ます。
しかし、&lt;code&gt;flag&lt;/code&gt;パッケージでは、ロングオプションとショートオプションを一度に定義することが出来ず、また、ロングオプションであろうとショートオプションであろうと&lt;code&gt;-XXX&lt;/code&gt;という、ハイフンが一つつく形式のオプションとなります。
これはあまり一般的ではなく&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;、便利とも言いにくいでしょう。&lt;/p&gt;
&lt;p&gt;そこで便利なのが、&lt;a href="https://github.com/jessevdk/go-flags" target="_blank" rel="noopener"&gt;&lt;code&gt;jessevdk/go-flags&lt;/code&gt;&lt;/a&gt;
パッケージです。&lt;/p&gt;
&lt;h2 id="go-flagsパッケージ"&gt;go-flagsパッケージ&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/jessevdk/go-flags" target="_blank" rel="noopener"&gt;&lt;code&gt;jessevdk/go-flags&lt;/code&gt;&lt;/a&gt;
パッケージは、その名の通り、コマンドラインオプションを取り扱うパッケージです。
ショートオプション、ロングオプションはもちろんのこと、ショートオプションをまとめて指定する、同じオプションを違う引数で複数回指定する、環境変数からの読み込み、デフォルト値の指定などに対応していて、一般的なオプションの処理に幅広く対応出来ます。
オプションは構造体として定義出来るため、パースした後の処理で取り回すのも簡単です。&lt;/p&gt;
&lt;p&gt;簡単な例を見てみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;`short:&amp;#34;n&amp;#34; long:&amp;#34;name&amp;#34; description:&amp;#34;listen address&amp;#34;`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// some error handling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, %s\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;パッケージ宣言やインポートの節は省略していますが、上記をmain.goとして実行すると、以下の様に出力されます。&lt;/p&gt;</description></item><item><title>kubesprayを使用してkubernetes clusterを構築する(2)</title><link>https://blog.web-apps.tech/deploy-k8s-with-kubespray-2/</link><pubDate>Fri, 23 Feb 2018 14:45:49 +0000</pubDate><guid>https://blog.web-apps.tech/deploy-k8s-with-kubespray-2/</guid><description>&lt;p&gt;3ヶ月ほど前に、&lt;a href="https://blog.web-apps.tech/deploy-k8s-cluster-using-kubespray/"&gt;kubesprayを使用してkubernetes clusterを構築する&lt;/a&gt;
という、&lt;a href="https://kubespray.io/" target="_blank" rel="noopener"&gt;kubespray&lt;/a&gt;
とkubespray-cliを使用してKubernetesクラスタを構築する記事を書きました。
しかし、kubespray-cliはすでに&lt;a href="https://github.com/kubernetes-incubator/kubespray/commit/1869aa39859bff4d27bf1337c1352fd383e980a5" target="_blank" rel="noopener"&gt;deprecatedだということなので&lt;/a&gt;
、kubespray-cliを使用せずにkubesprayでクラスタを構築する手順をまとめておきます。&lt;/p&gt;
&lt;h2 id="要件"&gt;要件&lt;/h2&gt;
&lt;p&gt;kubesprayを使用してkubernetesクラスタを構築するための要件は以下のようになっています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ansible 2.4以降とpython-netaddr (python-netaddrを忘れがちなので注意)
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pip install ansible netaddr&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Jinja 2.9以降(ansibleの依存でインストールされると思います)&lt;/li&gt;
&lt;li&gt;構築先サーバがインターネットに接続できること&lt;/li&gt;
&lt;li&gt;構築先サーバでswapが無効化されていること&lt;/li&gt;
&lt;li&gt;構築先サーバでIPv4 forwardingが有効になっていること
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sysctl -w net.ipv4.ip_forward=1&lt;/code&gt;する(再起動するまで)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/etc/sysctl.conf&lt;/code&gt;に&lt;code&gt;net.ipv4.ip_forward = 1&lt;/code&gt;と記入する(再起動後)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ansibleを実行するマシンから構築先サーバにSSH鍵が渡されていること&lt;/li&gt;
&lt;li&gt;ファイアウォールが無効化されていること
&lt;ul&gt;
&lt;li&gt;ファイアウォールの設定をしっかりできる人は有効でも&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、kubesprayには(kubespray-cliのような)inventory生成ツールが付属されており、これを利用する場合はpython3系である必要が有ります。&lt;/p&gt;
&lt;h2 id="構成"&gt;構成&lt;/h2&gt;
&lt;p&gt;前回の記事同様、以下のIPを持った三台のサーバを対象として構築してみます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;192.168.1.11&lt;/li&gt;
&lt;li&gt;192.168.1.12&lt;/li&gt;
&lt;li&gt;192.168.1.13&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;それぞれ、IPv4 forwardingが有効化され、firewalldを無効化し、Python 3をインストール済みのCentOS 7のサーバとします。また、kubesprayを実行するローカルマシンから、各サーバのrootユーザにSSH鍵を配置&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;済みとします。&lt;/p&gt;
&lt;h2 id="手順"&gt;手順&lt;/h2&gt;
&lt;h3 id="準備"&gt;準備&lt;/h3&gt;
&lt;p&gt;まず、kubesprayをダウンロードします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clone https://github.com/kubernetes-incubator/kubespray
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; kubespray
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;リポジトリのクローンが完了したら、ansibleなどの依存モジュールを導入します&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubespray$ pip install -r requirements.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;次に、ansible用のインベントリを作成します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubespray$ cp -rfp inventory/sample inventory/mycluster
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;kubespray$ &lt;span class="nb"&gt;declare&lt;/span&gt; -a &lt;span class="nv"&gt;IPS&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;192.168.1.11 192.168.1.12 192.168.1.13&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;CONFIG_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;inventory/mycluster/hosts.ini python3 contrib/inventory_builder/inventory.py &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;IPS&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;IPSは対象サーバのIPに合わせて定義をします。
また、環境によっては、&lt;code&gt;python3&lt;/code&gt;コマンドではなく、&lt;code&gt;python&lt;/code&gt;コマンドでPython 3が実行される場合も有ります。適宜読み替えてください。&lt;/p&gt;</description></item><item><title>Generates LICENSE file: git-license</title><link>https://blog.web-apps.tech/generate_license_with_gitlicense/</link><pubDate>Wed, 21 Feb 2018 04:56:49 +0000</pubDate><guid>https://blog.web-apps.tech/generate_license_with_gitlicense/</guid><description>&lt;p&gt;When we create a new repository on &lt;a href="https://github.com" target="_blank" rel="noopener"&gt;GitHub&lt;/a&gt;
, we can choose an open source license.&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/generate_license_with_gitlicense/images/create_new_repo_hu_19a8f17e26e8f88b.png" alt="create_new_repo" /&gt;
&lt;/p&gt;
&lt;p&gt;We choose an OSS license, then, &lt;code&gt;LICENSE&lt;/code&gt; file is put into the new repository.&lt;/p&gt;
&lt;p&gt;Now, I&amp;rsquo;m usually using &lt;a href="https://hub.github.com/" target="_blank" rel="noopener"&gt;&lt;code&gt;hub&lt;/code&gt;&lt;/a&gt;
command to create a new repository.
I&amp;rsquo;ll do below to create:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mkdir my_new_repository
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; my_new_repository
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git init
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ... some code writing and commit ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git create &lt;span class="c1"&gt;# git command is aliased to hub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git push -u origin master
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In this flow, I can write description for repository&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;, set homepage&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;, make the repository private&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;, but I &lt;strong&gt;CANNOT&lt;/strong&gt; choose LICENSE.
I can choose and create LICENSE file on the GitHub web page, or I can copy from my other repositories because its content is fixed.
However, I don&amp;rsquo;t do that.&lt;/p&gt;</description></item><item><title>テキストを列ごとにそろえて出力する</title><link>https://blog.web-apps.tech/output-columned-text/</link><pubDate>Mon, 29 Jan 2018 07:13:10 +0000</pubDate><guid>https://blog.web-apps.tech/output-columned-text/</guid><description>&lt;p&gt;TL;DR: 標準パッケージ&lt;a href="https://golang.org/pkg/text/tabwriter/" target="_blank" rel="noopener"&gt;&lt;code&gt;text/tabwriter&lt;/code&gt;&lt;/a&gt;
を使用する&lt;/p&gt;
&lt;p&gt;コマンドラインツールで標準出力を良い感じにそろえて出力したい場合があります。
例えば、&lt;a href="https://www.docker.com" target="_blank" rel="noopener"&gt;docker&lt;/a&gt;
では、以下の様に出力されます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker container ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;8caad461b4a4 redis &lt;span class="s2"&gt;&amp;#34;docker-entrypoint.s…&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; days ago Up &lt;span class="m"&gt;5&lt;/span&gt; days 0.0.0.0:6379-&amp;gt;6379/tcp redis-svr
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;329c9f9be035 mysql &lt;span class="s2"&gt;&amp;#34;docker-entrypoint.s…&amp;#34;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; days ago Up &lt;span class="m"&gt;5&lt;/span&gt; days 0.0.0.0:3306-&amp;gt;3306/tcp mysql-svr
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このような &lt;strong&gt;map、あるいは構造体の配列&lt;/strong&gt; の様なものを、きれいに表形式の様に列をそろえて出力したい場合に便利なのが標準パッケージの&lt;a href="https://golang.org/pkg/text/tabwriter/" target="_blank" rel="noopener"&gt;&lt;code&gt;text/tabwriter&lt;/code&gt;&lt;/a&gt;
です。
その名の通り、タブ区切りの文字列を良い感じに出力してくれるパッケージです。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;text/tabwriter&lt;/code&gt;で定義されているのは&lt;a href="https://golang.org/pkg/text/tabwriter/#pkg-constants" target="_blank" rel="noopener"&gt;いくつかの設定用定数&lt;/a&gt;
と、&lt;a href="https://golang.org/pkg/text/tabwriter#Writer" target="_blank" rel="noopener"&gt;&lt;code&gt;Writer&lt;/code&gt;構造体&lt;/a&gt;
のみです。
&lt;code&gt;Writer&lt;/code&gt;は(勿論)&lt;a href="https://golang.org/pkg/io/#Writer" target="_blank" rel="noopener"&gt;&lt;code&gt;io.Writer&lt;/code&gt;インターフェース&lt;/a&gt;
を実装しています。&lt;/p&gt;
&lt;p&gt;使用方法は通常の&lt;code&gt;io.Writer&lt;/code&gt;とはすこし変わっていて、最初に&lt;a href="https://golang.org/pkg/text/tabwriter#Writer.Init" target="_blank" rel="noopener"&gt;&lt;code&gt;Writer.Init()&lt;/code&gt;&lt;/a&gt;
で初期化し、任意回数&lt;a href="https://golang.org/pkg/text/tabwriter#Writer.Write" target="_blank" rel="noopener"&gt;&lt;code&gt;Writer.Write()&lt;/code&gt;&lt;/a&gt;
で書き込みをした後、&lt;a href="https://golang.org/pkg/text/tabwriter#Writer.Flush" target="_blank" rel="noopener"&gt;&lt;code&gt;Writer.Flush()&lt;/code&gt;&lt;/a&gt;
で整形した文字列を出力します。
&lt;a href="https://golang.org/pkg/text/tabwriter#NewWriter" target="_blank" rel="noopener"&gt;&lt;code&gt;NewWriter()&lt;/code&gt;&lt;/a&gt;
関数は&lt;code&gt;Writer&lt;/code&gt;構造体を&lt;code&gt;new()&lt;/code&gt;した後&lt;code&gt;Init()&lt;/code&gt;するのと同等です。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Writer.Init()&lt;/code&gt;関数及び&lt;code&gt;NewWriter()&lt;/code&gt;関数に与える引数は以下の様になっています。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;名前&lt;/th&gt;
&lt;th style="text-align: center"&gt;型&lt;/th&gt;
&lt;th style="text-align: center"&gt;内容&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;output&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;io.Writer&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;Flush()&lt;/code&gt;したときの出力先&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;minwidth&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;1セルあたりの最小幅(パディングを含む)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;tabwidth&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;タブ文字の幅(スペースの個数と等しい)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;padding&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;パディング&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;padchar&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;byte&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;パディング文字&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;flags&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;調整用フラグ&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;最後の引数である、調整用フラグには&lt;code&gt;0&lt;/code&gt;(標準状態)を与えるか、&lt;a href="https://golang.org/pkg/text/tabwriter/#pkg-constants" target="_blank" rel="noopener"&gt;パッケージ定数&lt;/a&gt;
の論理和を用いて設定を与えます。&lt;/p&gt;</description></item><item><title>Vagrant/vmware-fusionでハードウェア仮想化を有効にしたVMを作成する</title><link>https://blog.web-apps.tech/vagrant-vmware-fusion-nested-vm/</link><pubDate>Thu, 28 Dec 2017 04:29:59 +0000</pubDate><guid>https://blog.web-apps.tech/vagrant-vmware-fusion-nested-vm/</guid><description>&lt;p&gt;vmware fusionを使用している場合、仮想マシンのCPU設定で&lt;code&gt;この仮想マシンでハイパーバイザアプリケーションを有効にする&lt;/code&gt;にチェックを入れることで仮想マシン内でKVMを動作させることができるようになります。
ドキュメントには載っていませんが&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;、Vagrant + vmware-fusion pluginの構成でも設定することが可能です。
Vagrantfileに以下の記述を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;vmware_fusion&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vmx&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;vhv.enable&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;TRUE&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;vmxの設定をする方法自体は&lt;a href="https://www.vagrantup.com/docs/vmware/configuration.html#vmx-customization" target="_blank" rel="noopener"&gt;公式ドキュメント&lt;/a&gt;
にも記載がありますが、詳細がありません&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>container-upというツールを書いた</title><link>https://blog.web-apps.tech/container-up/</link><pubDate>Fri, 22 Dec 2017 04:23:39 +0000</pubDate><guid>https://blog.web-apps.tech/container-up/</guid><description>&lt;p&gt;&lt;a href="https://github.com/nasa9084/container-up" target="_blank" rel="noopener"&gt;container-up&lt;/a&gt;
というツールを書いたのでご紹介。&lt;/p&gt;
&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;p&gt;このブログは&lt;a href="https://ghost.org/" target="_blank" rel="noopener"&gt;ghost&lt;/a&gt;
というブログエンジンで動いています。動作環境として&lt;a href="https://www.docker.com/" target="_blank" rel="noopener"&gt;Docker&lt;/a&gt;
を使用していて、Ghostの&lt;a href="https://hub.docker.com/_/ghost/" target="_blank" rel="noopener"&gt;公式イメージ&lt;/a&gt;
を使用しています。
過去の経緯から、単体のDockerコンテナで動作させており、永続データはDockerボリュームとしてマウントしている形です。&lt;/p&gt;
&lt;p&gt;扨、Docker ComposeやKubernetesなどのオーケストレーションツールを使っている場合、コンテナのバージョンアップは比較的簡単に行うことができます。
たとえば、Docker Composeを使用している場合、&lt;code&gt;docker-compose up&lt;/code&gt;で、新しいイメージで作成したコンテナに差し替えることができます。&lt;/p&gt;
&lt;p&gt;しかし、Dockerを単体で使っている場合、基本的には手作業で差し替えを行う必要があります。
Ghostコンテナの更新時は手作業でBlue-Greenアップグレードを行ってきたのですが、Ghostはかなりアップデートのペースが速く、毎度コンテナを差し替えるのが面倒になってきました。
それを楽にするため、&lt;strong&gt;container-up&lt;/strong&gt;を作りました。&lt;/p&gt;
&lt;h2 id="インストール"&gt;インストール&lt;/h2&gt;
&lt;h3 id="go環境がある人"&gt;Go環境がある人&lt;/h3&gt;
&lt;p&gt;Go言語の環境がすでにある人は、以下のコマンドで使用できるようになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go get github.com/nasa9084/container-up
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="それ以外の人"&gt;それ以外の人&lt;/h3&gt;
&lt;p&gt;Go言語の環境がない人は、&lt;a href="https://github.com/nasa9084/container-up/releases" target="_blank" rel="noopener"&gt;Releases&lt;/a&gt;
ページから自分のOSに併せてバイナリをダウンロード、パスを通してください。
windows, linux, macos向け、それぞれamd64版のバイナリを用意してあります。
動作確認はmacos、linux(CentOS 7)のみ行っています。&lt;/p&gt;
&lt;p&gt;これら以外の環境の人は、予め&lt;a href="https://github.com/golang/dep" target="_blank" rel="noopener"&gt;dep&lt;/a&gt;
をインストールした上で以下のコマンドでコンパイルしてください。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ git clonse https://github.com/nasa9084/container-up.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;cd&lt;/span&gt; container-up
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ dep ensure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go build -o container-up main.go
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;コンパイルしたら、任意の場所にバイナリを移動し、パスを通してください。&lt;/p&gt;
&lt;h2 id="使い方"&gt;使い方&lt;/h2&gt;
&lt;p&gt;基本的な使い方は、引数にコンテナ名またはコンテナIDを渡すだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ container-up CONTAINER_NAME
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;与えられたコンテナと同じ名称のイメージを使用して、ボリュームやネットワークなどの設定はそのままに新しいコンテナを作成し、差し替えます。
&lt;code&gt;:latest&lt;/code&gt;なイメージを使用している場合、&lt;code&gt;docker pull&lt;/code&gt;した後にこのコマンドを実行することで、最新のイメージから作られたコンテナに差し替わるということです。&lt;/p&gt;
&lt;p&gt;もとのコンテナは&lt;code&gt;--rm&lt;/code&gt;オプションをつけて起動していた場合を除いて、&lt;code&gt;_oldContainer&lt;/code&gt;というサフィックスが付いた状態でstopします。
なにか問題があった場合は、このコンテナに戻すと良いでしょう。&lt;/p&gt;
&lt;p&gt;もし、元のコンテナが必要ない場合は、&lt;code&gt;--rm&lt;/code&gt;オプションをつけると、差し替え時に削除します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ container-up --rm CONTAINER_NAME
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;:latest&lt;/code&gt;ではないような、バージョンタグが付いたイメージを使用していて、新しいバージョンのイメージを使いたい場合などのため、新しいイメージ名を指定して実行することもできます。&lt;/p&gt;</description></item><item><title>Kubernetes-powered Docker for mac is released!</title><link>https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/</link><pubDate>Thu, 14 Dec 2017 05:03:01 +0000</pubDate><guid>https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/</guid><description>&lt;p&gt;DockerCon EU 2017で、DockerがKubernetesを統合・サポートすると&lt;a href="http://www.publickey1.jp/blog/17/dockerkubernetesdockercon_eu_2017.html" target="_blank" rel="noopener"&gt;発表されました&lt;/a&gt;
が、本日ついにKubernetesサポート版Docker for macが(Edgeリリースですが)リリースされました！&lt;/p&gt;
&lt;p&gt;これにより、macを使用している場合は(おそらく過去最も簡単に)開発用Kubernetesクラスタを起動することができるようになりました！&lt;/p&gt;
&lt;p&gt;この記事では、Docker for macでKubernetesを立ちあげる手順をまとめておきます。&lt;/p&gt;
&lt;h2 id="kubernetesの起動手順"&gt;Kubernetesの起動手順&lt;/h2&gt;
&lt;p&gt;Docker for macのStable版を利用している場合、Edge版をインストールする必要があります。
&lt;a href="https://docs.docker.com/docker-for-mac/install/" target="_blank" rel="noopener"&gt;Install Docker for mac&lt;/a&gt;
のページから、Edge Channelのインストーラをダウンロードし、インストールします。
Dockerを終了させておけば、Stable版を自分でアンインストールする必要はありません&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。
Edge版をインストールし、Dockerの設定画面を開くと、以下の様にKubernetesタブが追加されています！！&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/images/docker-preference-general_hu_1a007643e4d81e50.png" alt="Docker設定画面(General)" /&gt;
&lt;/p&gt;
&lt;p&gt;Kubernetesタブで、Kubernetesの有効化・無効化を簡単に切り替えることができます。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/images/docker-preference-kubernetes_hu_2e23bf3b3ec04c32.png" alt="Docker設定画面(Kubernetes)" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Enable Kubernetes&lt;/code&gt;にチェックを入れ(&lt;code&gt;Show system containers&lt;/code&gt;はお好みで)、&lt;code&gt;Apply &amp;amp; Restart&lt;/code&gt;ボタンを押すと、「Kubernetesの初回インストールは少し時間かかるけど、インストールする？」という確認画面が出るので、&lt;code&gt;Install&lt;/code&gt;を押します。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/images/docker-preference-progress-kubernetes_hu_522cccd163b2e560.png" alt="docker-preference-progress-kubernetes" /&gt;
&lt;/p&gt;
&lt;p&gt;一応プログレスバーが出るのですが、余り意味はありませんでした・・・
数分でインストールが終わります。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/images/docker-preference-done-kubernetes_hu_9e9c04ccfd0bb45.png" alt="docker-preference-done-kubernetes" /&gt;
&lt;/p&gt;
&lt;p&gt;無事インストールが終了したら、&lt;code&gt;Close&lt;/code&gt;を押したあと、設定画面を閉じます。&lt;/p&gt;
&lt;p&gt;この時点で、DockerメニューにもKubernetesのステータスが表示されています。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/images/docker-menu-kubernetes-is-running_hu_8bff2537d7e4aa46.png" alt="docker-menu-kubernetes-is-running" /&gt;
&lt;/p&gt;
&lt;p&gt;今回私は&lt;code&gt;Show system containers&lt;/code&gt;をオンにしたので、&lt;code&gt;docker ps&lt;/code&gt;&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;するとKubernetesの動作に必要なコンテナが起動しています。
DNS、API Server、Etcd、Scheduler、Proxyと最小限の構成ですね。&lt;/p&gt;
&lt;p&gt;kubectlが自動でインストールされるのかどうかは・・・・わかりませんでした。(すでにインストール済みだったため)
kubectlがインストール済みの場合、自動でコンフィグが追加され、以下のコマンドでcontextを選択することで操作できるようになります。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;$ kubectl config use-context docker-for-desktop
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/kubernetes-powerd_docker_for_mac/images/docker-kubectl-get-nodes_hu_1924e3527ecbf4db.png" alt="docker-kubectl-get-nodes" /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kubectl get nodes&lt;/code&gt;すると、確かに1ノード構成でクラスタが立ち上がっているのがわかります。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Edge版の初回起動時にアンインストールされます&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;code&gt;docker container ls&lt;/code&gt;と打つのは面倒ですね&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>go-sqlrow</title><link>https://blog.web-apps.tech/go-sqlrow/</link><pubDate>Wed, 13 Dec 2017 02:44:32 +0000</pubDate><guid>https://blog.web-apps.tech/go-sqlrow/</guid><description>&lt;p&gt;この記事は&lt;a href="https://qiita.com/advent-calendar/2017/go2" target="_blank" rel="noopener"&gt;Go2 Advent Calendar 2017&lt;/a&gt;
13日目の記事です。
昨日は&lt;a href="https://qiita.com/kami_zh" target="_blank" rel="noopener"&gt;@kami_zh&lt;/a&gt;
さんの &lt;a href="https://qiita.com/kami_zh/items/e6bea56db36bac8ca108" target="_blank" rel="noopener"&gt;Goで標準出力をキャプチャするパッケージを書いた&lt;/a&gt;
でした。&lt;/p&gt;
&lt;h2 id="go-sqlrow"&gt;go-sqlrow&lt;/h2&gt;
&lt;p&gt;Go言語で標準パッケージを使用してRDBMSからデータを取ってくるには、以下の様に書きます&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dsn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`SELECT id, name FROM person where id=&amp;#39;foo&amp;#39;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;SQL文を発行するまではいいのですが、最後の行、&lt;code&gt;sql.Row#Scan&lt;/code&gt;がくせ者です。
上記の例のように、&lt;code&gt;sql.row#Scan&lt;/code&gt;は可変長個のポインタを引数にとり、それらにそれぞれ値をセットします。この例では値の数が2つのため大きな問題ではありませんが、値の数が増えた場合などは非常に面倒です。また、テーブルの構造が変わった場合なども非常に面倒です。&lt;/p&gt;
&lt;p&gt;この問題を解決するため、&lt;a href="https://github.com/nasa9084/go-sqlrow" target="_blank" rel="noopener"&gt;go-sqlrow&lt;/a&gt;
という小さなパッケージを作りました&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;。
これは上記の&lt;code&gt;row.Scan&lt;/code&gt;を代わりにやってくれるパッケージです。&lt;/p&gt;
&lt;p&gt;機能・使い方は簡単で、先ほどの例を次の様に書き換えます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;dsn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`SELECT id, name FROM person where id=&amp;#39;foo&amp;#39;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;sqlrow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;後は内部で&lt;code&gt;row.Scan&lt;/code&gt;相当の処理を行います。
unexportedなフィールドは&lt;code&gt;encoding/json&lt;/code&gt;同様、&lt;code&gt;sql.Row&lt;/code&gt;との対応がとれませんので、注意が必要です。&lt;/p&gt;</description></item><item><title>Parcel + Riot.js</title><link>https://blog.web-apps.tech/parcel-riot-js/</link><pubDate>Tue, 12 Dec 2017 15:00:00 +0000</pubDate><guid>https://blog.web-apps.tech/parcel-riot-js/</guid><description>&lt;p&gt;この記事は &lt;a href="https://qiita.com/advent-calendar/2017/riot" target="_blank" rel="noopener"&gt;Riot.js Advent Calendar 2017&lt;/a&gt;
13日目の記事です。
昨日は&lt;a href="https://qiita.com/supple" target="_blank" rel="noopener"&gt;@supple&lt;/a&gt;
さんによる&lt;a href="https://qiita.com/supple/items/2cc58ee5c9bc11832596" target="_blank" rel="noopener"&gt;Riot+ElectronでMarkdownエディタを作る&lt;/a&gt;
でした。&lt;/p&gt;
&lt;h2 id="tldr"&gt;tl;dr&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://parceljs.org/" target="_blank" rel="noopener"&gt;Parcel&lt;/a&gt;
というJavaScriptのモジュールバンドラを触ってみた&lt;/li&gt;
&lt;li&gt;webpackなどと比べて設定ファイルなどもいらずとても簡単&lt;/li&gt;
&lt;li&gt;ホットリロードな開発サーバを簡単に実行できる&lt;/li&gt;
&lt;li&gt;Riotと組み合わせるのもそれほど難しくない&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="parcel--riotjs"&gt;Parcel + Riot.js&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://parceljs.org/" target="_blank" rel="noopener"&gt;Parcel&lt;/a&gt;
というJavaScriptのモジュールバンドラが話題なのでさわってみました。
国内で話題になっている元の記事は「&lt;a href="https://qiita.com/bitrinjani/items/b08876e0a2618745f54a" target="_blank" rel="noopener"&gt;webpack時代の終わりとparcel時代のはじまり&lt;/a&gt;
」。
&lt;a href="https://reactjs.org/" target="_blank" rel="noopener"&gt;React&lt;/a&gt;
との組み合わせで記事を書かれています。&lt;/p&gt;
&lt;p&gt;個人的には&lt;a href="http://riotjs.com/ja/" target="_blank" rel="noopener"&gt;Riot.js&lt;/a&gt;
が好みなので、Riot.jsとの組み合わせで触ってみました。
尚、webpackは挫折したため比較できません。&lt;/p&gt;
&lt;h2 id="parcelriotjsのインストール"&gt;Parcel/Riot.jsのインストール&lt;/h2&gt;
&lt;p&gt;npmを使ってインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ npm install -g parcel-bundler riot
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="source-code"&gt;source code&lt;/h2&gt;
&lt;h3 id="ディレクトリ構造"&gt;ディレクトリ構造&lt;/h3&gt;
&lt;p&gt;以下の様なディレクトリ構造だとします。
なお、練習用のため、動作確認に関係ない部分は適当に削っています。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;src/
|- index.html
|- index.js
|- package.json
|- app/
| |- App.tag
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="indexhtml"&gt;index.html&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;ja&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;index.js&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="indexjs"&gt;index.js&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;riot&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;riot&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;./app/tags&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;riot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;App&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="apptag"&gt;App.tag&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, parcel world!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;riot&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;riot&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="packagejson"&gt;package.json&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;package.json&lt;/code&gt;は&lt;code&gt;npm init -y&lt;/code&gt;で作成しました。&lt;/p&gt;</description></item><item><title>kubesprayを使用してkubernetes clusterを構築する</title><link>https://blog.web-apps.tech/deploy-k8s-cluster-using-kubespray/</link><pubDate>Thu, 30 Nov 2017 09:04:06 +0000</pubDate><guid>https://blog.web-apps.tech/deploy-k8s-cluster-using-kubespray/</guid><description>&lt;p&gt;&lt;strong&gt;注意: 情報が古くなっています。&lt;a href="https://blog.web-apps.tech/deploy-k8s-with-kubespray-2/"&gt;新しい情報にあわせて記事を書いた&lt;/a&gt;
ので、そちらをご覧ください。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/kubernetes-incubator/kubespray" target="_blank" rel="noopener"&gt;kubespray&lt;/a&gt;
はproduction readyなkubernetes(k8s)クラスタを構成できるツールです。
&lt;a href="https://www.ansible.com/" target="_blank" rel="noopener"&gt;Ansible&lt;/a&gt;
をベースに作られているため、任意のサーバでk8sクラスタを構成できます。&lt;/p&gt;
&lt;p&gt;今回は、3台のVMを用意してクラスタを構成してみます&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;。&lt;/p&gt;
&lt;h2 id="検証環境"&gt;検証環境&lt;/h2&gt;
&lt;p&gt;今回用意したVMは以下の構成です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2Core&lt;/li&gt;
&lt;li&gt;8GB RAM&lt;/li&gt;
&lt;li&gt;80GB HDD&lt;/li&gt;
&lt;li&gt;CentOS 7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;IPアドレスは以下の様になっているものとします。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;192.168.1.11&lt;/li&gt;
&lt;li&gt;192.168.1.12&lt;/li&gt;
&lt;li&gt;192.168.1.13&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、kubesprayを実行するローカルの環境はmacOS Sierraです。
各ホストのrootユーザに対してSSH鍵は配置済み、firewalldは無効化されているとします。&lt;/p&gt;
&lt;h2 id="requirements"&gt;requirements&lt;/h2&gt;
&lt;p&gt;実行する環境に、&lt;a href="https://www.ansible.com/" target="_blank" rel="noopener"&gt;Ansible&lt;/a&gt;
が必要なため、&lt;code&gt;pip&lt;/code&gt;でインストールします。&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install ansible
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="install-kubespray-cli"&gt;install kubespray-cli&lt;/h2&gt;
&lt;p&gt;kubespray自体も&lt;code&gt;pip&lt;/code&gt;でインストールします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pip install kubespray
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="prepare"&gt;prepare&lt;/h2&gt;
&lt;p&gt;設定ファイルを生成するため、&lt;code&gt;kubespray prepare&lt;/code&gt;を使用します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubespray prepare --nodes node1&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.11&lt;span class="o"&gt;]&lt;/span&gt; node2&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.12&lt;span class="o"&gt;]&lt;/span&gt; node3&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;192.168.1.13&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="deploy"&gt;deploy&lt;/h2&gt;
&lt;p&gt;以下のコマンドでk8sクラスタをデプロイします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ kubespray deploy -u root -n flannel
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;今回は&lt;a href="https://github.com/coreos/flannel" target="_blank" rel="noopener"&gt;&lt;code&gt;flannel&lt;/code&gt;&lt;/a&gt;
ネットワークプラグインで構成しました。
kubesprayは、次のネットワークプラグインを使用してクラスタを構成することができます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/coreos/flannel" target="_blank" rel="noopener"&gt;flannel&lt;/a&gt;
&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.projectcalico.org/" target="_blank" rel="noopener"&gt;calico&lt;/a&gt;
&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/projectcalico/canal" target="_blank" rel="noopener"&gt;canal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="http://contiv.github.io/" target="_blank" rel="noopener"&gt;contiv&lt;/a&gt;
&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.weave.works/" target="_blank" rel="noopener"&gt;weave&lt;/a&gt;
&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;あとは構成が終了するのを待つだけです。&lt;/p&gt;</description></item><item><title>GitLab Docker: initial runners registration token</title><link>https://blog.web-apps.tech/gitlab-docker-init-runners-reg-token/</link><pubDate>Wed, 22 Nov 2017 01:17:14 +0000</pubDate><guid>https://blog.web-apps.tech/gitlab-docker-init-runners-reg-token/</guid><description>&lt;p&gt;&lt;a href="https://about.gitlab.com/" target="_blank" rel="noopener"&gt;GitLab&lt;/a&gt;
はRuby on Railsで書かれたオープンソースのGitサーバアプリケーションです。おそらく、オープンソースのGitサーバとしては最もよく使われているものではないでしょうか。
GitLabは他のOSS Gitサーバアプリケーションと比べて、非常に多くの機能を持っています。
GitLab-CIもその一つで、GitLab上で自動テストを回すことができます。&lt;/p&gt;
&lt;p&gt;この、GitLab-CIを使用するにはrunnerと呼ばれる、CI環境用のホストを追加する必要があります。
このとき、Registration Tokenという登録用トークンが必要なのですが、REST APIで取得することができません。そのため、Dockerを用いた自動構築時に少々困りました。&lt;/p&gt;
&lt;h2 id="解法"&gt;解法&lt;/h2&gt;
&lt;p&gt;GitLab omnibusの設定項目でRegistration Tokenの初期値を設定することができます。
&lt;code&gt;docker run&lt;/code&gt;する際のオプションに、以下を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;GITLAB_OMNIBUS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;gitlab_rails[&amp;#39;initial_shared_runners_registration_token&amp;#39;] = &amp;#39;HOGEHOGETOKEN&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;もし、ほかの理由ですでに&lt;code&gt;GITLAB_OMNIBUS_CONFIG&lt;/code&gt;の指定がある場合、セミコロン区切りで複数の値を指定することができます。たとえば、初期パスワードを与えている場合は、以下の様にできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;-e &lt;span class="nv"&gt;GITLAB_OMNIBUS_CONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;gitlab_rails[&amp;#39;initial_root_password&amp;#39;] = &amp;#39;FUGAFUGAPASSWORD&amp;#39;; gitlab_rails[&amp;#39;initial_shared_runners_registration_token&amp;#39;] = &amp;#39;HOGEHOGETOKEN&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ここで指定した値をrunnerの登録時に与えれば、OKです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; GITLAB_RUNNER_CONTAINER_NAME gitlab-runner register -n -r HOGEHOGETOKEN --run-untagged --executor docker --docker-image alpine:latest --url http://GITLAB_URL --docker-volumes /var/run/docker.sock:/var/run/docker.sock
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このとき、GITLAB_RUNNER_CONTAINER_NAMEとGITLAB_URLは適宜置き換えてください。&lt;/p&gt;</description></item><item><title>Application Specific Context</title><link>https://blog.web-apps.tech/package-specified-context/</link><pubDate>Tue, 21 Nov 2017 04:21:58 +0000</pubDate><guid>https://blog.web-apps.tech/package-specified-context/</guid><description>&lt;p&gt;元ネタは&lt;a href="https://twitter.com/lestrrat" target="_blank" rel="noopener"&gt;@lestrrat&lt;/a&gt;
さんの「&lt;a href="https://medium.com/@lestrrat/abusing-type-aliases-to-augment-context-context-a08a85692fa8" target="_blank" rel="noopener"&gt;Abusing type aliases to augment context.Context&lt;/a&gt;
」。&lt;/p&gt;
&lt;p&gt;golangを用いてHTTPサーバを作る場合、ルーティングを定義するのに以下の様な関数を用います。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;もちろん、&lt;code&gt;http.Handle&lt;/code&gt;を用いる場合もありますし、&lt;a href="https://github.com/gorilla/mux" target="_blank" rel="noopener"&gt;gorilla/mux&lt;/a&gt;
などのライブラリを用いることもあると思います。
ここで重要なのは、&lt;code&gt;func(w http.ResponseWriter, r *http.Request)&lt;/code&gt;という引数の方です。&lt;/p&gt;
&lt;p&gt;多くの場合、アプリケーションのハンドラ内ではデータベースなどの外部アプリケーション・ミドルウェアを用いることになります。
しかし、golangのHTTPアプリケーションでは、ハンドラ関数の形式が&lt;code&gt;func (w http.ResponseWriter, r *http.Request)&lt;/code&gt;と決まっています。引数の追加はできないため、引数以外の方法でDB接続情報などを渡す必要があります。&lt;/p&gt;
&lt;p&gt;これまで、golangでWebアプリケーション開発を行う場合によく用いられていたデータベースコネクションの保持方法は、&lt;code&gt;db&lt;/code&gt;パッケージを作成し、そこにパッケージ変数として持つ方法かと思います。が、&lt;a href="https://dave.cheney.net/2017/06/11/go-without-package-scoped-variables" target="_blank" rel="noopener"&gt;グローバルな変数はできるだけ持ちたくない&lt;/a&gt;
ですよね。&lt;/p&gt;
&lt;p&gt;そこで、Go 1.8から追加された&lt;a href="https://golang.org/pkg/context" target="_blank" rel="noopener"&gt;&lt;code&gt;context&lt;/code&gt;&lt;/a&gt;
を使うことができます。&lt;a href="https://golang.org/pkg/net/http#Reqeuest" target="_blank" rel="noopener"&gt;&lt;code&gt;http.Request&lt;/code&gt;&lt;/a&gt;
には&lt;code&gt;context.Context&lt;/code&gt;が入っていて、&lt;a href="https://golang.org/pkg/net/http#Request.Context" target="_blank" rel="noopener"&gt;&lt;code&gt;Request.Context()&lt;/code&gt;&lt;/a&gt;
でget、&lt;a href="https://golang.org/pkg/net/http#Request.WithContext" target="_blank" rel="noopener"&gt;&lt;code&gt;Request.WithContext()&lt;/code&gt;&lt;/a&gt;
でsetできます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;context.Context&lt;/code&gt;に値を持たせる方法で最初に思いつくのは&lt;a href="https://golang.org/pkg/context#Context.WithValue" target="_blank" rel="noopener"&gt;&lt;code&gt;Context.WithValue()&lt;/code&gt;&lt;/a&gt;
を用いる方法ですが、これは値を取得する度にtype assertionをする必要があり、あまり&lt;a href="https://medium.com/@lestrrat/alternative-to-using-context-value-f2efe6bd2788" target="_blank" rel="noopener"&gt;よくありません&lt;/a&gt;
。
これを解消するため、自分で型を定義するのがよいでしょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// internal context subpackage&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;withSomethingContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Something&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;WithSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Something&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;withSomethingContext&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Something&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Something&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;withSomethingContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;something&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`no asscosiated something`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このように定義をすることで、毎回type assertionをする必要もなくなり、すっきりします。&lt;/p&gt;</description></item><item><title>GNU MOファイルの構造</title><link>https://blog.web-apps.tech/gnu_mo_format/</link><pubDate>Mon, 06 Nov 2017 09:08:27 +0000</pubDate><guid>https://blog.web-apps.tech/gnu_mo_format/</guid><description>GNU MOファイルの内部構造について、最小限ですが解説します。</description></item><item><title>Travis CIでdockerのバージョンを最新にする</title><link>https://blog.web-apps.tech/travis-ci-update-docker/</link><pubDate>Wed, 18 Oct 2017 09:17:00 +0000</pubDate><guid>https://blog.web-apps.tech/travis-ci-update-docker/</guid><description>&lt;p&gt;Travis CIでDockerfileをテストする等、dockerを使用したい場合、以下の様に&lt;code&gt;.travis.yml&lt;/code&gt;に記述することでdockerを有効にすることできます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;sudo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;required&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;docker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;が、その際のdockerのバージョンは17.03.1&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;と、最新版ではありません。
特に問題なのが、&lt;a href="https://docs.docker.com/engine/userguide/eng-image/multistage-build/" target="_blank" rel="noopener"&gt;multi-stage build&lt;/a&gt;
は17.05からの機能であるということです。
Travis CIで使用できるdockerでは、multi-stage buildを使用したDockerfileはビルドすることができず、常にfailedとなってしまいます。&lt;/p&gt;
&lt;h2 id="解決方法"&gt;解決方法&lt;/h2&gt;
&lt;p&gt;Travis-CIでDockerのバージョンを上げるには、以下の記述を&lt;code&gt;.travis.yml&lt;/code&gt;に追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;sudo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;required&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;docker&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;before_install&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sudo apt-get update&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;sudo apt-get install -y -o Dpkg::Options::=&amp;#34;--force-confnew&amp;#34; docker-ce&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;dockerの再起動などの処理は必要ありません。
以上の記述により、Dockerのバージョンが最新版にアップデートされ、multi-stage buildも使用できるようになります。&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;2017年10月18日現在&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>Kolla-AnsibleでOpenStack Ocata環境を構築する</title><link>https://blog.web-apps.tech/kolla-ansible-ocata/</link><pubDate>Wed, 04 Oct 2017 06:12:37 +0000</pubDate><guid>https://blog.web-apps.tech/kolla-ansible-ocata/</guid><description>OpenStack Kollaを用いると、比較的簡単にOpenStack on Docker環境を構築することができます。
今回はKolla-Ansibleを使用してall-in-one構成で4.0.0(Ocata)環境を構築してみます。</description></item><item><title>Kolla-ansible precheckで発生するエラーの対処</title><link>https://blog.web-apps.tech/kolla-ansible-precheck-error/</link><pubDate>Fri, 29 Sep 2017 14:20:16 +0000</pubDate><guid>https://blog.web-apps.tech/kolla-ansible-precheck-error/</guid><description>「OpenStack Kolla(Ocata)環境の構築」を参考にOpenStack Kollaのセットアップを行っていたら、エラーが出ました。</description></item><item><title>Functional Option Pattern</title><link>https://blog.web-apps.tech/go-functional-option-pattern/</link><pubDate>Tue, 26 Sep 2017 01:44:53 +0000</pubDate><guid>https://blog.web-apps.tech/go-functional-option-pattern/</guid><description>&lt;p&gt;Fuctional Option PatternはGo言語において構造体の初期化時にオプション引数を与えるためのデザインパターンで、元ネタはRob Pike氏の&lt;a href="https://commandcenter.blogspot.jp/2014/01/self-referential-functions-and-design.html" target="_blank" rel="noopener"&gt;Self-referential functions and the design of options&lt;/a&gt;
、Dave Cheney氏の&lt;a href="https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis" target="_blank" rel="noopener"&gt;Functional options for frendly APIS&lt;/a&gt;
です。&lt;/p&gt;
&lt;p&gt;Go言語には他の言語でオプション引数やキーワード引数と呼ばれる、省略可能な引数が存在しません。
通常は大きな問題は無いのですが、しかし、構造体の初期化時には、省略可能引数がほしくなる場合もあります。&lt;/p&gt;
&lt;p&gt;Dave Cheney氏の記事にもある例を見てみましょう。&lt;/p&gt;
&lt;h2 id="例"&gt;例&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Listener&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;NewServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;srv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;srv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;srv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;よくある構造体の初期化関数です。
初期化が上手くいけば、ポインタと&lt;code&gt;nil&lt;/code&gt;を、上手くいかなければ&lt;code&gt;nil&lt;/code&gt;とエラーを返す形になっています。&lt;/p&gt;</description></item><item><title>go-redis, redigo, boltのベンチマークを取ってみた</title><link>https://blog.web-apps.tech/go-redis-redigo-bolt-benchmark/</link><pubDate>Thu, 07 Sep 2017 04:40:01 +0000</pubDate><guid>https://blog.web-apps.tech/go-redis-redigo-bolt-benchmark/</guid><description>&lt;h2 id="tldr"&gt;tl;dr&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;データベースに接続済みの状態からstringで値をセット・ゲットするベンチマーク
&lt;ul&gt;
&lt;li&gt;BoltのGetがめちゃめちゃ速い&lt;/li&gt;
&lt;li&gt;go-redisよりはredigoの方が速い&lt;/li&gt;
&lt;li&gt;Boltのセットがメモリアロケーションすごく多い&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="result"&gt;result&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -bench .
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkRedisSet-4 10000 &lt;span class="m"&gt;246527&lt;/span&gt; ns/op &lt;span class="m"&gt;249&lt;/span&gt; B/op &lt;span class="m"&gt;9&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkRedisGet-4 5000 &lt;span class="m"&gt;231569&lt;/span&gt; ns/op &lt;span class="m"&gt;225&lt;/span&gt; B/op &lt;span class="m"&gt;9&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkRedigoSet-4 5000 &lt;span class="m"&gt;204545&lt;/span&gt; ns/op &lt;span class="m"&gt;70&lt;/span&gt; B/op &lt;span class="m"&gt;4&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkRedigoGet-4 5000 &lt;span class="m"&gt;209392&lt;/span&gt; ns/op &lt;span class="m"&gt;80&lt;/span&gt; B/op &lt;span class="m"&gt;6&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBoltSet-4 10000 &lt;span class="m"&gt;166142&lt;/span&gt; ns/op &lt;span class="m"&gt;34287&lt;/span&gt; B/op &lt;span class="m"&gt;57&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkBoltGet-4 1000000 &lt;span class="m"&gt;1140&lt;/span&gt; ns/op &lt;span class="m"&gt;488&lt;/span&gt; B/op &lt;span class="m"&gt;8&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PASS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ok practices/redis-bolt-benchmark 8.705s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="source"&gt;source&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;span class="lnt"&gt;60
&lt;/span&gt;&lt;span class="lnt"&gt;61
&lt;/span&gt;&lt;span class="lnt"&gt;62
&lt;/span&gt;&lt;span class="lnt"&gt;63
&lt;/span&gt;&lt;span class="lnt"&gt;64
&lt;/span&gt;&lt;span class="lnt"&gt;65
&lt;/span&gt;&lt;span class="lnt"&gt;66
&lt;/span&gt;&lt;span class="lnt"&gt;67
&lt;/span&gt;&lt;span class="lnt"&gt;68
&lt;/span&gt;&lt;span class="lnt"&gt;69
&lt;/span&gt;&lt;span class="lnt"&gt;70
&lt;/span&gt;&lt;span class="lnt"&gt;71
&lt;/span&gt;&lt;span class="lnt"&gt;72
&lt;/span&gt;&lt;span class="lnt"&gt;73
&lt;/span&gt;&lt;span class="lnt"&gt;74
&lt;/span&gt;&lt;span class="lnt"&gt;75
&lt;/span&gt;&lt;span class="lnt"&gt;76
&lt;/span&gt;&lt;span class="lnt"&gt;77
&lt;/span&gt;&lt;span class="lnt"&gt;78
&lt;/span&gt;&lt;span class="lnt"&gt;79
&lt;/span&gt;&lt;span class="lnt"&gt;80
&lt;/span&gt;&lt;span class="lnt"&gt;81
&lt;/span&gt;&lt;span class="lnt"&gt;82
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;rbbench_test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/boltdb/bolt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redigo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/garyburd/redigo/redis&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/go-redis/redis&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redisOpts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Addr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;localhost:6379&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkRedisSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;redisOpts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkRedisGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;redisOpts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;Val&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkRedigoSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redigo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;localhost:6379&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;SET&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkRedigoGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redigo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Dial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tcp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;localhost:6379&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;redigo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkBoltSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bolt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bolt.db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mo"&gt;0600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;bolt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBucketIfNotExists&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Put&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkBoltGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bolt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bolt.db&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mo"&gt;0600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;View&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;bolt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>二重にプロキシされたRancher Serverのリバースプロキシ設定</title><link>https://blog.web-apps.tech/2proxied-rancher-server/</link><pubDate>Mon, 04 Sep 2017 10:25:25 +0000</pubDate><guid>https://blog.web-apps.tech/2proxied-rancher-server/</guid><description>常時SSLの環境で二重にリバースプロキシされた環境のRancherは、公式ドキュメント通りの設定を行っても正常に動作しません。
X-Forwarded-ProtoがHTTPSの状態でRancher Serverまで届くように設定することで問題を解消できます。</description></item><item><title>Rancher-HAProxyでHSTSを設定する</title><link>https://blog.web-apps.tech/hsts-rancher-haproxy/</link><pubDate>Sat, 02 Sep 2017 16:49:12 +0000</pubDate><guid>https://blog.web-apps.tech/hsts-rancher-haproxy/</guid><description>HSTSはHTTP Strict Transport Securityの略で、HTTPでの接続を強制的にHTTPSへと変更するようウェブブラウザへ伝達するセキュリティ機構です。
Rancher-HAProxyでロードバランシングしている場合にもHSTSを使えるように設定してみました。</description></item><item><title>io.Writer.Write()とfmt.Fprintf()のBenchmark</title><link>https://blog.web-apps.tech/benchmark-iowriter-and-fprintf/</link><pubDate>Sat, 02 Sep 2017 04:30:59 +0000</pubDate><guid>https://blog.web-apps.tech/benchmark-iowriter-and-fprintf/</guid><description>&lt;h2 id="tldr"&gt;tl;dr&lt;/h2&gt;
&lt;p&gt;基本的に&lt;code&gt;io.Writer.Write()&lt;/code&gt;を使用するのが高速なようです。&lt;/p&gt;
&lt;h2 id="result"&gt;result&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ go &lt;span class="nb"&gt;test&lt;/span&gt; -bench . -benchmem
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkWrite-4 30000000 48.7 ns/op &lt;span class="m"&gt;16&lt;/span&gt; B/op &lt;span class="m"&gt;1&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkWriteWithBytes-4 500000000 3.95 ns/op &lt;span class="m"&gt;0&lt;/span&gt; B/op &lt;span class="m"&gt;0&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkFprintf-4 20000000 91.5 ns/op &lt;span class="m"&gt;0&lt;/span&gt; B/op &lt;span class="m"&gt;0&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkWriteTo-4 100000000 10.0 ns/op &lt;span class="m"&gt;0&lt;/span&gt; B/op &lt;span class="m"&gt;0&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BenchmarkWriteWithBufferBytes-4 300000000 4.31 ns/op &lt;span class="m"&gt;0&lt;/span&gt; B/op &lt;span class="m"&gt;0&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="source"&gt;source&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main_test&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;bytes&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;io&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello, my world&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;NullWriter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;NullWriter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;NullWriter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="nb"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkWriteWithBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;NullWriter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkFprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;NullWriter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkWriteTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;NullWriter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BenchmarkWriteWithBufferBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;testing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;NullWriter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResetTimer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>sync.WaitGroup</title><link>https://blog.web-apps.tech/how-to-use-sync-waitgroup/</link><pubDate>Fri, 01 Sep 2017 07:03:07 +0000</pubDate><guid>https://blog.web-apps.tech/how-to-use-sync-waitgroup/</guid><description>&lt;p&gt;Goroutineを使用して複数の処理を並列で実行、すべてが終わったら次の処理に進みたいという場合があると思います。
Goroutineでデータのリストを作るという処理を考えます。
データの順番は関係なく、すべてのGoroutineでのデータがそろったら次の処理をしたいという設定です。
この場合、単純に考えると以下のようなコードになりますが、以下のコードではデータがそろう前に次の処理が行われます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;datalist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// something w/datalist&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;next step&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このような場合に、&lt;code&gt;sync.WaitGroup&lt;/code&gt;を使用します。
&lt;code&gt;sync.WaitGroup&lt;/code&gt;は基本的にはただのカウンタですが、カウンタがゼロになるまで処理を待つことができます。
言葉で説明してもわかりにくいと思いますので、ソースコードを見てみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;datalist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WaitGroup&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Goroutineの数だけカウンタを増やす&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// something w/datalist&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// カウンタを減らす&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// カウンタが0になるまでブロックする&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;next step&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上記の様にすることで、for文の部分ではGoroutineで並列に実行しつつ、次の処理は並列実行部分が終わってからという動作をさせることができます。&lt;/p&gt;</description></item><item><title>Go 1.9 is released</title><link>https://blog.web-apps.tech/go-1-9-is-released/</link><pubDate>Mon, 28 Aug 2017 01:41:47 +0000</pubDate><guid>https://blog.web-apps.tech/go-1-9-is-released/</guid><description>&lt;p&gt;先日2017年8月24日にGo 1.9がリリースされました。
&lt;a href="https://golang.org/dl/" target="_blank" rel="noopener"&gt;ダウンロードページ&lt;/a&gt;
からダウンロード可能です。&lt;/p&gt;
&lt;p&gt;最大の変更点は&lt;a href="../go1-9rc1_is_released"&gt;Go1.9rc1 is released!&lt;/a&gt;
でもお伝えしたように、&lt;a href="https://golang.org/doc/go1.9#language" target="_blank" rel="noopener"&gt;&lt;strong&gt;Type Alias&lt;/strong&gt;&lt;/a&gt;
でしょう。
型名に対して別名をつけることができる機能です。&lt;/p&gt;
&lt;p&gt;また、そのほかにも多くの変更が加えられています。
リリースノートは&lt;a href="https://golang.org/doc/go1.9" target="_blank" rel="noopener"&gt;こちら&lt;/a&gt;
です。&lt;/p&gt;
&lt;p&gt;以下では、いくつか変更点を見ていきます。&lt;/p&gt;
&lt;h2 id="ports"&gt;Ports&lt;/h2&gt;
&lt;p&gt;Go 1.9から新しく2つのOSと1つのプロセッサアーキテクチャがサポートされています。&lt;/p&gt;
&lt;h3 id="power8"&gt;POWER8&lt;/h3&gt;
&lt;p&gt;IBMのPOWER8プロセッサがサポートされています。
&lt;code&gt;GOARCH=ppc64&lt;/code&gt;または&lt;code&gt;GOARCH=ppc64le&lt;/code&gt;で使用することができます。&lt;/p&gt;
&lt;h3 id="freebsd"&gt;FreeBSD&lt;/h3&gt;
&lt;p&gt;FreeBSD 9.3で動作します。。。が、すでにFreeBSDはサポート切れです。(なんでや・・・・)
Go 1.10からはFreeBSD 10.3+で動作する様になる予定です。&lt;/p&gt;
&lt;h3 id="openbsd-60"&gt;OpenBSD 6.0&lt;/h3&gt;
&lt;p&gt;OpenBSD 6.0がサポートされました。
かわりに、Go 1.9ではOpenBSD5.9をサポートしていません。&lt;/p&gt;
&lt;h2 id="parallel-compilation"&gt;Parallel Compilation&lt;/h2&gt;
&lt;p&gt;パッケージの関数を並列コンパイルできるようになりました。
並列コンパイルはデフォルトでONになっており、無効化するには環境変数で&lt;code&gt;GO19CONCURRENTCOMPILATION&lt;/code&gt;を&lt;code&gt;0&lt;/code&gt;に設定します。&lt;/p&gt;
&lt;h2 id="vendor-matching-with-"&gt;Vendor matching with ./&amp;hellip;&lt;/h2&gt;
&lt;p&gt;これまで、&lt;code&gt;./...&lt;/code&gt;というディレクトリ表現はvendorディレクトリも含んでいました。しかし、&lt;code&gt;go test&lt;/code&gt;の場合などvendorディレクトリは含まれない方がうれしい場合も多く、実際&lt;code&gt;glide nv&lt;/code&gt;などでvendorディレクトリを含まないディレクトリマッチングが実装されていました。
go1.9からは&lt;code&gt;./...&lt;/code&gt;にはvendorディレクトリが含まれないようになり、vendorディレクトリにマッチさせたい場合は&lt;code&gt;./vendor/...&lt;/code&gt;と書く必要があります。&lt;/p&gt;
&lt;h2 id="moved-goroot"&gt;Moved GOROOT&lt;/h2&gt;
&lt;p&gt;Go 1.9から、GOROOTが移動となりました。
起動されたパスから自動でGOROOTを探索します。
これにより、Goのインストールパスが違う場所に移動しても、Goのツール類は継続して使える用になりました。&lt;/p&gt;
&lt;h2 id="compiler-toolchain"&gt;Compiler Toolchain&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;複素数の割り算がC99準拠となりました。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="doc"&gt;Doc&lt;/h2&gt;
&lt;p&gt;長い引数リストは省略されます。
これは&lt;code&gt;go doc&lt;/code&gt;で生成されるコードの可読性向上のためです。
また、構造体フィールドのドキュメンテーションがサポートされました。&lt;code&gt;go doc http.Client.Jar&lt;/code&gt;などでどうなったのか確認することができます。&lt;/p&gt;
&lt;h2 id="env"&gt;env&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;go env -json&lt;/code&gt;フラグによりJSON出力することができるようになりました。&lt;/p&gt;
&lt;h2 id="test"&gt;Test&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;go test&lt;/code&gt;コマンドに&lt;code&gt;-list&lt;/code&gt;フラグが追加されました。
これに正規表現で引数を与えることで、テスト名・ベンチマーク名・Exampleテスト名を調べることができます。&lt;/p&gt;
&lt;h2 id="vet"&gt;Vet&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;vet&lt;/code&gt;コマンドがより強化されました。&lt;/p&gt;</description></item><item><title>docker-machineでRancherOSを使う</title><link>https://blog.web-apps.tech/docker-machine-with-rancheros/</link><pubDate>Thu, 24 Aug 2017 02:14:41 +0000</pubDate><guid>https://blog.web-apps.tech/docker-machine-with-rancheros/</guid><description>&lt;h1 id="docker-machineとそのメリット"&gt;docker-machineとそのメリット&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://docs.docker.com/machine/" target="_blank" rel="noopener"&gt;docker-machine&lt;/a&gt;
は仮想マシン上に&lt;a href="https://docs.docker.com/engine/" target="_blank" rel="noopener"&gt;Docker Engine&lt;/a&gt;
をインストールするツールです。
&lt;code&gt;docker-machine&lt;/code&gt;コマンドを使用することで、Dockerホストを作成・管理することが可能です。
docker-machineを使用してDockerホストを作成すると、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine env &amp;lt;MACHINE_NAME&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;でシェル評価可能なDocker接続情報を得ることができ、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;docker-machine env &amp;lt;MACHINE_NAME&amp;gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;とすることにより、そのセッション内ではあたかもローカル環境のDockerの様にコンテナを操作することが可能となります。&lt;/p&gt;
&lt;h1 id="docker-machineで使用するos"&gt;docker-machineで使用するOS&lt;/h1&gt;
&lt;p&gt;扨、通常docker-machineでDockerホストを作成すると、インストールされるOSは&lt;a href="http://boot2docker.io/" target="_blank" rel="noopener"&gt;Boot2Docker&lt;/a&gt;
ですが、docker-machineでは、ホスト作成時のコマンドラインオプションでisoイメージやシェルスクリプトを指定することでOSやDocker Engineのバージョンを変更することができます。&lt;/p&gt;
&lt;h2 id="rancheros"&gt;RancherOS&lt;/h2&gt;
&lt;p&gt;Boot2Dockerに類似したOSとして、&lt;a href="http://rancher.com/rancher-os/" target="_blank" rel="noopener"&gt;RancherOS&lt;/a&gt;
があり、&lt;code&gt;ros&lt;/code&gt;コマンドを使用することでインストール後でもDockerのバージョンを簡単に切り替えることができます。&lt;/p&gt;
&lt;p&gt;RancherOSは以前、仮想マシン環境のサポートとして、&lt;a href="https://github.com/rancher/os-vagrant" target="_blank" rel="noopener"&gt;Vagrant&lt;/a&gt;
用の環境を提供していましたが、現在(2017年8月)では、すでにサポートが終了しており、docker-machineを使用するようにというアナウンスが出ています。&lt;/p&gt;
&lt;p&gt;そこで、今回はdocker-machineを使用してRancherOSを立ちあげてみようと思います。&lt;/p&gt;
&lt;h1 id="docker-machineでrancherosを立ちあげる"&gt;docker-machineでRancherOSを立ちあげる&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://rancher.com/docs/os/v1.0/en/running-rancheros/workstation/docker-machine/" target="_blank" rel="noopener"&gt;公式ドキュメント&lt;/a&gt;
上に示されたコマンドをそのまま使用しても、途中でエラーが出てしまい(エラーが出ること自体は記述されていますが)、docker-machineをの大きなメリットである、&lt;code&gt;docker-machine env&lt;/code&gt;が使用できません。&lt;/p&gt;
&lt;p&gt;エラーを回避するためには、&lt;a href="https://github.com/rancher/install-docker" target="_blank" rel="noopener"&gt;Rancherのリポジトリ上にあるインストールスクリプト&lt;/a&gt;
を指定します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine create -d virtualbox --virtualbox-boot2docker-url https://releases.rancher.com/os/latest/rancheros.iso --engine-install-url https://raw.githubusercontent.com/rancher/install-docker/master/17.06.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;インストールが完了したら、&lt;code&gt;docker-machine ls&lt;/code&gt;コマンドで実行中のDockerホストの一覧を表示することができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker-machine ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ros - virtualbox Running tcp://192.168.99.100:2376 v17.06.0-ce
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id="docker-engineのバージョンを切り替える"&gt;Docker Engineのバージョンを切り替える&lt;/h1&gt;
&lt;p&gt;せっかくRancherOSを使用しているので、Docker Engineのバージョンを切り替えてみましょう。
Docker Engineのバージョンを切り替えるにはRancherOS上で&lt;code&gt;ros&lt;/code&gt;コマンドを使用するのでした。&lt;/p&gt;</description></item><item><title>Docker multi-stage builds</title><link>https://blog.web-apps.tech/docker-multi-stage-builds/</link><pubDate>Thu, 17 Aug 2017 02:06:00 +0000</pubDate><guid>https://blog.web-apps.tech/docker-multi-stage-builds/</guid><description>&lt;p&gt;Docker 17.05から、新機能として&lt;a href="https://docs.docker.com/engine/userguide/eng-image/multistage-build/" target="_blank" rel="noopener"&gt;&lt;strong&gt;multi-stage builds&lt;/strong&gt;&lt;/a&gt;
というものが導入されました。
これは、コンテナイメージをより最適化するために有用な機能で、Dockerfileからコンテナイメージをビルドする際にビルド依存のライブラリ/環境とランタイム依存のライブラリ/環境を切り分けることができる機能です。&lt;/p&gt;
&lt;p&gt;具体例を見てみましょう。
Go言語で書かれた何らかのアプリケーションをコンテナ上で動かすことを考えます。
以前までであれば、以下のような二つのDockerfileを用いて作成します。&lt;/p&gt;
&lt;p&gt;まずはビルド用Dockerfileです&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.7.3&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/go/src/github.com/someone/foo&lt;/span&gt;/&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; app.go .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -o app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;つぎに、実行用のDockerfileです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;busybox:latest&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/root&lt;/span&gt;/&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;このようにすることで、ビルド時にはGo言語のビルド環境が入ったコンテナを、実行時は(Go言語環境は不要なので)busyboxコンテナを使用することで、実行イメージを小さく抑えることができます。
しかし、このように二つのDockerfileを使用する場合、コンテナイメージのビルド手順が煩雑になる、複数ファイルのため管理しにくいなどの問題がありました。&lt;/p&gt;
&lt;p&gt;multi-stage buildsを実装されたことで、以下のようにDockerfileを一つにまとめることができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-dockerfile" data-lang="dockerfile"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.7.3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/go/src/github.com/someone/foo&lt;/span&gt;/&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; app.go .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;RUN&lt;/span&gt; &lt;span class="nv"&gt;GOOS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;linux go build -a -o app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;busybox:latest&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;/root&lt;/span&gt;/&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;COPY&lt;/span&gt; --from&lt;span class="o"&gt;=&lt;/span&gt;build /go/src/github.com/someone/foo/app .&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;CMD&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;一行目の&lt;code&gt;AS build&lt;/code&gt;、九行目の&lt;code&gt;--from=build&lt;/code&gt;がポイントです。&lt;/p&gt;</description></item><item><title>Go1.9rc1 is released!</title><link>https://blog.web-apps.tech/go1-9rc1_is_released/</link><pubDate>Wed, 26 Jul 2017 01:24:00 +0000</pubDate><guid>https://blog.web-apps.tech/go1-9rc1_is_released/</guid><description>&lt;p&gt;Go1.9rc1がリリースされました！
そこで、Go1.9のリリースノートをさらっと見てみようと思います。
(まだrc1なので、今後変更される場合があります。ご注意を)&lt;/p&gt;
&lt;p&gt;全部見ていくと、結構な量になりそうなので、すぐに影響のありそうな部分だけ、軽く見ていきましょう。&lt;/p&gt;
&lt;h1 id="type-alias"&gt;type alias&lt;/h1&gt;
&lt;p&gt;Go1.9ではType Aliasというものが導入されます。
これはその名の通り、型に別名をつけられるというもの。
言葉で説明するより、コードを見た方が早いと思いますので、コードを用意しました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;log&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;T1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;T2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;T1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Taro&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;call t1.Call()&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;call t2.Call2()&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Call2&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;T1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hello, &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;T2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Call2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hi, &amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;go1.8以前ではsyntax errorになるこのコードですが、go1.9では正常に動作し、以下のような出力をします。&lt;/p&gt;</description></item><item><title>Riot.jsにSass(SCSS)を導入する</title><link>https://blog.web-apps.tech/sass_into_riotjs/</link><pubDate>Wed, 19 Jul 2017 01:15:00 +0000</pubDate><guid>https://blog.web-apps.tech/sass_into_riotjs/</guid><description>&lt;p&gt;Riot.jsでは、標準でスタイルシートにLessを使用することができます。
その際の使用方法は簡単で、スタイルタグにtypeを指定するだけです。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;less&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;扨、ここで、イマドキな皆さんはLessじゃなくてSass(SCSS)を使いたい！と思うかもしれません(思いますよね？)
なので、Sassを使えるようにしてみましょう。&lt;/p&gt;
&lt;h1 id="基本方針"&gt;基本方針&lt;/h1&gt;
&lt;p&gt;基本的には、&lt;code&gt;riot.parser.css.sass&lt;/code&gt;にSassのコンパイラ関数を作成するだけです。
&lt;code&gt;riot.parser.css.sass&lt;/code&gt;には、引数として、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;タグ名&lt;/li&gt;
&lt;li&gt;stylesheet
が渡されます。この、第二引数をコンパイルして返す関数を作成すれば良いのです。&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id="ランタイムコンパイルでsassscssを使用する"&gt;ランタイムコンパイルでSass(SCSS)を使用する&lt;/h1&gt;
&lt;p&gt;ランタイムコンパイル時は&lt;code&gt;sass.js&lt;/code&gt;を使用します。
&lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;タグ内で、&lt;code&gt;https://cdn.rawgit.com/medialize/sass.js/v0.6.3/dist/sass.js&lt;/code&gt;を読み込むなどすれば良いでしょう。
その上で、タグのマウント前に以下の記述を追加します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;riot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parsers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stylesheet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Sass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stylesheet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id="gulp-riotプリコンパイルでsassscssを使用する"&gt;gulp-riotプリコンパイルでSass(SCSS)を使用する&lt;/h1&gt;
&lt;p&gt;glup-riotでプリコンパイルする際にSassを使用するには、&lt;code&gt;node-sass&lt;/code&gt;を使用して、&lt;code&gt;gulpfile.js&lt;/code&gt;に以下のように記述します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;gulp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gulp&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;riot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;gulp-riot&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;node-sass&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;riot&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;gulp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;app.tag&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;riot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;parsers&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;sass&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stylesheet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sass&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;renderSync&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stylesheet&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gulp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description></item><item><title>Vagrantで起動したVMからBOXを作る</title><link>https://blog.web-apps.tech/create_vagrant_box_from_vagrant_vm/</link><pubDate>Tue, 11 Jul 2017 02:39:00 +0000</pubDate><guid>https://blog.web-apps.tech/create_vagrant_box_from_vagrant_vm/</guid><description>&lt;p&gt;Vagrantで、centos/7等の標準的なBOXをベースにカスタムしたVMを保存しておいたり、配布したりするためにBOXを作る手順です。
自分用のメモとして。&lt;/p&gt;
&lt;h1 id="vm内での操作"&gt;VM内での操作&lt;/h1&gt;
&lt;h2 id="vboxguestadditionsを導入する"&gt;VBoxGuestAdditionsを導入する。&lt;/h2&gt;
&lt;p&gt;以下のソースを適当なファイルに保存する。(ここでは&lt;code&gt;$HOME/ins.sh&lt;/code&gt;とします。)
このとき、二行目はVirtualboxのバージョンに合わせて適宜書き換える。
リストは&lt;a href="http://download.virtualbox.org/virtualbox/" target="_blank" rel="noopener"&gt;こちら&lt;/a&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;yum install -y wget kernel kernel-devel perl gcc
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget http://download.virtualbox.org/virtualbox/5.1.18/VBoxGuestAdditions_5.1.18.iso
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir /media/VBoxGuestAdditions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mount -o loop,ro VBoxGuestAdditions_5.1.18.iso /media/VBoxGuestAdditions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sh /media/VBoxGuestAdditions/VBoxLinuxAdditions.run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm VBoxGuestAdditions_5.1.18.iso
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;umount /media/VBoxGuestAdditions
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rmdir /media/VBoxGuestAdditions
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;保存したスクリプトを管理者権限で実行します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo bash ins.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="yumをきれいにする"&gt;yumをきれいにする&lt;/h2&gt;
&lt;p&gt;軽量化のため、yumをきれいにします。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo yum clean all
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="ゼロ埋めして消す"&gt;ゼロ埋めして消す&lt;/h2&gt;
&lt;p&gt;圧縮効率向上のため、ゼロ埋めして消します。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo dd &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/zero &lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/EMPTY &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1M
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo rm /EMPTY
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h1 id="ホストからの操作"&gt;ホストからの操作&lt;/h1&gt;
&lt;h2 id="boxを作成する"&gt;BOXを作成する&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vagrant package
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;** box listに登録する&lt;/p&gt;</description></item><item><title>YAPC::Fukuoka 2017 HAKATAに行ってきました</title><link>https://blog.web-apps.tech/yapc_fukuoka_2017/</link><pubDate>Mon, 03 Jul 2017 02:04:00 +0000</pubDate><guid>https://blog.web-apps.tech/yapc_fukuoka_2017/</guid><description>&lt;p&gt;今回は言われました！「ブログを書くまでがYAPC!」
と言うことで、&lt;a href="https://yapcjapan.org/2017kansai/" target="_blank" rel="noopener"&gt;YAPC::Kansai 2017 OSAKA&lt;/a&gt;
(行ってきたときの記事は&lt;a href="https://blog.web-apps.tech/article/yapc_kansai_2017"&gt;こちら&lt;/a&gt;
)に引き続き、&lt;a href="https://yapcjapan.org/2017fukuoka/" target="_blank" rel="noopener"&gt;YAPC::Fukuoka 2017 HAKATA&lt;/a&gt;
に行ってきました。
YAPCはPerlのイベントで、&amp;ldquo;Yet Another Perl Conference&amp;quot;の略です。twitterハッシュタグは前回に引き続き&lt;a href="https://twitter.com/hashtag/yapcjapan" target="_blank" rel="noopener"&gt;#yapcjapan&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;福岡および九州は初めてでしたが、いや、暑いですね。
特にYAPCの翌日は非常に天気が良いものの、梅雨の湿気もあり、観光をしていて汗だくでした。&lt;/p&gt;
&lt;p&gt;今回も大阪同様ホテルはとらず、適当にやっていくことに。
意外となんとかなるものです。&lt;/p&gt;
&lt;h1 id="yapcfukuoka-2017-hakata"&gt;YAPC::Fukuoka 2017 HAKATA&lt;/h1&gt;
&lt;p&gt;今回も例に漏れず(?)寝坊でオープニングには間に合わず。
今回はPerl6の話は余り多くなかった印象です。&lt;/p&gt;
&lt;p&gt;セキュリティの話、コンテナの話、テストの話など、非常に多様なセッションがありました。&lt;/p&gt;
&lt;p&gt;今回のノベルティはなぜかモバイルバッテリーが二つも入っていたり、米が入っていたり、染み抜きペンが入っていたりととても面白い内容でした。
あ、いつものサイリュームも入ってましたよ。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_fukuoka_2017/images/yapc_fukuoka_2017_novelties_hu_94c4d00124ff86c2.jpg" alt="yapc_fukuoka_2017_novelties" /&gt;
&lt;/p&gt;
&lt;p&gt;個人スポンサーノベルティはビーチサンダル。これからの季節に良いですね。&lt;/p&gt;
&lt;h2 id="ltをしてきました"&gt;LTをしてきました。&lt;/h2&gt;
&lt;p&gt;今回はLTもしてきました。
タイトルは「&lt;a href="https://speakerdeck.com/nasa9084/wu-hu-su-qing-rasikiemacs" target="_blank" rel="noopener"&gt;嗚呼素晴らしきemacs&lt;/a&gt;
」です。&lt;/p&gt;
&lt;h2 id="ベストトーク賞"&gt;ベストトーク賞&lt;/h2&gt;
&lt;p&gt;YAPCでは恒例のベストトーク賞ですが、今回は徳丸さんのゲストセッションがベストトーク賞に選ばれました。
しかしご多忙な徳丸さん。クロージングの時点ですでに帰還してしまってました。
仕方ないので徳丸さんの会社にお勤めの方が代理で受け取ることに。
なんと賞品を渡す人は徳丸さんのセッションを聞いていなかったようで・・・
ベストトークを聞いていなかった人が代理の人に賞品を渡すという、なんとも面白い事態でした。&lt;/p&gt;
&lt;p&gt;ベストLT賞は&lt;a href="https://twitter.com/codehex" target="_blank" rel="noopener"&gt;@codehex&lt;/a&gt;
さんで、YAPC::Okinawaの宣伝でした。&lt;/p&gt;
&lt;h2 id="懇親会"&gt;懇親会&lt;/h2&gt;
&lt;p&gt;懇親会ではPixivさんから抽選でプレゼントをいただきました。
Pawooのロゴ入りのモバイルバッテリー(これで今回三つ目)です。&lt;/p&gt;
&lt;h1 id="次回のお話"&gt;次回のお話&lt;/h1&gt;
&lt;p&gt;次回YAPCは3月に沖縄で開催予定です。&lt;/p&gt;</description></item><item><title>Fujitsu FACOM128Bを見てきた</title><link>https://blog.web-apps.tech/fujitsu_facom128b/</link><pubDate>Tue, 06 Jun 2017 01:45:00 +0000</pubDate><guid>https://blog.web-apps.tech/fujitsu_facom128b/</guid><description>&lt;p&gt;&lt;a href="http://events.linuxfoundation.jp/events/open-source-summit-japan/extend-the-experience/tour" target="_blank" rel="noopener"&gt;Open Source Summit Fujitsu Museum Tour&lt;/a&gt;
)で、富士通 沼津工場まで行って、現在動作する世界最古のコンピュータであるリレーコンピュータ「FACOM128B」を見てきました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://ja.wikipedia.org/wiki/FACOM#FACOM_128" target="_blank" rel="noopener"&gt;Fujitsu FACOM128B&lt;/a&gt;
は1958年に作られたリレー式自動計算機で、富士通沼津工場に置かれているものは1959年製です。&lt;a href="http://www.fujitsu.com/jp/about/plus/museum/ikeda/tour/index.html" target="_blank" rel="noopener"&gt;Fujitsu Webサイト&lt;/a&gt;
から申し込みをすることで、中学生以上なら見学することができます。&lt;/p&gt;
&lt;p&gt;圧巻です。エンジニアなら一度は見ておくと、感動ものです。&lt;/p&gt;</description></item><item><title>emacs-macでtwittering-modeを使った際に毎回PINを聞かれる問題の解消</title><link>https://blog.web-apps.tech/emacs-mac-twittering-mode-every-asked-pin/</link><pubDate>Tue, 09 May 2017 00:49:00 +0000</pubDate><guid>https://blog.web-apps.tech/emacs-mac-twittering-mode-every-asked-pin/</guid><description>&lt;p&gt;twitterのクライアントとして、日頃からemacs上で動くクライアントの&amp;quot;twittering-mode&amp;quot;を使用しています。
ところが最近、新しいmacにインストールしたemacs-macでtwittering-modeを起動すると、毎回twitterのPINを聞かれるようになってしまいました。
毎回、毎回、起動時の暗号化フェーズで&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Encrypt failed Exit
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;と言われ・・・・
以前使っていたmacではこのようなことが無かったため、困っていたのですが、以下の手順により解決できました。&lt;/p&gt;
&lt;h1 id="背景"&gt;背景&lt;/h1&gt;
&lt;p&gt;結論から言うと、これはGnuPGのバージョンが新しくなったことによる問題でした。
GnuPG2.1.0から、gpg-agentとpinentryと呼ばれる二つのソフトウェアの利用が必須となりました。
twittering-mode事態はgpg-agentやpinentryが必須でも基本的に問題なく動作するようにはなっているハズ・・・でした。
しかし、これらのソフトウェアの必須化に伴って、これまで標準入力から入力できていたパスフレーズが標準入力から入力できなくなっており、そのために暗号化に失敗して毎回PINを聞く・・・という状態になっていたようです。&lt;/p&gt;
&lt;h1 id="解決策"&gt;解決策&lt;/h1&gt;
&lt;p&gt;みんな大好き&lt;a href="https://wiki.archlinuxjp.org/index.php/GnuPG#.E7.84.A1.E4.BA.BA.E3.81.AE.E3.83.91.E3.82.B9.E3.83.95.E3.83.AC.E3.83.BC.E3.82.BA" target="_blank" rel="noopener"&gt;arch wiki&lt;/a&gt;
に解決策がありました。
まず、&lt;code&gt;~/.gnupg/gpg-agent.conf&lt;/code&gt;に以下のように記述します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;allow-loopback-pinentry
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;つぎに、&lt;code&gt;~/.gnupg/gpg.conf&lt;/code&gt;に以下のように記述します。&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;pinentry-mode loopback
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最後に、gpg-agentを再起動します。
コマンドラインから、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ gpgconf --kill gpg-agent
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;でgpg-agentを再起動できます。&lt;/p&gt;
&lt;p&gt;以上で、twittering-modeが正常に使用できるようになるはずです。&lt;/p&gt;</description></item><item><title>MySQL on docker macな開発環境でローカルからMySQLに接続する</title><link>https://blog.web-apps.tech/mysql_on_docker_on_mac/</link><pubDate>Tue, 02 May 2017 06:57:00 +0000</pubDate><guid>https://blog.web-apps.tech/mysql_on_docker_on_mac/</guid><description>&lt;p&gt;MySQLをdocker上に立てることで、ローカルの環境を汚さずにMySQLを使ったアプリケーションの開発を行うことができます。
特に、練習段階や、動作確認などの場合、 &lt;code&gt;test_hogehoge&lt;/code&gt; な感じのデータベースやテーブルを作ってしまい、後片付けをしないために汚くなっていく、なんてこと、あるんじゃないでしょうか。&lt;/p&gt;
&lt;p&gt;さて、MySQL on dockerへの接続、今までローカルにMySQLを入れて開発していたのでちょっと躓きました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD password mysql:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;上記のように起動した場合、次のようにコマンドを実行することで接続することができます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ mysql -u hoge -p -h 127.0.0.1 --port &lt;span class="m"&gt;3306&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;特にポイントなのが、&lt;code&gt;-h 127.0.0.1&lt;/code&gt;の部分。&lt;code&gt;localhost&lt;/code&gt;にしてしまうと、socketで接続しようとして、エラーになっちゃうんですね。
ここでしばらく悩みました。。。&lt;/p&gt;
&lt;p&gt;以上、簡単ですがメモがてら。&lt;/p&gt;</description></item><item><title>golang: net/httpでBASIC認証</title><link>https://blog.web-apps.tech/golang_nethttp_basicauth/</link><pubDate>Tue, 02 May 2017 05:06:00 +0000</pubDate><guid>https://blog.web-apps.tech/golang_nethttp_basicauth/</guid><description>&lt;p&gt;golangでベーシック認証するのはどうしたら良いのかなー。って思ってたら、&lt;code&gt;net/http&lt;/code&gt;でhandlerに渡される&lt;code&gt;http.Request&lt;/code&gt;に&lt;code&gt;BasicAuth()&lt;/code&gt;というメソッドが生えてました。
これはBASIC認証用のユーザ名、パスワード、ヘッダ解析のフラグという値を返してくれます。
なので、&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BasicAuth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;hogehogeuser&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fugafugapasswd&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// something&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;とすることで認証することができます。簡単、簡単。
なお残念ながらダイジェスト認証はサポートされていない様子。&lt;/p&gt;</description></item><item><title>YAPC::Kansai 2017 OSAKAに行ってきました</title><link>https://blog.web-apps.tech/yapc_kansai_2017/</link><pubDate>Sun, 05 Mar 2017 04:12:00 +0000</pubDate><guid>https://blog.web-apps.tech/yapc_kansai_2017/</guid><description>&lt;p&gt;12月の&lt;a href="http://yapcjapan.org/2016hokkaido/" target="_blank" rel="noopener"&gt;YAPC::Hokkaido 2016 SAPPORO&lt;/a&gt;
(行ってきた時の記事は&lt;a href="https://blog.web-apps.tech/article/yapc_hokkaido_2016"&gt;こちら&lt;/a&gt;
)に引き続き、&lt;a href="http://yapcjapan.org/2017kansai/" target="_blank" rel="noopener"&gt;YAPC::Kansai 2017 OSAKA&lt;/a&gt;
に行ってきました。&lt;/p&gt;
&lt;p&gt;今回もブログを書くまでがYAPCとは言われなかった気がします。
YAPCはPerlのイベントで、&amp;ldquo;Yet Another Perl Conference&amp;quot;の略です。twitterハッシュタグは前回に引き続き&lt;a href="https://twitter.com/hashtag/yapcjapan" target="_blank" rel="noopener"&gt;#yapcjapan&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;私にとって、大阪はもちろん、関西自体が初めてで、かなり余裕のあるスケジュールを組んだために、どう時間を過ごしていいか悩むといった自体に。
空港に降り立ち、まずどうしよう、という状態ですね。困った。&lt;/p&gt;
&lt;p&gt;仕方がないので大阪出身の友人に、「大阪観光ってどこいったらいいのかな」と聞いてみたのですが、「まぁたこ焼き食べたりしたら？」と今ひとつ役に立たない返事。まぁ食べますけど！
それでも心斎橋とか難波に向かうとよいと教えてもらえたので、Googleマップ先生に頼りつつ、難波へ向かいました。&lt;/p&gt;
&lt;p&gt;結果、何をしたかというと、札幌からの移動前に新しく購入したスマホ用のあれこれをビックカメラで購入するという、大阪まできて何をやっているのかというなんとも残念な行動となってしまいました。&lt;/p&gt;
&lt;h1 id="ホテル探し"&gt;ホテル探し&lt;/h1&gt;
&lt;p&gt;今回、北海道から関西まで、勿論飛行機で移動したわけですが、実はホテルも取らずに(!)、YAPC以外は無計画での旅行でした。
とりあえずYAPC前日くらいはホテルに泊まらねば朝起きれない！ということで、ホテル探しをしました。
運良く会場(&lt;a href="http://www.motex.co.jp/" target="_blank" rel="noopener"&gt;MOTEX ホール&lt;/a&gt;
)の近くに割と安く宿を取ることができました。&lt;/p&gt;
&lt;p&gt;
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_kansai_2017/images/yapc2017kansai_hotel1_hu_87f302b71ee233e2.jpg" alt="yapc2017kansai_hotel1" /&gt;
こちらがそのお部屋の写真。シングルの部屋を5,500円(500ポイント適用後)でとったのですが、入ってみてびっくり、ツインの部屋でした。
安かったものの、なんとなく豪勢な感じ。&lt;/p&gt;
&lt;p&gt;夜ご飯は近くのお店でたこ焼きを食べました。
十八番というお店で、後で調べたら結構有名っぽいですね。美味しかった。
たこ焼きを塩で食べるというのは初体験でしたが、これもなかなかです。
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_kansai_2017/images/takoyaki_18ban_hu_f77de7706462de69.jpg" alt="takoyaki_18ban" /&gt;
&lt;/p&gt;
&lt;h1 id="yapckansai-2017-osaka"&gt;YAPC::Kansai 2017 OSAKA&lt;/h1&gt;
&lt;p&gt;開けて翌日。微妙に寝坊したおかげでオープニングには間に合いませんでした。&lt;/p&gt;
&lt;p&gt;一番印象に残ったトークは「Vue.jsで作るSPAから学ぶMVVM、非同期処理、その光と影」ですね。
タイトルにVue.jsと入っているにもかかわらず、Vue.jsという言葉が出て来たのは一度きり、SPAの話のはずなのに、「SPAはやめよう」と、なんだかタイトルに釣られた感が半端ない内容でした。
勿論内容も素晴らしく、「ブラウザはドキュメントビューアなんだからリッチなインターフェースを作るものではない」「ブラウザでリッチなインターフェースを作るのはなんでもVimでなんとかしようとするようなもの」「とはいっても作らなきゃいけない時もある」という、SPAはやるべきじゃないけど、現状やらなきゃいけないことはどうすれば良いのか、その時MV*はどのように構成したらいいのかといった、きちんと筋が通っていて、とても面白い話でした。&lt;/p&gt;
&lt;p&gt;次に印象に残っているのが、「Webアプリケーションのキャッシュ戦略とそのパターン」です。
こちらも「キャッシュは使わないほうがいい」という、タイトル詐欺みたいな話でしたが、非常に納得のいく内容でした。&lt;/p&gt;
&lt;p&gt;ベストトーク賞の投票で票を入れたのは「Webエンジニアに知ってほしいRDBアンチパターン」です。
内容もさることながら、やはり喋りが素晴らしいんです。とっても練習をしていると聞いています。&lt;/p&gt;
&lt;p&gt;ランチタイムはスポンサー企業の方と昼食をいただきました。
今回交通費支援をいただいたので、その対価のようなものです。
実際には、企業に関わるお話は結局あまりしなかったのですが、会場の近くはあまり飲食店がない印象で、昼食を取るのも大変そうでしたので、大変助かりました。&lt;/p&gt;
&lt;p&gt;YAPC::Kansai 2017 OSAKAのステッカーはこんな感じ。
&lt;img loading="lazy" src="https://blog.web-apps.tech/yapc_kansai_2017/images/yapc_kansai2017_sticker_hu_2b61357db7f329c8.jpg" alt="yapc_kansai2017_sticker" /&gt;
札幌の時のものと並べてはるには、上下を揃えるのが難しい形状で、ちょっと難儀します。&lt;/p&gt;
&lt;h1 id="次回のお話"&gt;次回のお話&lt;/h1&gt;
&lt;p&gt;次回YAPCは福岡で開催だそうです。&lt;a href="http://yapcjapan.org/2017fukuoka/" target="_blank" rel="noopener"&gt;YAPC::Fukuoka 2017 HAKATA&lt;/a&gt;
すでにチケットも発売されています。&lt;/p&gt;
&lt;p&gt;その後は沖縄、東京が企画されているそうです。
是非回りたい。&lt;/p&gt;</description></item><item><title>InfluxDBを触ってみた</title><link>https://blog.web-apps.tech/play_influxdb/</link><pubDate>Sat, 18 Feb 2017 09:45:00 +0000</pubDate><guid>https://blog.web-apps.tech/play_influxdb/</guid><description>&lt;p&gt;NoSQLを使うことも一般的になってきた昨今ですが、NoSQLの一種に、時系列データベース (Time Series Database; &lt;strong&gt;TSDB&lt;/strong&gt;)と呼ばれるものが有ります。
TSDBはその名のとおり、時系列データを取り扱うことに特化したDBです。
サーバ監視したログデータや、センサデータなんかを取り扱うことが得意なDBということですね。&lt;/p&gt;
&lt;p&gt;そのうち、&lt;a href="http://db-engines.com/" target="_blank" rel="noopener"&gt;DB-ENGINES&lt;/a&gt;
の&lt;a href="http://db-engines.com/en/ranking/time&amp;#43;series&amp;#43;dbms" target="_blank" rel="noopener"&gt;DB-Engines Ranking of Time Series DBMS&lt;/a&gt;
で一位を取っている&lt;em&gt;InfluxDB&lt;/em&gt;を触ってみました。&lt;/p&gt;
&lt;p&gt;InfluxDBの公式ドキュメントは&lt;a href="https://docs.influxdata.com/influxdb/v1.0/" target="_blank" rel="noopener"&gt;InfluxData | Documentation | InfluxDB Version 1.2 Documentation&lt;/a&gt;
にあります。&lt;/p&gt;
&lt;h1 id="参考にした資料実行環境"&gt;参考にした資料・実行環境&lt;/h1&gt;
&lt;p&gt;今回は&lt;a href="http://qiita.com/masato/items/eab9f76f21cbfd7c9b92" target="_blank" rel="noopener"&gt;Qiita/DockerのInfluxDBとGrafanaでdweet.ioのデータを可視化する&lt;/a&gt;
の前半を参考に、Docker上でInfluxDBを実行してみました。
なお、上記の記事中では、&lt;del&gt;tutum/influxdb&lt;/del&gt;というイメージを使用していますが、現在はInfluxDBオフィシャルのイメージが提供されていますので、そちらを利用します。
最新の安定版を利用しますので、InfluxDBのバージョンは1.2.0です。&lt;/p&gt;
&lt;h1 id="influxdbコンテナを起動する"&gt;InfluxDBコンテナを起動する&lt;/h1&gt;
&lt;p&gt;早速InfluxDBコンテナを起動してみます。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker pull influxdb
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run --name influxdb_test -p 8083:8083 -p 8086:8086 influxdb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;これだけです。簡単ですね。Exposeしているポートの中身は以下のようになっています。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;8083: Admin Web インターフェース&lt;/li&gt;
&lt;li&gt;8086: HTTP API&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="admin-uiにアクセスする"&gt;Admin UIにアクセスする&lt;/h2&gt;
&lt;p&gt;Admin UIにアクセスしてみます。
InfluxDBにはWebアクセスできるUIがついています。&lt;/p&gt;
&lt;p&gt;まずはコンテナのIPを調べてみましょう。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker inspect influxdb_test
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;HostConfig &amp;gt; NetworkSettings &amp;gt; Networks &amp;gt; bridge &amp;gt; IPAddress にコンテナのIPが記載されています。
今回は&lt;code&gt;172.17.0.2&lt;/code&gt;だったとして進めます。&lt;/p&gt;</description></item><item><title>Python 3でbottle-websocketを使う</title><link>https://blog.web-apps.tech/bottle-websocket_with_python3/</link><pubDate>Tue, 10 Jan 2017 17:05:00 +0000</pubDate><guid>https://blog.web-apps.tech/bottle-websocket_with_python3/</guid><description>&lt;p&gt;Python 3で&lt;a href="https://github.com/zeekay/bottle-websocket" target="_blank" rel="noopener"&gt;bottle-websocket&lt;/a&gt;
がそのままでは動かなかったので簡単にメモしておきます。&lt;/p&gt;
&lt;h1 id="解決方法"&gt;解決方法&lt;/h1&gt;
&lt;p&gt;通常通り&lt;code&gt;pip install bottle-websocket&lt;/code&gt;してから、 &lt;code&gt;pip install karellen-geventws&lt;/code&gt;すると動作するようになります。
karellen-geventwsはGeventWebSocketのforkで、Python 3に対応しています。&lt;/p&gt;</description></item><item><title>学生が勉強会/コミュニティを運営するということ</title><link>https://blog.web-apps.tech/community_advent/</link><pubDate>Sat, 17 Dec 2016 06:37:00 +0000</pubDate><guid>https://blog.web-apps.tech/community_advent/</guid><description>&lt;p&gt;この記事は&lt;a href="http://qiita.com/advent-calendar/2016/event-management" target="_blank" rel="noopener"&gt;IT勉強会/コミュニティ運営 Advent Calendar 2016&lt;/a&gt;
に寄せて書いた記事です。
執筆者は&lt;a href="https://twitter.com/nasa9084" target="_blank" rel="noopener"&gt;@nasa9084&lt;/a&gt;
です。
前日の記事は一般社団法人LOCALさんの&lt;a href="http://qiita.com/local_hokkaido/items/e15c8e80034e7f1c45ac" target="_blank" rel="noopener"&gt;一般社団法人LOCAL のご紹介&lt;/a&gt;
でした。&lt;/p&gt;
&lt;h1 id="まずはじめに"&gt;まずはじめに&lt;/h1&gt;
&lt;p&gt;あまりネット上、特にブログで自己紹介をする機会というのは多くなく、このブログ単体で言うならば、とある理由があって以前書いていたブログから移行してきたばかりなので、自己紹介というものをすこしはしているのですが、折角の機会でもあるので、ある程度きちんと自己紹介から始めさせていただくこととします。
どうもこんにちは&lt;a href="https://twitter.com/nasa9084" target="_blank" rel="noopener"&gt;nasa9084&lt;/a&gt;
といいます。
現在試される大地であるところの北海道は札幌市に住んでいる大学生(0x17歳)です。
来春4月から、東京で就職予定ですが、卒業論文の進捗が芳しくありません。
&lt;a href="https://builderscon.io][builderscon]]%e3%82%84%e3%80%81[[https://www.pycon.jp" target="_blank" rel="noopener"&gt;PyCon JP&lt;/a&gt;
というカンファレンスのスタッフをしたりしています。&lt;/p&gt;
&lt;h1 id="でじぽろという勉強会"&gt;「でじぽろ」という勉強会&lt;/h1&gt;
&lt;p&gt;昨年のから今年の10月まで、札幌で&lt;a href="https://digiporo.charakoba.com" target="_blank" rel="noopener"&gt;&lt;strong&gt;でじぽろ&lt;/strong&gt;&lt;/a&gt;
という勉強会を主催していました。
でじぽろはIT技術初心者、もう少し具体的に言うと&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UNIX/Linuxに興味がある/使ったことがある&lt;/li&gt;
&lt;li&gt;プログラミングに興味がある/すこしやったことがある&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;といったレベルの方を対象として月に一回開催していた勉強会です。&lt;/p&gt;
&lt;p&gt;私と、&lt;a href="https://twitter.com/chamaharun" target="_blank" rel="noopener"&gt;@chamaharun&lt;/a&gt;
の二人で主催をしていて、内容としては&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP入門&lt;/li&gt;
&lt;li&gt;SQL入門&lt;/li&gt;
&lt;li&gt;プログラミング言語大横断&lt;/li&gt;
&lt;li&gt;Linuxディストリビューションの紹介&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;なんかをやったりしていました。&lt;/p&gt;
&lt;h1 id="勉強会を開催するということ"&gt;勉強会を開催するということ&lt;/h1&gt;
&lt;p&gt;扨、少しばかり前置きが長くなってしまいましたが、そろそろ本題であるところの運営に関する部分の話をしなきゃいけないですね。
今回は&lt;a href="http://qiita.com/advent-calendar/2016/event-management" target="_blank" rel="noopener"&gt;IT勉強会/コミュニティ運営 Advent Calendar&lt;/a&gt;
ですから、多くの大事なところは他の大人な方々が書いてくれてますので、今日は私が特に気をつけたほうがいいと思っていることだったり、おすすめの方法論だったりについて書きましょう。&lt;/p&gt;
&lt;h2 id="持ち出しはしない"&gt;持ち出しはしない&lt;/h2&gt;
&lt;p&gt;勉強会を継続的に運営するにあたり、主催者やスタッフの財布からお金が出ていくことは避けたほうがよいと思います。
楽しいことがしたいと思って始める(であろう)勉強会ですが、事前準備や当日の運営、終わったあとの処理など、結構な時間や労力がかかります。これは大きな負担で、この上開催にお金がかかるとなると、金額が大したことない額だったとしても、継続するのは心理的に困難になるでしょう。
せっかく立ち上がった勉強会も、「主催のお金がないので継続開催できません」では悲しいものがあります。
初回開催など、立て替える必要がある場面はあると思いますが、開催後にでも精算を行って、主催者・スタッフのマイナスが無いようにしたほうがよいです。&lt;/p&gt;
&lt;h2 id="自分に強制するという選択肢"&gt;自分に強制する、という選択肢&lt;/h2&gt;
&lt;p&gt;多くのコミュニティ運営者は、「勉強会やコミュニティの運営は仕事ではないので、開催しなければならないという意識を持って開催するのはつらいからやめたほうがいい」と言っている様に思います。
わたしも多くの部分で賛成ですが、個人の性格だったり、勉強会の目的次第では、「&lt;strong&gt;強制的に開催する&lt;/strong&gt;」という選択肢もある、と覚えておいてください。&lt;/p&gt;
&lt;p&gt;私が主催していたでじぽろの目的の一つに、「主催も勉強する」というものがあります。初心者向けなんて謳っているけれど、主催も学生だから、一緒に勉強していきましょう！ということです。
加えて、主催である私も、&lt;a href="https://twitter.com/chamaharun" target="_blank" rel="noopener"&gt;@chamaharun&lt;/a&gt;
も、比較的怠惰な性格をしています。
そこで、でじぽろ運営にあたって、一つルールを決めました。
それが、「つらくても、話すネタがなくても、とにかく月に一回開催する」というルールです。&lt;/p&gt;
&lt;p&gt;不定期開催というのは、心理的負担も減りますが、それと同時に、気づいたら二回目の開催がないまま時間だけが過ぎていた、なんてことになりやすい開催方式でもあります。
定期的に開催することを自分に義務付けることで、勉強会を開催することが習慣になります。
継続開催を目標の一つとする場合、この選択は大きな助けともなってくれることと思います。
&lt;strong&gt;でじぽろ&lt;/strong&gt;は、このルールのおかげで、一年間毎月開催することができたと思っています。&lt;/p&gt;
&lt;h2 id="あまり深く考えない"&gt;あまり深く考えない&lt;/h2&gt;
&lt;p&gt;勉強会を主催するということは、実はそれほどハードルの高いことではありません。「とりあえず気が向いたからはじめてみた」くらいの気持ちで十分です。
でじぽろも、はじめは友人との呑みの席で、「なんか勉強会とかやってみたいよね」で始まったのでした。
皆言ってることでは有りますが、&lt;em&gt;仕事ではない&lt;/em&gt;のです。辛かったり、つまらなかったらやめていいんです。
そして、気が向いたらまた新しく始めてみたらいいと思いますよ。&lt;/p&gt;
&lt;h2 id="懇親会をする"&gt;懇親会をする&lt;/h2&gt;
&lt;p&gt;個人的にこれはとても重要なことだと思っているのですが、懇親会はぜひやったほうがいいと思います。4日の&lt;a href="http://blog.hotolab.net/entry/gotandajs_1st_anniv" target="_blank" rel="noopener"&gt;エンジニアコミュニティのつくりかた&lt;/a&gt;
でも書かれていましたが、&lt;strong&gt;懇親会が本編だと考えています&lt;/strong&gt;。
多くの場合、勉強会で発表されることは、今の御時世ですから、検索したら出てきます。わざわざオフラインで集まってスクリーンの前で発表なんて聞かなくてもいいんです。
それでもやっぱり勉強会/コミュニティに集まるというのは、&lt;strong&gt;人と人との出会い&lt;/strong&gt;が重要だからだと思います。
そして、発表のときというのは、座っているうち8割9割の人は質問もしないですし、発表後に発表者に挨拶に行ったりもしません。
これでは、休みの日に、わざわざ集まっている意味は無いと思います。&lt;/p&gt;
&lt;p&gt;懇親会を開催することで、大勢の前の発表では言えないことだったり、発表するほどでは無いけど趣味で触っている新技術の話だったり、そういったものに大きな意味が有ります。twitterやfacebookでつながりを持つことに意味があるんです。&lt;/p&gt;
&lt;h1 id="学生が勉強会を運営するということ"&gt;「学生が」勉強会を運営するということ&lt;/h1&gt;
&lt;p&gt;扨、それなりの量を書いた(気になっている)のですが、他の記事を書いている方々は皆さん大人(学生ではない)の方々ですね。
ココで一つ、「&lt;strong&gt;学生が勉強会を運営すること&lt;/strong&gt;」のメリットを考えてみます。&lt;/p&gt;</description></item><item><title>pyorgというパッケージを作りました</title><link>https://blog.web-apps.tech/create_pyorg/</link><pubDate>Mon, 12 Dec 2016 17:19:00 +0000</pubDate><guid>https://blog.web-apps.tech/create_pyorg/</guid><description>&lt;p&gt;この記事は&lt;a href="http://qiita.com/advent-calendar/2016/emacs" target="_blank" rel="noopener"&gt;Emacs Advent Calendar 2016&lt;/a&gt;
の、13日目の記事で、執筆者は &lt;a href="https://twitter.com/nasa9084" target="_blank" rel="noopener"&gt;@nasa9084&lt;/a&gt;
です。
前日はfujimisakariさんの&lt;a href="http://blog.fujimisakari.com/elisp_useful_for_programming/" target="_blank" rel="noopener"&gt;プログラミングに役立つelisp10選&lt;/a&gt;
でした。&lt;/p&gt;
&lt;h1 id="org記法でブログを書きたい"&gt;org記法でブログを書きたい&lt;/h1&gt;
&lt;p&gt;全国のEmacsユーザの皆さん、org-modeは使っていますか？私は使っています。
普段Pythonを書く私にとって、&lt;code&gt;#&lt;/code&gt;はコメントアウトのイメージで、&lt;code&gt;#&lt;/code&gt;を見出しに使うmarkdownは(ダメってほどじゃないですけど)なんとなく好きになれません。Emacsユーザということもあり、細かいメモを取るときや、スライドを作るときはorg-modeを使っています。&lt;/p&gt;
&lt;p&gt;そんなわけで、慣れ親しんだorg記法。ブログを書くときも使いたいと考えました。
しかし、マークダウンで書くことができるブログや、或いはorgで書いたものをwordpressにアップすることができるelispなんかも有りましたが、どうもしっくり来ません。
そんな折に運用していたWordPressが使えなくなり、このブログシステムを作りました。
Pythonで使えるorg記法パーサも探したのですが、どれもブログで使えるようなものではなく、自分で変換機構も作成することにしました。
最初はブログシステムの中にorgをHTMLに変換するフィルターを作ればいいかな、と思って書き出したのですが、コレがなかなかうまく行かず。最終的にパーサとしてパッケージ化したので、そのお話をさせていただこうと思います。&lt;/p&gt;
&lt;h1 id="正規表現の置換だけで実装してみた"&gt;正規表現の置換だけで実装してみた&lt;/h1&gt;
&lt;p&gt;org記法を使いたいとは言っても、ブログ記事を書くのに使いたいだけなので、チェックボックスや時間に関する部分など、org-modeの大部分は必要ありません。文字の装飾部や見出し、リストが実装されれば十分です。
ですので、最初はわざわざ構文木などを作らずとも、単純に正規表現で置換すればいいのではと考えて実装を始めました。
しかしコレが大きな間違いだったのです。&lt;/p&gt;
&lt;h2 id="リスト"&gt;リスト&lt;/h2&gt;
&lt;p&gt;問題の１つめは、ネストしたリストを使えないことでした。
単純に正規表現で行ごとに置換していく都合上、ネストしたリストを解析することができません。この段階で、ネストしたリストは使わないことにしよう、と考えました。
しかし、実際に実装してみてわかったのですが(気づくのが遅い)、問題はそれだけではありませんでした。
リストが始まったことや終わったことを判断できないのです。いま置換している行はリストの始めなのか(つまり&lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;が必要なのか)、真ん中なのか、終わりなのか、判断することができないのです。これは困りました。&lt;/p&gt;
&lt;h2 id="スラッシュ"&gt;スラッシュ&lt;/h2&gt;
&lt;p&gt;更に大きな問題が潜んでいました。斜体とリンクです。
ご存知のように、URLは区切り文字としてスラッシュを多用します。また、org-modeでは斜体をスラッシュで挟んだ形で表します。
このせいで、URLの一部が斜体としてマークアップされてしまう事態が発生しました。
これはちょっと困ったものです。とりあえず斜体を使わないこととしましたが、これには不満が残ります。&lt;/p&gt;
&lt;h2 id="結局パーサとしてパッケージ化"&gt;結局パーサとしてパッケージ化&lt;/h2&gt;
&lt;p&gt;更に、テーブルの実装ができないなど、org記法が使える！というには不満点が多すぎました。
そんなわけで、改めて外部モジュールとして、org記法のパーサを書きました。org記法で書かれたテキストを読み込み、解析し、抽象構文木を生成します。そこからHTMLを出力することも可能です。GitHub上でソースも公開しています(&lt;a href="https://github.com/nasa9084/py-org][nasa9084/py-org" target="_blank" rel="noopener"&gt;nasa9084/py-org&lt;/a&gt;
)。
コレをブログシステムに組み込むことでorgでブログを書くことができるという寸法です。
また、当初予定してはいなかったのですが、gitのsubmoduleで管理するのはバージョンアップの際などいろいろと面倒なので、パッケージ化してPyPIへとアップしました(&lt;a href="https://pypi.python.org/pypi/pyorg" target="_blank" rel="noopener"&gt;pyorg&lt;/a&gt;
)。
現在はバージョン0.1.3として、見出し、リスト、テーブル、リンク、画像、引用、文字の強調を実装済みです。今後、少しずつ拡張予定ですが、当面はリファクタリングを進めようと思っています。&lt;/p&gt;
&lt;p&gt;以上、pyorgのお話でした。&lt;/p&gt;</description></item><item><title>YAPC::Hokkaido 2016 SAPPOROに行ってきました</title><link>https://blog.web-apps.tech/yapc_hokkaido_2016/</link><pubDate>Fri, 09 Dec 2016 16:34:00 +0000</pubDate><guid>https://blog.web-apps.tech/yapc_hokkaido_2016/</guid><description>&lt;p&gt;ブログを書くまでがYAPC!とは言われなかった気がしますが書きます。&lt;/p&gt;
&lt;p&gt;昨年で終了したYAPC::Asia Tokyoから一年、新生YAPCとして開催された&lt;a href="http://yapcjapan.org/2016hokkaido/" target="_blank" rel="noopener"&gt;&lt;strong&gt;YAPC::Hokkaido 2016 SAPPORO&lt;/strong&gt;&lt;/a&gt;
に参加しました。
YAPCはPerlのイベントで、&amp;ldquo;Yet Another Perl Conference&amp;quot;の略です。twitterハッシュタグは&lt;a href="https://twitter.com/hashtag/yapcjapan" target="_blank" rel="noopener"&gt;#yapcjapan&lt;/a&gt;
でした。&lt;/p&gt;
&lt;p&gt;当日の札幌はすごい雪で、東京発の飛行機が飛ばないという事態が発生、登壇者もなかなか札幌まで到達できず、スタッフさん達はなかなか大変な一日だったのではないかな、という印象です。&lt;/p&gt;
&lt;p&gt;スペシャルセッションである対談セッションは、Amazon Web Service、Google、Microsoft、さくらインターネットというクラウド大手4社が集って対談を行うという、非常に豪華な一時間でした。
基調講演はrebuild.fmのmiyagawaさんで、CDNのお話という、これまた普段はなかなか聞くことができない内容でした。
そのほか、emacs界隈で有名なsyohexさん、あちこちの界隈で有名な小飼弾さんなどなど、、、なかなかに濃い内容でした。&lt;/p&gt;
&lt;p&gt;今回は複数抽選が有り、Azure本(&lt;a href="http://amzn.to/2hpRrQj]" target="_blank" rel="noopener"&gt;Azureテクノロジ入門&lt;/a&gt;
)とLINEビーコンが贈呈されました。私も運良くAzure本に当選し、頂くことができました。ありがたい・・・&lt;/p&gt;
&lt;p&gt;当日チケットは1,000円なのに、前夜祭、懇親会がそれぞれ3,500円という、不思議なチケット価格が少しおもしろかったように思います。
次回YAPCは2017年3月4日に大阪で、YAPC::Kansaiとして開催される予定です。&lt;/p&gt;</description></item><item><title>Pythonとわたし</title><link>https://blog.web-apps.tech/python_with_me/</link><pubDate>Mon, 05 Dec 2016 08:13:00 +0000</pubDate><guid>https://blog.web-apps.tech/python_with_me/</guid><description>&lt;p&gt;この記事は、&lt;a href="http://www.adventar.org/calendars/1741" target="_blank" rel="noopener"&gt;PyCon JP Advent Calendar&lt;/a&gt;
5日目へ寄せて書いた記事です。
執筆は&lt;a href="https://twitter.com/nasa9084" target="_blank" rel="noopener"&gt;@nasa9084&lt;/a&gt;
です。
昨日は寺田さんによる、&lt;a href="https://www.cmscom.jp/blog/v63gcs" target="_blank" rel="noopener"&gt;PyCon JPの立ち上げ&lt;/a&gt;
という記事でした。&lt;/p&gt;
&lt;h1 id="pythonと私の想い出"&gt;Pythonと私の想い出&lt;/h1&gt;
&lt;p&gt;PyCon JPアドベントカレンダーのテーマは「&lt;strong&gt;Pythonと私の想い出&lt;/strong&gt;」だそうです。
私が初めてまぁそれなりと言える程度にかけるようになったプログラミング言語がPythonでした。
なんどもCに挑戦しては挫折し、を繰り返していたのですが、Pythonのおかげで簡単なプログラムはかけるようになったんでした。&lt;/p&gt;
&lt;p&gt;扨、すでに行き先がよくわからなくなってきているこの記事ですが、もう少し私とPythonとの関わりを書いていきましょうかね。&lt;/p&gt;
&lt;h2 id="pythonを使う理由"&gt;Pythonを使う理由&lt;/h2&gt;
&lt;p&gt;もともと、私はHTMLから、ソースコードというものをエディタで書く、という世界に入ってきたんです。小学校高学年くらいの頃だったでしょうか。
最初はホームページビルダーでWebサイトを書いていたんですが、当時(今でもあるのかな？)、小学生でも使えるJavaScript集みたいなサイトがありまして、例えば、headタグの直後にコピペするとなんかカーソルにきらきらしたのがくっついてくるようになる、とかですね、今となってはとっても懐かしい感じのものがたくさんあったわけですよ。
そんなのをコピペするために、ホームページビルダーでソースコードビュー的なものを開きまして、コピペをしていたわけですね。
HTMLなんてまだまだ書けなかった私ですが、なんとなくルールがわかるんですね。そうすると、なんだか無駄っぽいのがあるわけですよ。
そういうのを、ちょこちょこと手作業で消していってみるわけです。
今思うと、リファクタリングのはしりみたいなもんです。これが私のソースコードを編集することの原点だったんです。&lt;/p&gt;
&lt;p&gt;ときは流れまして、Pythonという言語に出会います。
聞くところによると、この言語、&lt;strong&gt;インデントをきちんとしないと動作しない&lt;/strong&gt;そうじゃないですか。だれが書いてもそれなりに読みやすいコードになると。
もともとソースコードを綺麗にするのが楽しくてソースコードを触り始めた私ですから、これはとても気に入りました。
そうして私はPythonの世界にずぶずぶと浸かっていくのでありました・・・&lt;/p&gt;
&lt;h2 id="github-repository"&gt;GitHub Repository&lt;/h2&gt;
&lt;p&gt;現在、私のGitHubリポジトリ(&lt;a href="https://github.com/nasa9084" target="_blank" rel="noopener"&gt;https://github.com/nasa9084&lt;/a&gt;
)の数は、ちょうど20だそうです。自分が主となって開発しているものの、意味づけという理由があったりしてOrganizationを切り分けているものもありますから、20以上30未満、といったところでしょうか。
このうち、主にPythonで書いているリポジトリは10個程度で、半分には届かないものの、かなりの割合を占めています。&lt;/p&gt;
&lt;h2 id="pycon-jp-2016"&gt;PyCon JP 2016&lt;/h2&gt;
&lt;p&gt;2016年はPyCon JP 2016のスタッフをしました。PyCon JPは東京開催で、もちろんスタッフの多くは東京(または東京近郊)在住で、オフラインミーティングや作業日の開催地も東京です。
一応、都合のつく限りリモートでも参加をするんですが、これがなかなか難しいのです。
解決方法はまだわからないのですが、来年は東京で就職なので、遠方のスタッフがもっと溶け込みやすいようになにか頑張りたいと思っています。&lt;/p&gt;
&lt;h2 id="eureka"&gt;Eureka&lt;/h2&gt;
&lt;p&gt;&lt;del&gt;実は、このブログのシステムもPythonで書かれています。構成としては、プログラム部がbottle + beaker + jinja2、アプリケーションサーバがuWSGI、HTTPサーバがnginxという構成です。
現状、JavaScriptは一切使っていないため、(特に管理画面において)残念な仕様の部分が多いです。
なんとかしたい。&lt;/del&gt;
ブログ移転で違うシステムになりました。&lt;/p&gt;
&lt;h1 id="まとめ的な"&gt;まとめ的な&lt;/h1&gt;
&lt;p&gt;そろそろ長くなってきましたし、もうなんの話かわからなくなってきましたので、この辺で終わりにしようと思います。
とりあえずですね。何が言いたいかというと、&lt;strong&gt;Pythonはいいぞ&lt;/strong&gt;ということです。
ぜひPyCon JP 2017にもお越しください。&lt;/p&gt;</description></item><item><title>builderscon tokyo 2016 を開催しました！</title><link>https://blog.web-apps.tech/builderscon_tokyo_2016/</link><pubDate>Mon, 05 Dec 2016 04:34:00 +0000</pubDate><guid>https://blog.web-apps.tech/builderscon_tokyo_2016/</guid><description>&lt;p&gt;過ぎし2016年12月3日、&lt;strong&gt;builderscon tokyo 2016&lt;/strong&gt;を開催しました。
builderscon tokyo 2016には(一応)コアスタッフとして、初期のウェブサイト制作等を行いました。
blogを書くまでがbuilderscon!ということなのでブログを書きましょう。&lt;/p&gt;
&lt;p&gt;いやね、builderscon スタッフの皆さんすごい人が揃いすぎてて、私のような若造がリモート参加だと、ちょっとしたすきに話が進んじゃってて。なかなか大変です。
ただ、そんなすごい人たちが色々と決めたり準備を進めたりするのを見るのはすごく勉強になりました。&lt;/p&gt;
&lt;p&gt;当日のトークは、php.iniの話だったり、ビールサーバーの話だったり、キーボードをつくる話だったり、ほんとなんか、尖った話が沢山でした。&lt;/p&gt;
&lt;p&gt;トークもね、一応応募したんですが、当然の如く落選しました。
コレは仕方ないですよ。
私もトーク採用フローに参加しましたけど、他のトークのほうが聞きたかったですもん。&lt;/p&gt;
&lt;p&gt;次はbuilderscon tokyo 2017の開催が決まっています!今度は1000人規模ですよ！
&lt;a href="http://2017.tokyo.builderscon.io/" target="_blank" rel="noopener"&gt;builderscon tokyo 2017&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;興味のある人はとりあえずSlackに入ってみるといいですよ。
&lt;a href="https://slack-invite-dot-builderscon-1248.appspot.com/" target="_blank" rel="noopener"&gt;builderscon slack invite form&lt;/a&gt;
&lt;/p&gt;</description></item></channel></rss>