<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Go on blog.kyu08.com</title>
    <link>https://blog.kyu08.com/pr-344/tags/go/</link>
    <description>Recent content in Go on blog.kyu08.com</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>ja</language>
    <copyright>blog.kyu08.com</copyright>
    <lastBuildDate>Sun, 01 Mar 2026 09:00:32 +0900</lastBuildDate><atom:link href="https://blog.kyu08.com/pr-344/tags/go/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Go Conference mini in Sendai 2026に参加した</title>
      <link>https://blog.kyu08.com/pr-344/posts/go-con-mini-in-sendai-2026/</link>
      <pubDate>Sun, 01 Mar 2026 09:00:32 +0900</pubDate>
      
      <guid>https://blog.kyu08.com/pr-344/posts/go-con-mini-in-sendai-2026/</guid>
      <description>2026/02/21(土)に仙台で行われたGo Conference mini in Sendai 2026に参加したのでその内容をまとめる。 Go Conference mini in Sendai 20262026年2月21日（土）</description>
      <content>&lt;p&gt;&lt;img src=&#34;closing-slide.webp&#34; alt=&#34;&#34; loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;2026/02/21(土)に仙台で行われたGo Conference mini in Sendai 2026に参加したのでその内容をまとめる。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;blogcard&#34; data-url=&#34;https://sendaigo.jp/&#34; data-auto-fetch=&#34;false&#34;&gt;
  &lt;a href=&#34;https://sendaigo.jp/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;blogcard-link&#34;&gt;&lt;div class=&#34;blogcard-thumbnail&#34;&gt;
      &lt;img src=&#34;https://sendaigo.jp/ogp.png&#34; alt=&#34;Go Conference mini in Sendai 2026&#34; loading=&#34;lazy&#34;&gt;
    &lt;/div&gt;&lt;div class=&#34;blogcard-content&#34;&gt;
      &lt;div class=&#34;blogcard-title&#34;&gt;Go Conference mini in Sendai 2026&lt;/div&gt;&lt;div class=&#34;blogcard-description&#34;&gt;2026年2月21日（土）開催 - Go Forward Together - 東北から広がるGoコミュニティ&lt;/div&gt;&lt;div class=&#34;blogcard-url&#34;&gt;https://sendaigo.jp/&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;h2 id=&#34;keynote静的解析からみるgoの過去と未来&#34;&gt;【KeyNote】静的解析からみるGoの過去と未来&lt;/h2&gt;
&lt;p&gt;tenntennさんによるキーノート。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container google-slides&#34;&gt;
      &lt;iframe src=&#34;https://docs.google.com/presentation/d/14e9PiaKbyqcZTu5mYCKBqa9MokJhxmT0WePHxwPzCmg/embed?start=false&amp;loop=false&amp;delayms=3000&#34; frameborder=&#34;0&#34; width=&#34;960&#34; height=&#34;569&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;最後に紹介されていたGo1.27のアノテーションで静的解析をできるようにする機能は今まさに自分が欲している機能&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;なので調べてみようと思った。&lt;/p&gt;
&lt;p&gt;以下メモ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;//line a.go:1&lt;/code&gt;のような記法は知らなかった。
&lt;ul&gt;
&lt;li&gt;調べてみたところ&lt;code&gt;line directive&lt;/code&gt;という名前がついているようだった。&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;こんな感じでコンパイラが出力するエラーメッセージなどが上書きされる。
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;line-directive.webp&#34; alt=&#34;&#34; loading=&#34;lazy&#34; /&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://go.dev/play/p/Thvs9U8Twvj&#34; target=&#34;_blank&#34; &gt;https://go.dev/play/p/Thvs9U8Twvj&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;自動生成されたコードのエラーを元のコードの行番号で表示したいときなどに使われるらしい。(例えば自動生成されたGoファイルでのエラーに対してprotoファイルの行番号をエラーに表示したいケースなど)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;go test -cover&lt;/code&gt;を実行すると裏側では&lt;code&gt;go tool cover&lt;/code&gt;が実行され、計測用のコードが挿入される&lt;/li&gt;
&lt;li&gt;Goがセルフホスティングされるようになったのは2015年（Go1.5）（それまではC）
&lt;ul&gt;
&lt;li&gt;(まだ10年しかたってないんだなー)&lt;/li&gt;
&lt;li&gt;ここからコンパイラのコードが既存標準パッケージと共通化されたりするようになった&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2019
&lt;ul&gt;
&lt;li&gt;goplsが登場&lt;/li&gt;
&lt;li&gt;最初はgolspだったがしれっと名前が変わったらしいw&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Go 1.27
&lt;ul&gt;
&lt;li&gt;アノテーションによる静的解析
&lt;ul&gt;
&lt;li&gt;一点もののlinterを作らなくてよくなる。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;//go:fix inline&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://go.dev/doc/go1.26#go-command&#34; target=&#34;_blank&#34; &gt;https://go.dev/doc/go1.26#go-command&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;xxしたあとにyyする、みたいな制約をアノテーションで表現できるようになる（らしい。が一次情報は見つけられていない）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ai時代のgo開発2026-爆速開発のためのガードレール&#34;&gt;AI時代のGo開発2026 爆速開発のためのガードレール&lt;/h2&gt;
&lt;p&gt;UPSIDERのRyo MimuraさんによるAI時代の開発生産性を保つにあたっての課題と対策についてのセッション。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container docswell&#34;&gt;
      &lt;div class=&#34;docswell-placeholder&#34; data-src=&#34;https://www.docswell.com/s/r4mimu/ZQXGNY-2026-02-21-102435?slide=1&#34; style=&#34;width:100%;height:569px;background:#f0f0f0;display:flex;align-items:center;justify-content:center;color:#666;&#34;&gt;Loading...&lt;/div&gt;
    &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;最近PRレビューをする機会が増えてレビュワーとPR作成者双方の負担を減らす方法を考えていたのでとても参考になった。&lt;/p&gt;
&lt;p&gt;以下メモ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AIの予期せぬ変更はRules / Skillsでもある程度は防げるがあくまで挙動は非決定的なためすり抜けてしまう可能性がある。そのためハード制約（決定的な処理による制約）を設けることが重要。&lt;/li&gt;
&lt;li&gt;ハード制約の例
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;internal&lt;/code&gt; packageで予期せぬ外部参照から保護する&lt;/li&gt;
&lt;li&gt;&lt;code&gt;depguard&lt;/code&gt;による依存性ルールの強制&lt;/li&gt;
&lt;li&gt;Package by Featureで凝集性を向上させることでコンテキストをうまく制御する&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Fuzzing Test, Mutation Testingなどのテスト手法を活用してコード品質を保つ&lt;/li&gt;
&lt;li&gt;開発者体験 = エージェント体験
&lt;ul&gt;
&lt;li&gt;両者は同じもの。&lt;/li&gt;
&lt;li&gt;環境構築、テストとフィードバック、可観測性等開発者体験が悪ければAI Agentもうまく開発を進めることはできなくなる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;go-での並列処理-最初の一歩から次の一歩へ&#34;&gt;Go での並列処理 「最初の一歩」から「次の一歩」へ&lt;/h2&gt;
&lt;p&gt;TakasagoさんによるGoでの並行処理についてのセッション。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container google-slides&#34;&gt;
      &lt;iframe src=&#34;https://docs.google.com/presentation/d/1SpK9Pxsh2QOOXwIirNe3YiN6U5ujAxiottt4ZNPdBkg/embed?start=false&amp;loop=false&amp;delayms=3000&#34; frameborder=&#34;0&#34; width=&#34;960&#34; height=&#34;569&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;並行処理の原理だけでなく、パターンを身につけておくといざ実装するとなったときに役に立ちそうだと思った。（なかなか毎月書くような機会がないのであまり定着してない&amp;hellip;）&lt;/p&gt;
&lt;p&gt;以下メモ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Goは同期で書いておいて高速化したい箇所だけ並列化する、という書き方がやりやすいのが特徴。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;go126のruntimemetricsが便利そうな件&#34;&gt;Go.1.26のruntime/metricsが便利そうな件（？）&lt;/h2&gt;
&lt;p&gt;o_ga09さんによる発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container google-slides&#34;&gt;
      &lt;iframe src=&#34;https://docs.google.com/presentation/d/1mamepeOir5fiEh3ZcGuRM9kkEvQohCcKeZIsKwZ6_L4/embed?start=false&amp;loop=false&amp;delayms=3000&#34; frameborder=&#34;0&#34; width=&#34;960&#34; height=&#34;569&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;goroutineリークをリアルタイムに検出できるの便利そう。&lt;/p&gt;
&lt;h2 id=&#34;モジュラモノリスにおける境界をgoのinternalパッケージで守る&#34;&gt;モジュラモノリスにおける境界をGoのinternalパッケージで守る&lt;/h2&gt;
&lt;p&gt;SODA inc.のmagavelさんによる発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container speakerdeck&#34;&gt;
        &lt;iframe src=&#34;https://speakerdeck.com/player/52cdc21278874c8dafb7a21812d6bd81&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
      &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;メモ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「結合はむしろ、忘れてはならない設計ツールだ。」&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bounded_context&lt;/code&gt;ディレクトリを切っているのが印象的だった&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;お話したこと:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ディレクトリ構成について
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bounded_context&lt;/code&gt;ディレクトリの同階層には&lt;code&gt;monolish&lt;/code&gt;ディレクトリがある
&lt;ul&gt;
&lt;li&gt;これらは現状ワンバイナリになっている&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bounded_context&lt;/code&gt;ディレクトリの中には購入、xxx、yyyなどの境界づけられたコンテキストが並ぶ。&lt;/li&gt;
&lt;li&gt;たとえば購入コンテキストの中には購入モジュール、決済モジュールなどがある。&lt;/li&gt;
&lt;li&gt;購入モジュールからは決済モジュールの公開されたIFを呼び出すようになっている。&lt;/li&gt;
&lt;li&gt;公開したくないパッケージはすべてinternal配下に置くことで予期しない依存を防いでいる。&lt;/li&gt;
&lt;li&gt;他にも&lt;code&gt;depguard&lt;/code&gt;を使って依存関係を制御している。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;go設計思想の深掘り&#34;&gt;Go設計思想の深掘り&lt;/h2&gt;
&lt;p&gt;k_program510さんによる発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container speakerdeck&#34;&gt;
        &lt;iframe src=&#34;https://speakerdeck.com/player/bf88016d5fe349edb4eee19de56f94c2&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
      &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;メモ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;発表者の方がオブジェクト指向言語に慣れていてGoにクラスがないことに驚いてGo誕生の背景を深ぼろうと思った、という自分の疑問に向き合う姿勢がとても素敵だと思った。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;設計思想は「どこで使うべきか」を教えてくれる&lt;/code&gt;いい言葉だ。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;databasesqldriverを理解してカスタムデータベースドライバーを作る&#34;&gt;database/sql/driverを理解してカスタムデータベースドライバーを作る&lt;/h2&gt;
&lt;p&gt;replu5さんによる発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container speakerdeck&#34;&gt;
        &lt;iframe src=&#34;https://speakerdeck.com/player/71c311a482f14af59e5808230f22dae3&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
      &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;メモ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;カスタムデータベースドライバーを作る理由
&lt;ul&gt;
&lt;li&gt;ログをだしたい&lt;/li&gt;
&lt;li&gt;リクエストをDBのwriteインスタンスとreadインスタンスに振り分けたい&lt;/li&gt;
&lt;li&gt;sqlcを使っているが、sqlcが生成したコードに手を加えていくのは避けたい&lt;/li&gt;
&lt;li&gt;本体をforkしてしまうと本体に追従するのが大変なので既存のドライバーをラップしたドライバーを作成することにした&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;お話したこと&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sqlcだと引数に応じてwhere句を一部変更することができないと思うがどうやっているのか。
&lt;ul&gt;
&lt;li&gt;そういうケースでは複数パターンのクエリを（愚直に）repository層に書いている。&lt;/li&gt;
&lt;li&gt;そもそも巨大で複雑なクエリにはsqlcは適していないので使うべきではないかもしれない。
&lt;ul&gt;
&lt;li&gt;（技術の思想や特徴を理解し適切な場所で使うべき、という姿勢は↑のk_program510さんの『Go設計思想の深掘り』とも通じることがあると感じた。）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;nilとは何か-言語仕様と設計者の葛藤から理解する&#34;&gt;nilとは何か 〜言語仕様と設計者の葛藤から理解する〜&lt;/h2&gt;
&lt;p&gt;株式会社サイバーエージェント kurodaさんによる発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container speakerdeck&#34;&gt;
        &lt;iframe src=&#34;https://speakerdeck.com/player/a0086a4f622f413b83f12560bf8fb2a2&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
      &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;以下メモ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Goで定義されているキーワード数を即答している人が数人いてすごかったw（25個らしい）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nil&lt;/code&gt;はキーワードではない。&lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;iota&lt;/code&gt;と同じpredeclared identifier(事前宣言された識別子)である。&lt;/li&gt;
&lt;li&gt;predeclared identifierのなかでデフォルト型を持たないのは&lt;code&gt;nil&lt;/code&gt;だけ。&lt;/li&gt;
&lt;li&gt;（ちょいちょいクイズが挟まっていて参加者を飽きさせない工夫があって発表の仕方が参考になった）&lt;/li&gt;
&lt;li&gt;interfaceが==nilになるのは型情報もデータも両方ゼロのときのみ。
&lt;ul&gt;
&lt;li&gt;なのでtyped nilは==nilにならない。
&lt;ul&gt;
&lt;li&gt;-&amp;gt; &lt;code&gt;var err *MyError = nil&lt;/code&gt;のように初期化した値は==nilにならないのでnilをreturnしたい場合は明示的にnilを返す必要がある。（全然知らなかった）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;nilに関する問題をどう解決するかの議論がなかなか前に進んでいないことを説明してからの&lt;code&gt;errors.AsType&lt;/code&gt;をセマンティクスを変えずにうまく問題を解決した例として説明する流れがめっちゃ綺麗だった。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;who-tests-the-tests-&#34;&gt;Who tests the &lt;code&gt;Tests&lt;/code&gt; ?&lt;/h2&gt;
&lt;p&gt;sivchariさんの発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container google-slides&#34;&gt;
      &lt;iframe src=&#34;https://docs.google.com/presentation/d/1we1bAhUH-_hCEZTYFy2DOyFjWN0fp7VWBkWBha8nwk4/embed?start=false&amp;loop=false&amp;delayms=3000&#34; frameborder=&#34;0&#34; width=&#34;960&#34; height=&#34;569&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
    &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;メモ:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI時代になってCIの重要性が増している。&lt;/li&gt;
&lt;li&gt;カバレッジだけを追っていくと本質的でないテストコードが増えてしまう。&lt;/li&gt;
&lt;li&gt;テストコードのテストとしてMutation Testingという手法を紹介する。&lt;/li&gt;
&lt;li&gt;Mutation Testing
&lt;ul&gt;
&lt;li&gt;プログラムの一部を意図的に書き換え、生成したミュータントに対してテストを実行し、失敗するかどうかを検証する手法。
&lt;ul&gt;
&lt;li&gt;演算子の変更、&lt;code&gt;else&lt;/code&gt;ブロックの削除など&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;失敗することを期待するテスト(&lt;code&gt;KILLED&lt;/code&gt;: テスト失敗 == 期待した挙動、&lt;code&gt;SURVIVED&lt;/code&gt;: テスト成功 == 期待した挙動ではない)&lt;/li&gt;
&lt;li&gt;どれくらい失敗したかを指標にする。&lt;/li&gt;
&lt;li&gt;ただこれは銀の弾丸ではない。実行時間とのトレードオフになる。
&lt;ul&gt;
&lt;li&gt;100% &lt;code&gt;KILLED&lt;/code&gt;を目指すべきではない。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mutation Testingをどう実装するか
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sivchari/gomu&#34; target=&#34;_blank&#34; &gt;sivchari/gomu&lt;/a&gt;というMutation Testingライブラリを作成した。&lt;/li&gt;
&lt;li&gt;overlayを使うと実際のファイルを仮想的に変更して実行できる
&lt;ul&gt;
&lt;li&gt;ソースコードを汚さずに好きなように変更できる&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;感想:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;overlayすごそう&lt;/li&gt;
&lt;li&gt;気になったこと
&lt;ul&gt;
&lt;li&gt;mutation testingの使い所について
&lt;ul&gt;
&lt;li&gt;実際のプロダクションに導入するならある程度テストが整備されたあとにやるのが優先順位としてよい？（Mutation Testingがちゃんと動作することの前提としてある程度のカバレッジが必要そう）&lt;/li&gt;
&lt;li&gt;あとは不慣れな巨大コードと向き合うときにmutation testを実行してみてテスト品質を把握する、というのもいいかもしれない。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;mutation testing以外のテスト品質保証手法について
&lt;ul&gt;
&lt;li&gt;あまりテストの品質を定量的、機械的に保証する方法をカバレッジ以外に考えたことがなかった。&lt;/li&gt;
&lt;li&gt;mutation testing以外ではどのようにテストコードの品質や正当性を保証するのがよさそう？&lt;/li&gt;
&lt;li&gt;たとえばk8sの内部実装などではどのように品質担保しているのか気になった（気になっただけで調べられてはいない）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;goから学ぶgcの仕組みとgreen-tea-gcによる次世代最適化&#34;&gt;Goから学ぶGCの仕組みとGreen Tea GCによる次世代最適化&lt;/h2&gt;
&lt;p&gt;go_poron10さんによる発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container speakerdeck&#34;&gt;
        &lt;iframe src=&#34;https://speakerdeck.com/player/17dc2bf5b4ed4a1d8c289ad77f26cd8c&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
      &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;とても内容が高度で途中でついていけなくなってしまったのでいつかリベンジしたい。&lt;/p&gt;
&lt;h2 id=&#34;実装公開goで実現する堅牢なアーキテクチャdddgrpc-connectそしてai協調開発の実践&#34;&gt;【実装公開】Goで実現する堅牢なアーキテクチャ：DDD、gRPC-connect、そしてAI協調開発の実践&lt;/h2&gt;
&lt;p&gt;株式会社テレシーのDaisuke Sasakiさんによる発表。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;embed-container speakerdeck&#34;&gt;
        &lt;iframe src=&#34;https://speakerdeck.com/player/0592dd9c358e4ea9b74adf758ddb546a&#34; allowfullscreen=&#34;true&#34; mozallowfullscreen=&#34;true&#34; webkitallowfullscreen=&#34;true&#34;&gt;&lt;/iframe&gt;
      &lt;/div&gt;&lt;/p&gt;
&lt;p&gt;お話したこと:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;application層のQuery Serviceからdomain packageへの依存はOKにしている？それとも独自のreturn typeをQuery serviceで定義している？
&lt;ul&gt;
&lt;li&gt;依存OKにしている。&lt;/li&gt;
&lt;li&gt;domain層に以下の2種類があり、それぞれ別パッケージに定義している。
&lt;ul&gt;
&lt;li&gt;commandとqueryの両方から参照される型(tier1)&lt;/li&gt;
&lt;li&gt;queryからのみ参照される型(tier2)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;スポンサーブースで話したこと一部抜粋&#34;&gt;スポンサーブースで話したこと（一部抜粋）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ANDPAD
&lt;ul&gt;
&lt;li&gt;意外にもGo関連の勉強会でスポンサーブースを出すのは初とのこと。
&lt;ul&gt;
&lt;li&gt;スポンサーブースが抽選なので出展の機会を得るのは簡単ではないらしい。&lt;/li&gt;
&lt;li&gt;個人的にはGoに力を入れている会社のイメージを2年くらい前から持っていたので意外だった。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;SODA
&lt;ul&gt;
&lt;li&gt;CodeRabbitでレビュー負荷を下げている&lt;/li&gt;
&lt;li&gt;PRレビューはチーム全員で分担して特定の誰かに負担が偏らないようにしている&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;感想&#34;&gt;感想&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ソロ参加だったがセッションの合間や懇親会でたくさんの人と交流できてとても楽しかった。
&lt;ul&gt;
&lt;li&gt;社外のエンジニアと話せるとかなり刺激&amp;amp;学びになるので今後も機会を見つけていろんな勉強会に参加してみようと思った。&lt;/li&gt;
&lt;li&gt;勉強会に参加している人は自分の時間を使って勉強会に参加するくらいなのでモチベが高い（あるいは技術が好きな）人が多いというのはあるかもしれない。（考えてみれば当たり前だが実際に行ってみてそのことを実感できた）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;今年はCSの勉強&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;と並行してGoのインプット &amp;amp; アウトプットを頑張っていこうと思っているのでモチベがいい感じに上がった。
&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=&#34;振り返り&#34;&gt;振り返り&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;セッションの合間は発表者の方に質問するためにウロウロしている時間が長かったのもあり、全スポンサーブースを回れなかった。もうちょっといい感じに時間を使えるとよさそう。（スポンサーブースで各社の方とお話するのは楽しいので全部回りたい気持ち）&lt;/li&gt;
&lt;li&gt;懇親会の途中から他の人に自分から話しかけたりできたけど次回は最初からできるともっとよさそう。&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;おまけ&#34;&gt;おまけ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;土日に仙台でKing Gnuのライブがあった影響か、土曜は仙台駅付近のホテルがめっちゃ高かったので福島まで移動して宿泊してgot aことなきした。（ありがとうアパホテル）&lt;/li&gt;
&lt;li&gt;福島で食べたお寿司が美味しかった。観光までする（体力的）余裕がなかったのが残念。
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;sushi.webp&#34; alt=&#34;&#34; loading=&#34;lazy&#34; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;なんか新幹線が長かった。
&lt;ul&gt;
&lt;li&gt;&lt;img src=&#34;long-shinkansen.webp&#34; alt=&#34;&#34; loading=&#34;lazy&#34; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;大AI時代になりPRレビュー負担が肥大化しているのでCIで機械的にコード品質を担保するためにLinterを増やそうと思っているため。&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://pkg.go.dev/cmd/compile#hdr-Line_Directives&#34; target=&#34;_blank&#34; &gt;https://pkg.go.dev/cmd/compile#hdr-Line_Directives&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;今は（今更ながら）『ネットワークはなぜつながるのか』を読んでいる。&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;話しかけるときは普通に「お疲れ様です〜」とかでいいんだなという学びを得た。&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </item>
    
    <item>
      <title>『Goならわかるシステムプログラミング 第2版』を読んだ</title>
      <link>https://blog.kyu08.com/pr-344/posts/go-system-programming/</link>
      <pubDate>Sun, 03 Nov 2024 12:42:30 +0000</pubDate>
      
      <guid>https://blog.kyu08.com/pr-344/posts/go-system-programming/</guid>
      <description>『Goならわかるシステムプログラミング第2版』をサンプルコードを手元で実行しつつ一通り読んだ。(期間としては2024/6/8 ~ 2024/11</description>
      <content>&lt;p&gt;&lt;img src=&#34;./book.webp&#34; alt=&#34;book&#34; loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;『Goならわかるシステムプログラミング第2版』をサンプルコードを手元で実行しつつ一通り読んだ。(期間としては2024/6/8 ~ 2024/11/4でコミットした日数としてはおおよそ24日ほどだった。)&lt;/p&gt;
&lt;p&gt;筆者は情報系の学部を出ておらず、CSなどの基礎知識があまりないので大変勉強になった。また、サンプルコードが豊富なので実際に自分のマシン上で動かしながら学ぶことができ解像度を上げながら理解を深めることができた。&lt;/p&gt;
&lt;p&gt;低レイヤ、コンピューターサイエンスの学習に興味がある方にはとてもおすすめなのでぜひ買って読んでみてください。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;blogcard&#34; data-url=&#34;https://www.lambdanote.com/products/go-2&#34; data-auto-fetch=&#34;false&#34;&gt;
  &lt;a href=&#34;https://www.lambdanote.com/products/go-2&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;blogcard-link&#34;&gt;&lt;div class=&#34;blogcard-thumbnail&#34;&gt;
      &lt;img src=&#34;http://www.lambdanote.com/cdn/shop/products/web-asset-1_1024x1024.jpg?v=1647933491&#34; alt=&#34;Goならわかるシステムプログラミング 第2版&#34; loading=&#34;lazy&#34;&gt;
    &lt;/div&gt;&lt;div class=&#34;blogcard-content&#34;&gt;
      &lt;div class=&#34;blogcard-title&#34;&gt;Goならわかるシステムプログラミング 第2版&lt;/div&gt;&lt;div class=&#34;blogcard-description&#34;&gt;Go言語による新時代のコンピュータシステム入門 渋川よしき 著 424ページ A5判 ISBN：978-4-908686-12-2 2022年3月23日 第2版第1刷 発行 いつも開発に使っている言語やライブラリの裏側は、いったいどうなっ&lt;/div&gt;&lt;div class=&#34;blogcard-url&#34;&gt;https://www.lambdanote.com/products/go-2&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;手元で実行したコードは以下のリポジトリにまとめた。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;blogcard&#34; data-url=&#34;https://github.com/kyu08/go-system-programming&#34; data-auto-fetch=&#34;false&#34;&gt;
  &lt;a href=&#34;https://github.com/kyu08/go-system-programming&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;blogcard-link&#34;&gt;&lt;div class=&#34;blogcard-thumbnail&#34;&gt;
      &lt;img src=&#34;https://opengraph.githubassets.com/355ab1c4f0743bcf245b84b5a33ead3e075d2b755c79cbdc43e5e554867af726/kyu08/go-system-programming&#34; alt=&#34;GitHub - kyu08/go-system-programming: 『Goならわかるシステムプログラミング』の写経リポジトリ&#34; loading=&#34;lazy&#34;&gt;
    &lt;/div&gt;&lt;div class=&#34;blogcard-content&#34;&gt;
      &lt;div class=&#34;blogcard-title&#34;&gt;GitHub - kyu08/go-system-programming: 『Goならわかるシステムプログラミング』の写経リポジトリ&lt;/div&gt;&lt;div class=&#34;blogcard-description&#34;&gt;『Goならわかるシステムプログラミング』の写経リポジトリ. Contribute to kyu08/go-system-programming development by creating an account on GitHub.&lt;/div&gt;&lt;div class=&#34;blogcard-url&#34;&gt;https://github.com/kyu08/go-system-programming&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;以下読書メモ。&lt;/p&gt;
&lt;h2 id=&#34;第1章-go言語で覗くシステムプログラミングの世界&#34;&gt;第1章 Go言語で覗くシステムプログラミングの世界&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;デバッガを使って&lt;code&gt;fmt.Println&lt;/code&gt;の動作をシステムコールまで追った。&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;当然だがデバッガを使うと変数の中身に何が入ってるかがわかって便利。&lt;/li&gt;
&lt;li&gt;デバッガを使ってみて別パッケージのprivate変数の中身を見ることができるのはプリントデバッグにはないデバッガの利点だと気づいた。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;第2章-低レベルアクセスへの入口1iowriter&#34;&gt;第2章 低レベルアクセスへの入口1：io.Writer&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;io.Writer&lt;/code&gt;はOSが持つファイルのシステムコールの相似形&lt;/li&gt;
&lt;li&gt;OSでは、システムコールを&lt;strong&gt;ファイルディスクリプタ&lt;/strong&gt;と呼ばれるものに対して呼ぶ。&lt;/li&gt;
&lt;li&gt;ファイルディスクリプタ(file descriptor)は一種の識別子（数値）で、この数値を指定してシステムコールを呼び出すと、数値に対応するモノへとアクセスできる。&lt;/li&gt;
&lt;li&gt;ファイルディスクリプタはOSがカーネルのレイヤーで用意している抽象化の仕組み。&lt;/li&gt;
&lt;li&gt;OSのカーネル内部のデータベースに、プロセスごとに実体が用意される。&lt;/li&gt;
&lt;li&gt;OSはプロセスが起動されるとまず3つの擬似ファイルを作成し、それぞれにファイルディスクリプタを割り当てる。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt;が標準入力、&lt;code&gt;1&lt;/code&gt;が標準出力、&lt;code&gt;2&lt;/code&gt;が標準エラー出力。&lt;/li&gt;
&lt;li&gt;以降はそのプロセスでファイルをオープンしたりソケットをオープンしたりするたびに1ずつ大きな数値が割り当てられていく。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;複数のファイル&lt;code&gt;f1&lt;/code&gt;, &lt;code&gt;f2&lt;/code&gt;を&lt;code&gt;os.Create()&lt;/code&gt;する処理をデバッガーで追ってみたところ、それぞれファイルディスクリプタの値が&lt;code&gt;3&lt;/code&gt;, &lt;code&gt;4&lt;/code&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;となっておりファイルディスクリプタの値が&lt;code&gt;3&lt;/code&gt;からインクリメントされる様子を確認できた。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;delve-neovim.webp&#34; alt=&#34;delve-neovim.webp&#34; loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2 id=&#34;第3章-低レベルアクセスへの入口1ioreader&#34;&gt;第3章 低レベルアクセスへの入口1：io.Reader&lt;/h2&gt;
&lt;h3 id=&#34;エンディアン変換&#34;&gt;エンディアン変換&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;リトルエンディアンでは、10000という数値(&lt;code&gt;0x2710&lt;/code&gt;)をメモリに格納するとき下位バイトから順に格納する。&lt;/li&gt;
&lt;li&gt;ビッグエンディアンでは、上位バイトから順に格納する。&lt;/li&gt;
&lt;li&gt;現在主流のCPUではリトルエンディアンが採用されている。&lt;/li&gt;
&lt;li&gt;ネットワーク上で転送されるデータの多くはビッグエンディアンが用いられている。&lt;/li&gt;
&lt;li&gt;そのため多くの環境ではネットワークで受け取ったデータをリトルエンディアンに変換する必要がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ioパッケージのいくつかの関数--構造体--インターフェースの使い方&#34;&gt;&lt;code&gt;io&lt;/code&gt;パッケージのいくつかの関数 / 構造体 / インターフェースの使い方&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;io.Pipe&lt;/code&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;io.LimitReader&lt;/code&gt;: 先頭の&lt;code&gt;n&lt;/code&gt;バイトだけ読み込む&lt;/li&gt;
&lt;li&gt;&lt;code&gt;io.MultiReader&lt;/code&gt;: 複数の&lt;code&gt;io.Reader&lt;/code&gt;を1つの&lt;code&gt;io.Reader&lt;/code&gt;にまとめる&lt;/li&gt;
&lt;li&gt;&lt;code&gt;io.SectionReader&lt;/code&gt;: &lt;code&gt;offset&lt;/code&gt;と&lt;code&gt;n&lt;/code&gt;を指定して一部のデータだけ読み込む&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;第4章-チャネル&#34;&gt;第4章 チャネル&lt;/h2&gt;
&lt;p&gt;普段goroutineを全然使わないので忘れていることが多かった。以下学んだことメモ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;バッファなしチャネルでは、受け取り側が受信しないと、送信側もブロックされる。&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;for task := range tasks // tasksは任意のch&lt;/code&gt;のように書くと、チャネルに値が入るたびにループが回り、チャネルがクローズされるまでループが回る。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;第5章-システムコール&#34;&gt;第5章 システムコール&lt;/h2&gt;
&lt;p&gt;システムコールとは特権モードでOSの機能を呼ぶこと。&lt;/p&gt;
&lt;h3 id=&#34;cpuの動作モード&#34;&gt;CPUの動作モード&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OSの仕事は以下の2つ
&lt;ul&gt;
&lt;li&gt;各種資源（メモリ、CPU時間、ストレージなど）の管理&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;OSが動作する特権モード&lt;/li&gt;
&lt;li&gt;一般的なアプリケーションが動作するユーザーモード&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;システムコールが必要な理由&#34;&gt;システムコールが必要な理由&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;通常のアプリケーションでメモリ割り当てやファイル入出力、インターネット通信などの機能を使うために必要なのがシステムコール&lt;/li&gt;
&lt;li&gt;システムコールがなくてもCPUの命令そのものはほとんど使うことができる&lt;/li&gt;
&lt;li&gt;しかし、ユーザーモードでは計算した結果を画面に出力したり、ファイルに保存したり外部のWebサービスに送信したりできない。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;dtruss&lt;/code&gt;コマンドを使ってシステムコールの呼び出しを確認しようとしたがmacOSのセキュリティの設定上何も表示されなかったのでDocker上でLinuxを起動して確認してみることにした。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -it --name stracetest golang:1.22.4-alpine3.19
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;apk add strace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go mod init kyu08/stracetest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 任意のgoファイルを作成&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go build ./...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;strace -o strace.log ./実行ファイル
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;less strace.log
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;今回は&lt;code&gt;f, _ := os.Create(&amp;quot;test_file.txt&amp;quot;)&lt;/code&gt;と&lt;code&gt;defer f.Close()&lt;/code&gt;を実行するだけのgoプログラムを実行したときのシステムコールのログを確認した。以下はその一部。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rt_sigaction&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SIGRT_32, &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;sa_handler&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;0x70d90, sa_mask&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;~&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;, sa_flags&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;SA_ONSTACK|SA_RESTART|SA_SIGINFO&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;, NULL, 8&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rt_sigprocmask&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SIG_SETMASK, ~&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;, 8&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clone&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;child_stack&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;0x400001c000, flags&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;890&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rt_sigprocmask&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SIG_SETMASK, &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;, NULL, 8&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- SIGURG &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;si_signo&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;SIGURG, si_code&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;SI_TKILL, si_pid&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;889, si_uid&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; ---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rt_sigreturn&lt;span style=&#34;color:#f92672&#34;&gt;({&lt;/span&gt;mask&lt;span style=&#34;color:#f92672&#34;&gt;=[]})&lt;/span&gt;                 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1139696&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rt_sigprocmask&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SIG_SETMASK, ~&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;, 8&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clone&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;child_stack&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;0x4000062000, flags&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;891&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rt_sigprocmask&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;SIG_SETMASK, &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt;, NULL, 8&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;futex&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x4000080148, FUTEX_WAKE_PRIVATE, 1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;futex&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x4000048948, FUTEX_WAKE_PRIVATE, 1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;prlimit64&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0, RLIMIT_NOFILE, NULL, &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;rlim_cur&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;1024*1024, rlim_max&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;1024*1024&lt;span style=&#34;color:#f92672&#34;&gt;})&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fcntl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0, F_GETFL&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 0x20002 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;flags O_RDWR|O_LARGEFILE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;futex&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x4000049148, FUTEX_WAKE_PRIVATE, 1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fcntl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;1, F_GETFL&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 0x20002 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;flags O_RDWR|O_LARGEFILE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fcntl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;2, F_GETFL&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 0x20002 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;flags O_RDWR|O_LARGEFILE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;openat&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;AT_FDCWD, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test_file.txt&amp;#34;&lt;/span&gt;, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;futex&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x115ea0, FUTEX_WAKE_PRIVATE, 1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;futex&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0x115db8, FUTEX_WAKE_PRIVATE, 1&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fcntl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;3, F_GETFL&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 0x20002 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;flags O_RDWR|O_LARGEFILE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fcntl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;3, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;epoll_create1&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;EPOLL_CLOEXEC&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pipe2&lt;span style=&#34;color:#f92672&#34;&gt;([&lt;/span&gt;5, 6&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;, O_NONBLOCK|O_CLOEXEC&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;     &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;epoll_ctl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;4, EPOLL_CTL_ADD, 5, &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;events&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;EPOLLIN, data&lt;span style=&#34;color:#f92672&#34;&gt;={&lt;/span&gt;u32&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;1549912, u64&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;1549912&lt;span style=&#34;color:#f92672&#34;&gt;}})&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;epoll_ctl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;4, EPOLL_CTL_ADD, 3, &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;events&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, data&lt;span style=&#34;color:#f92672&#34;&gt;={&lt;/span&gt;u32&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;3997171713, u64&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;18446585726557487105&lt;span style=&#34;color:#f92672&#34;&gt;}})&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; -1 EPERM &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;Operation not permitted&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fcntl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;3, F_GETFL&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                       &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; 0x20802 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;flags O_RDWR|O_NONBLOCK|O_LARGEFILE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fcntl&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;3, F_SETFL, O_RDWR|O_LARGEFILE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;   &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;close&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;3&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                                &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exit_group&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;                           &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ?
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++ exited with &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; +++
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openat(AT_FDCWD, &amp;quot;test_file.txt&amp;quot;, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3&lt;/code&gt;の部分でファイルが作成され、ファイルディスクリプタに&lt;code&gt;3&lt;/code&gt;が割り当ている&lt;/li&gt;
&lt;li&gt;&lt;code&gt;close(3)                                = 0&lt;/code&gt;の部分で&lt;code&gt;defer f.Close()&lt;/code&gt;に相当する処理が行われている&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ということを確認できた。&lt;/p&gt;
&lt;h2 id=&#34;第6章-tcpソケットとhttpの実装&#34;&gt;第6章 TCPソケットとHTTPの実装&lt;/h2&gt;
&lt;h3 id=&#34;ソケットとは&#34;&gt;ソケットとは&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ほとんどのOSではアプリケーション層からトランスポート層のプロトコルを利用するときのAPIとして&lt;strong&gt;ソケット&lt;/strong&gt;という仕組みを利用している&lt;/li&gt;
&lt;li&gt;HTTP/1.0と1.1はこのソケットのバイトストリーム上に作られたテキストを使ったプロトコル&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ソケットの種類本書で説明するもののみ&#34;&gt;ソケットの種類（本書で説明するもののみ）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;TCP：一番使われている。安定性が高い。&lt;/li&gt;
&lt;li&gt;UDP：通信開始が早い。相手に一方的に送りつける。&lt;/li&gt;
&lt;li&gt;Unixドメインソケット：ローカル通信でしか使えないが最速。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;ソケット通信の基本構造&#34;&gt;ソケット通信の基本構造&lt;/h3&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;
&lt;li&gt;GoではTCP通信が確立されると、送信側、受信側の両方に相手との通信する&lt;code&gt;net.Conn&lt;/code&gt;インタフェースを満たすオブジェクトが渡ってくる&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;goに組み込まれているtcpの機能netconnだけを使ってhttpによる通信を実現する&#34;&gt;Goに組み込まれているTCPの機能（&lt;code&gt;net.Conn&lt;/code&gt;）だけを使ってHTTPによる通信を実現する&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;net.Conn&lt;/code&gt;だけを使ってTCPソケットの初期化や通信の確立などの普段なら&lt;code&gt;net/http&lt;/code&gt;がやってくれている部分を実装した。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http.ListenAndServe()&lt;/code&gt;のコードを読んでみたら、&lt;a href=&#34;https://github.com/golang/go/blob/c83b1a7013784098c2061ae7be832b2ab7241424/src/net/http/server.go#L3258&#34; target=&#34;_blank&#34; &gt;golang/go/src/net/http/server.go#L3258&lt;/a&gt;で本書のハンズオンと同じようにTCPソケットの初期化を行っていることを確認できた。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;素朴な実装の速度改善&#34;&gt;素朴な実装の速度改善&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;①Keep-Aliveへの対応
&lt;ul&gt;
&lt;li&gt;HTTP/1.1から入った規格&lt;/li&gt;
&lt;li&gt;HTTP/1.0ではセットの通信が終わるたびにTCPコネクションが切れる仕様になっていたが、Keep-Aliveを使うことで、しばらくの間はTCP接続のコネクションを維持して使い回すことができる。&lt;/li&gt;
&lt;li&gt;TCP接続の通信には一定のオーバーヘッドがあるが、Keep-Aliveを使うことでそのオーバーヘッドを削減できる。&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;li&gt;チャンク形式ではヘッダーに送信データのサイズを書かないかわりに&lt;code&gt;Transfer-Encoding: chunked&lt;/code&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=&#34;第7章-udpソケットを使ったマルチキャスト通信&#34;&gt;第7章 UDPソケットを使ったマルチキャスト通信&lt;/h2&gt;
&lt;h3 id=&#34;udpとtcpの用途の違い&#34;&gt;UDPとTCPの用途の違い&lt;/h3&gt;
&lt;p&gt;UDPはTCPと同じトランスポート層のプロトコルで以下のような特徴がある。&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;複数のコンピュータに同時にメッセージを送ることが可能な「マルチキャスト」と「ブロードキャスト」をサポートしている。（TCPにはない機能）&lt;/li&gt;
&lt;li&gt;UDPの利用例としてはDNSやNTP, WebRTCなどがある。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;udpのマルチキャストの実装例&#34;&gt;UDPのマルチキャストの実装例&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;マルチキャストはリクエスト側の負担を増やすことなく多くのクライアントに同時にデータを送信できる仕組み。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;udpとtcpの機能面の違い&#34;&gt;UDPとTCPの機能面の違い&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;TCPには再送処理とフロー処理がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;再送処理&#34;&gt;再送処理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;TCPでは送信するメッセージに&lt;strong&gt;シーケンス番号&lt;/strong&gt;が入っているので、受信側ではこの数値をみることでパケットの順序を管理できる。&lt;/li&gt;
&lt;li&gt;受信側はメッセージを受け取ると、受信したデータの&lt;strong&gt;シーケンス番号&lt;/strong&gt;と&lt;strong&gt;ペイロードサイズの合計&lt;/strong&gt;を確認応答番号として返信する。&lt;/li&gt;
&lt;li&gt;送信側はこの応答確認番号が受け取れなかった場合に再送処理を行う。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;フロー処理&#34;&gt;フロー処理&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;受信側がリソースを用意できていない状態で送信リクエストが集中して通信内容が失われるのを防ぐための仕組みを&lt;strong&gt;ウィンドウ制御&lt;/strong&gt;という。
&lt;ul&gt;
&lt;li&gt;具体的には、受信用のバッファ（ウィンドウ）をあらかじめ決めておき送信側ではそのサイズまでは受信側からの受信確認を待たずにデータを送信できる。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;受信側のデータの読み込みが間に合わない場合には、受信できるウィンドウサイズを受信側から送信側に伝えて通信量を制御できる。これを&lt;strong&gt;フロー制御&lt;/strong&gt;という。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;フレームサイズ&#34;&gt;フレームサイズ&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;UDPレイヤーで取り扱えるデータは約64キロバイトまで。&lt;/li&gt;
&lt;li&gt;UDPではデータの分割などはアプリケーションで面倒を見る必要がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;輻輳制御とフェアネス&#34;&gt;輻輳制御とフェアネス&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;輻輳制御&lt;/strong&gt;とは、ネットワークの輻輳（渋滞）を避けるように流量を調整し、そのネットワークの最大効率で通信できるようにするとともに複数の通信をお互いに&lt;strong&gt;フェアに行う&lt;/strong&gt;ための仕組み。&lt;/li&gt;
&lt;li&gt;TCPには輻輳制御が備わっており、そのアルゴリズムにはさまざまな種類がある。&lt;/li&gt;
&lt;li&gt;UDPにはTCPのような輻輳制御の仕組みはなく、流量の制御はUDPを利用する各プログラムに委ねられている。そのため、UDPとTCPを利用するアプリケーションがそれぞれあって、UDPを利用するアプリケーションでフェアネスが考慮されていない場合には、&lt;strong&gt;両方の通信が重なった時に遠慮する機能が組み込まれたTCPの通信速度だけが極端に落ち込む&lt;/strong&gt;こともある。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;第8章-高速なunixドメインソケット&#34;&gt;第8章 高速なUnixドメインソケット&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;UnixドメインソケットはPOSIX系OSで提供されている機能で、コンピュータ内部でしか使えない代わりに高速な通信が可能。&lt;/li&gt;
&lt;li&gt;Unixドメインソケットには、TCP型（ストリーム型）とUDP型（データグラム型）の両方の使い方ができる。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;unixドメインソケットの基本&#34;&gt;Unixドメインソケットの基本&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;TCPとUDPによるソケット通信が外部のネットワークにつながるインターフェースに接続するのに対し、Unixドメインソケットはカーネル内部で完結する高速なネットワークインターフェースを作成する。&lt;/li&gt;
&lt;li&gt;Unixドメインソケットを使うことで、ウェブサーバーとNGINXなどのリバースプロキシとの間、あるいはウェブサーバーとデーターベースとの間の接続を高速にできる場合がある。&lt;/li&gt;
&lt;li&gt;Unixドメインソケットを開くには、ファイルシステムのパスを指定する。サーバープロセスを起動するとファイルシステム上の指定したパスにソケットファイルが作成される。&lt;/li&gt;
&lt;li&gt;Unixドメインソケットで作成されるのはソケットファイルと呼ばれる特殊なファイルであり、通常のファイルのような実体を持たない。あくまでもプロセス間の高速な通信としてファイルというインターフェースを利用するだけ。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下はソケットファイルが作成されている様子。ソケットファイルは先頭が&amp;quot;s&amp;quot;で始まる。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;socket-file.webp&#34; alt=&#34;socket-file.webp&#34; loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3 id=&#34;unixドメインソケットとtcpのベンチマーク&#34;&gt;UnixドメインソケットとTCPのベンチマーク&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Unixドメインソケットを使った実装とTCPを経由した実装のベンチマークの比較をすると筆者の環境だとUnixドメインソケットの方が10倍ほど高速だった。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ go test -bench . -benchmem
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;goos: darwin
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;goarch: arm64
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pkg: github.com/kyu08/go-system-programming/bench
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkTCPServer-8                &lt;span style=&#34;color:#ae81ff&#34;&gt;4165&lt;/span&gt;            &lt;span style=&#34;color:#ae81ff&#34;&gt;327038&lt;/span&gt; ns/op           &lt;span style=&#34;color:#ae81ff&#34;&gt;52175&lt;/span&gt; B/op        &lt;span style=&#34;color:#ae81ff&#34;&gt;110&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkUDSStreamServer-8         &lt;span style=&#34;color:#ae81ff&#34;&gt;42742&lt;/span&gt;             &lt;span style=&#34;color:#ae81ff&#34;&gt;27837&lt;/span&gt; ns/op           &lt;span style=&#34;color:#ae81ff&#34;&gt;16762&lt;/span&gt; B/op         &lt;span style=&#34;color:#ae81ff&#34;&gt;59&lt;/span&gt; allocs/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PASS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ok      github.com/kyu08/go-system-programming/bench    4.788s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;第9章-ファイルシステムの基礎とgo言語の標準パッケージ&#34;&gt;第9章 ファイルシステムの基礎とGo言語の標準パッケージ&lt;/h2&gt;
&lt;p&gt;この章では&lt;code&gt;os&lt;/code&gt;パッケージと&lt;code&gt;path/filepath&lt;/code&gt;パッケージの主要な関数の使い方が紹介されていた。&lt;/p&gt;
&lt;h3 id=&#34;ファイルディレクトリを扱うgo言語の関数たち&#34;&gt;ファイル/ディレクトリを扱うGo言語の関数たち&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;2つのファイルの同一性の判定: &lt;code&gt;os.Samefile()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ファイルのパーミッション、オーナー、タイムスタンプの変更: &lt;code&gt;os.Chmod()&lt;/code&gt;, &lt;code&gt;os.Chown&lt;/code&gt;, &lt;code&gt;os.Chtimes()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ハードリンク、シンボリックリンクの作成: &lt;code&gt;os.Link&lt;/code&gt;, &lt;code&gt;os.Symlink()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ファイル一覧の取得: &lt;code&gt;dir, _ := os.Open(path)&lt;/code&gt; -&amp;gt; &lt;code&gt;dir.Readdir()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;os内部におけるファイル操作の高速化&#34;&gt;OS内部におけるファイル操作の高速化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CPUにとってディスクの読み書きはとても遅い処理であり、なるべく最後までやらないようにしたい。LinuxではVFSの内部に設けられているバッファを利用することでディスクに対する操作をなるべく回避している。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;pathfilepathパッケージの関数たち&#34;&gt;&lt;code&gt;path/filepath&lt;/code&gt;パッケージの関数たち&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;パスの最後の要素を返す: &lt;code&gt;filepath.Base()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;パスのディレクトリ部分を返す: &lt;code&gt;filepath.Dir()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;パスをディレクトリとパス名に分割する: &lt;code&gt;filepath.Split()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ファイルの拡張子を返す: &lt;code&gt;filepath.Ext()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/some/../path&lt;/code&gt;や&lt;code&gt;another//path&lt;/code&gt;のような形式のパスを整える: &lt;code&gt;filepath.Clean()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;パターンにマッチするファイルの判定: &lt;code&gt;filepath.Match()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ディレクトリのトラバース: &lt;code&gt;filepath.Walk()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;想像よりも標準パッケージでいろんなことができるのでこの辺りの操作をしたくなったら自作関数を書く前に標準パッケージを探してみるのが良さそうだと思った。&lt;/p&gt;
&lt;h2 id=&#34;第10章-ファイルシステムの最深部を扱うgo言語の関数&#34;&gt;第10章 ファイルシステムの最深部を扱うGo言語の関数&lt;/h2&gt;
&lt;h3 id=&#34;ファイルの変更監視syscallinotify&#34;&gt;ファイルの変更監視（&lt;code&gt;syscall.Inotify&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;プログラムでファイルを監視する方法には次の2種類がある。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;監視したいファイルをOS側に通知しておいて、変更があったら教えてもらう（パッシブな）方式&lt;/li&gt;
&lt;li&gt;タイマーなどで定期的にフォルダを走査し、&lt;code&gt;os.Stat()&lt;/code&gt;などを使って変更を探しに行く（アクティブな）方式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;アクティブな方式の方がコード量は少ないが監視対象が増えるとCPU負荷やIO負荷が増える。&lt;/p&gt;
&lt;p&gt;パッシブな方式はファイルの変更検知が各OSでシステムコールやAPUIとして提供されている一方で環境ごとのコード差は大きくなる。&lt;/p&gt;
&lt;p&gt;ここでは &lt;a href=&#34;https://github.com/fsnotify/fsnotify&#34; target=&#34;_blank&#34; &gt;fsnotify/fsnotify.v1&lt;/a&gt;を用いてファイルの変更検知プログラムを作成した。&lt;/p&gt;
&lt;p&gt;fsnotify.v1では、Linuxの場合はinotify系APIが、BSD系OSの場合はkqueueが使われている。&lt;/p&gt;
&lt;h3 id=&#34;ファイルのメモリへのマッピングsyscallmmap&#34;&gt;ファイルのメモリへのマッピング（&lt;code&gt;syscall.Mmap()&lt;/code&gt;）&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;syscall.Mmap()&lt;/code&gt;を使うことでファイルの中身をそのままメモリ上に展開したり、メモリ上で書き換えた内容をそのままファイルに書き込むことができる。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/edsrzf/mmap-go&#34; target=&#34;_blank&#34; &gt;edsrzf/mmap-go&lt;/a&gt;では&lt;code&gt;mmap.Map()&lt;/code&gt;を使うことでファイルをメモリに展開できる。&lt;code&gt;mmap.Map()&lt;/code&gt;は次のようなシグネチャを持つ。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Map&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;File&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;prot&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;flags&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) (&lt;span style=&#34;color:#a6e22e&#34;&gt;MMap&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;2つ目の引数に次のような値を指定することでメモリ領域に対して許可する操作を設定できる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mmap.RDONLY&lt;/code&gt;: 読み込み専用&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mmap.RDWR&lt;/code&gt;: 読み書き可能&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mmap.EXEC&lt;/code&gt;: 実行可能にする&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mmap.COPY&lt;/code&gt;: コピーオンライト&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;コピーオンライトが指定されると、複数のプロセスが同じファイルをマッピングしているときに、カーネル上は1つ分のみメモリ領域が使用され、それ以上のメモリを消費しない。&lt;/p&gt;
&lt;p&gt;しかし、その領域内でメモリ書き換えが発生すると、その領域がまるごとコピーされる。このようにすることでメモリ消費量をうまく節約できる。&lt;/p&gt;
&lt;h3 id=&#34;同期非同期--ブロッキングノンブロッキング&#34;&gt;同期・非同期 / ブロッキング・ノンブロッキング&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;同期処理: OSにI/Oタスクを投げて、入出力の準備ができたらアプリケーションに処理が返ってくる&lt;/li&gt;
&lt;li&gt;非同期処理: OSにI/Oタスクを投げて、入出力の準備ができたら通知をもらう&lt;/li&gt;
&lt;li&gt;ブロッキング処理: お願いしたI/Oタスクの結果の準備ができるまで待つ（自分は停止）&lt;/li&gt;
&lt;li&gt;ノンブロッキング処理: お願いしたI/Oタスクの結果の準備ができるのを待たない（自分は停止しない）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;select属のシステムコールによるio多重化&#34;&gt;select属のシステムコールによるI/O多重化&lt;/h3&gt;
&lt;p&gt;非同期・ブロッキングは1スレッドでたくさんの入出力を効率よく扱うための手法でありI/O多重化とも呼ばれる。それを効率よく実現するAPIのことを本書では&lt;strong&gt;select属&lt;/strong&gt;と総称する。&lt;/p&gt;
&lt;p&gt;並行処理を使うことで小さい規模のI/Oの効率化は十分に行えるが、select属はC10K問題と呼ばれる、万の単位の入出力を効率よく扱うための手法として有効。&lt;/p&gt;
&lt;h3 id=&#34;第11章-コマンドシェル101&#34;&gt;第11章 コマンドシェル101&lt;/h3&gt;
&lt;p&gt;シェルとは、ユーザーがコンピューターを操作するために使う接点となるシステムにおいてコンピューターシステムの殻（shell）となるプログラムのこと。&lt;/p&gt;
&lt;h4 id=&#34;シェルがないシステム&#34;&gt;シェルがないシステム&lt;/h4&gt;
&lt;p&gt;Distrolessと呼ばれるコンテナイメージはシェルがないため、セキュリティホールをついてシステムに侵入されることがない。&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;（当然攻撃の脅威がゼロになるわけではない）&lt;/p&gt;
&lt;h4 id=&#34;シェルがコマンドを起動するまで&#34;&gt;シェルがコマンドを起動するまで&lt;/h4&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;li&gt;プロセスの起動&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;「11.5.3コマンドと引数の前処理」で紹介されていたが、&lt;code&gt;$(which nvim)&lt;/code&gt;と同様に&lt;code&gt;`which nvim`&lt;/code&gt;でもコマンドの実行結果を変数に代入できるのは知らなかった。&lt;/p&gt;
&lt;h2 id=&#34;第12章-プロセスの役割とgo言語による操作&#34;&gt;第12章 プロセスの役割とGo言語による操作&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OSが実行ファイルを読み込んで実行するには、そのためのリソース（CPU、メモリ）を用意する必要がある。そのようなリソースをまとめたプログラムの実行単位のことを&lt;strong&gt;プロセス&lt;/strong&gt;と呼ぶ。プロセスはOSが実行ファイルを読み込んで実行するときに新しく作られる。&lt;/li&gt;
&lt;li&gt;プロセスにはプロセスごとにユニークな識別子がある。（&lt;strong&gt;プロセスID&lt;/strong&gt;）。Go言語では&lt;code&gt;os.Getpid()&lt;/code&gt;で取得できる。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;プロセスの入出力&#34;&gt;プロセスの入出力&lt;/h3&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;出力：終了コード&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;osから見たプロセス&#34;&gt;OSから見たプロセス&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OSの仕事はたくさんあるプロセスに効率よく仕事をさせること&lt;/li&gt;
&lt;li&gt;Linuxではプロセスごとに&lt;code&gt;task_struct&lt;/code&gt;型の&lt;strong&gt;プロセスディスクリプタ&lt;/strong&gt;と呼ばれる構造体を持っている。
&lt;ul&gt;
&lt;li&gt;基本的にはプロセスから見た各種情報と同じ内容だが、そこには含まれていない要素もいくつか存在する。&lt;/li&gt;
&lt;li&gt;例えば、&lt;strong&gt;どこからどこまでが自分のメモリ領域かというメモリブロックの情報&lt;/strong&gt;や&lt;strong&gt;スタック領域がどこにありプログラムが静的に確保するデータや動的に確保するデータがどのようにレイアウトされるか&lt;/strong&gt;もOSが持つプロセスの情報の中にある。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;プロセスの出力に色づけをする&#34;&gt;プロセスの出力に色づけをする&lt;/h3&gt;
&lt;p&gt;プロセスの出力に色をつけたい場合には&lt;strong&gt;ANSIエスケープシーケンス&lt;/strong&gt;を使うことができる。&lt;/p&gt;
&lt;p&gt;自分が利用したことある&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;Rustの&lt;a href=&#34;https://crates.io/crates/colored&#34; target=&#34;_blank&#34; &gt;&lt;code&gt;colored&lt;/code&gt;&lt;/a&gt;クレートも確認したところ実際にANSIエスケープシーケンスを使ってターミナルに色をつけていた。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#[cfg_attr(feature = &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;no-color&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;, ignore)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#[test]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;compute_style_simple_fg_blue&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; blue &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\x1B&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;[34m&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        assert_eq!(blue, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;.blue().compute_style());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;div class=&#34;blogcard&#34; data-url=&#34;https://github.com/colored-rs/colored/blob/775ec9f19f099a987a604b85dc72ca83784f4e38/src/lib.rs#L805-L811&#34; data-auto-fetch=&#34;false&#34;&gt;
  &lt;a href=&#34;https://github.com/colored-rs/colored/blob/775ec9f19f099a987a604b85dc72ca83784f4e38/src/lib.rs#L805-L811&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;blogcard-link&#34;&gt;&lt;div class=&#34;blogcard-thumbnail&#34;&gt;
      &lt;img src=&#34;https://opengraph.githubassets.com/1072123a6eb5d0eb1781edd6afa28fd10244f3ba273a0bc5e3f5e1c1801ffba9/colored-rs/colored&#34; alt=&#34;colored/src/lib.rs at 775ec9f19f099a987a604b85dc72ca83784f4e38 · colored-rs/colored&#34; loading=&#34;lazy&#34;&gt;
    &lt;/div&gt;&lt;div class=&#34;blogcard-content&#34;&gt;
      &lt;div class=&#34;blogcard-title&#34;&gt;colored/src/lib.rs at 775ec9f19f099a987a604b85dc72ca83784f4e38 · colored-rs/colored&lt;/div&gt;&lt;div class=&#34;blogcard-description&#34;&gt;(Rust) Coloring terminal so simple you already know how to do it ! - colored-rs/colored&lt;/div&gt;&lt;div class=&#34;blogcard-url&#34;&gt;https://github.com/colored-rs/colored/blob/775ec9f19f099a987a604b85dc72ca83784f4e38/src/lib.rs#L805-L811&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
 より&lt;/p&gt;
&lt;p&gt;調べてみたところ&lt;code&gt;\x1B&lt;/code&gt;でも&lt;code&gt;\e&lt;/code&gt;でもエスケープシーケンスを表現できるらしい。&lt;sup id=&#34;fnref:7&#34;&gt;&lt;a href=&#34;#fn:7&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&#34;外部プロセスに対して自分が擬似端末だと詐称する&#34;&gt;外部プロセスに対して自分が擬似端末だと詐称する&lt;/h3&gt;
&lt;p&gt;ライブラリによっては、自分が繋がっている先が擬似端末かどうかでエスケープシーケンスを出力するかどうかを決定している。&lt;/p&gt;
&lt;p&gt;子プロセスの出力を色づけするためには、親を擬似端末だと詐称することでエスケープシーケンスを出力させることができる。&lt;/p&gt;
&lt;h3 id=&#34;デーモン化&#34;&gt;デーモン化&lt;/h3&gt;
&lt;p&gt;普通のプログラムはシェルのプロセスの子になってしまうので、ログアウトしたりシェルを閉じたりするだけで終了してしまう。&lt;/p&gt;
&lt;p&gt;そのような場合でも終了しないように下記のような特別な細工が施されたプロセスが&lt;strong&gt;デーモン&lt;/strong&gt;である。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;セッションID、グループIDを新しいものにして既存のセッションとグループから独立&lt;/li&gt;
&lt;li&gt;カレントのディレクトリはルートに移動&lt;/li&gt;
&lt;li&gt;フォークしてからブートプロセスのinitを親に設定し、実際の親はすぐに終了&lt;/li&gt;
&lt;li&gt;標準入出力も起動時のものから切り離される(通常は&lt;code&gt;dev/null&lt;/code&gt;に設定される)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;第13章-シグナルによるプロセス間の通信&#34;&gt;第13章 シグナルによるプロセス間の通信&lt;/h2&gt;
&lt;p&gt;シグナルには主に2つの用途がある。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;プロセス間通信&lt;/strong&gt;: カーネルが仲介してあるプロセスから別のプロセスへとシグナルを送るケース。自分自身にシグナルを送ることもできる。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ソフトウェア割り込み&lt;/strong&gt;: システムで発生したイベントがシグナルとしてプロセスに送られる。シグナルを受け取ったプロセスは現在置くなっているタスクを中断してあらかじめ登録しておいた処理を実行する。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;システムコールはユーザー空間で動作しているプロセスからカーネル空間にはたらきかけるためのインターフェースだが、その逆方向がシグナルだと考えることができる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;システムコールでは最大7つほどの引数を指定できるのに対し、ソフトウェア割り込みとしてのシグナルで送信できるのはその種類のみ。&lt;/li&gt;
&lt;li&gt;プロセスは受け取ったシグナルを無視するか補足して処理する。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;シグナルのハンドラを書く&#34;&gt;シグナルのハンドラを書く&lt;/h3&gt;
&lt;p&gt;Goでは次のように&lt;code&gt;signal.NotifyContext()&lt;/code&gt;を使ってシグナルを受け取ることができる。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;context&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;os/signal&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;syscall&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;time&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Background&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;sigctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;signal&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;NotifyContext&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;syscall&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SIGINT&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;syscall&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;SIGTERM&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;toctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;context&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WithTimeout&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;ctx&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cancel2&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sigctx&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Done&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;signal&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;toctx&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Done&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;timeout&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;KubernetesやDockerでは外からタスクを終了させるとき、まずSIGTERMをアプリケーションに対して送信する。(SIGTERM: &lt;code&gt;kill()&lt;/code&gt;システムコールや&lt;code&gt;kill&lt;/code&gt;コマンドがデフォルトで送信するシグナル。プロセスを終了させるもの)&lt;/p&gt;
&lt;p&gt;(GoアプリケーションのGraceful Shutdownの実装例でSIGTERMをハンドリングするのをよく見るのはだからか、と納得した。)&lt;/p&gt;
&lt;h2 id=&#34;第14章-go言語と並列処理&#34;&gt;第14章 Go言語と並列処理&lt;/h2&gt;
&lt;h3 id=&#34;並行処理と並列処理の違い&#34;&gt;並行処理と並列処理の違い&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;並行処理: 1つのコアで複数のタスクを素早く切り替えながら処理すること&lt;/li&gt;
&lt;li&gt;並列処理: 複数のコアを使って複数のタスクを同時に処理すること&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;チャネル&#34;&gt;チャネル&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Go言語で簡単に並列処理を書くための道具としてgoroutineとチャネルがある。&lt;/li&gt;
&lt;li&gt;チャネルを使うことでデータの入出力を&lt;strong&gt;直列化できる。&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;スレッドとgoroutineの違い&#34;&gt;スレッドとgoroutineの違い&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;スレッドとはプログラムを実行するためのものであり、OSによって手配される。&lt;/li&gt;
&lt;li&gt;プログラムからみたスレッドは「&lt;strong&gt;時間が凍結されたプログラムの実行状態&lt;/strong&gt;」で、CPUが演算に使ったり計算結果や状態を保持したりする&lt;strong&gt;レジスタ&lt;/strong&gt;と呼ばれるメモリと&lt;strong&gt;スタックメモリ&lt;/strong&gt;が含まれる。&lt;/li&gt;
&lt;li&gt;OSは凍結状態のプログラムの実行状態を復元して各スレッドに短時間ずつ処理をさせる。実行予定のスレッドは&lt;strong&gt;ランキュー&lt;/strong&gt;と呼ばれるリストに入っている。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;スレッドがCPUコアに対してマッピングされる&lt;/strong&gt;のに対し、&lt;strong&gt;gouroutineはOSのスレッドにマッピングされる&lt;/strong&gt;点が通常のスレッドとgoroutineとの最大の違い。
&lt;ul&gt;
&lt;li&gt;goroutineはOSスレッドの1~2MBと比べると初期スタックメモリのサイズが小さい(2KB)ため起動処理が軽い。&lt;/li&gt;
&lt;li&gt;また、gouroutineはOSに処理を渡さずに作成できるのでカーネルとのタスク切り替えのコストも小さい。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;goroutineのメリット&#34;&gt;goroutineのメリット&lt;/h3&gt;
&lt;p&gt;大量のクライアントからのリクエストを効率よく捌きたいとき（いわゆるC10K）に、クライアントごとに1つのgoroutineを割り当てたとしても少ないメモリ消費量で処理できる（前述の通りgoroutineは起動時の初期スタックメモリのサイズが小さいため）&lt;/p&gt;
&lt;h2 id=&#34;第15章-並行並列処理の手法と設計のパターン&#34;&gt;第15章 並行・並列処理の手法と設計のパターン&lt;/h2&gt;
&lt;h3 id=&#34;代表的な並行並列処理の手法&#34;&gt;代表的な並行・並列処理の手法&lt;/h3&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;/ul&gt;
&lt;h3 id=&#34;イベント駆動&#34;&gt;イベント駆動&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;主に並列化ではなく並行処理のために使われる。&lt;/li&gt;
&lt;li&gt;I/Oバウンドなプログラムで用いられる。&lt;/li&gt;
&lt;li&gt;OSに依頼したデータ受信の仕事が終わるたびにコールバックが返ってくる仕組み。&lt;/li&gt;
&lt;li&gt;単体ではCPUを使いこなしにくい点が欠点。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;マルチスレッド&#34;&gt;マルチスレッド&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;同じメモリ空間内で多くのCPUが同時に実行するための仕組み
&lt;ul&gt;
&lt;li&gt;Linuxではプロセスもスレッドもカーネル上は同じ構造体として表現されている。親のプロセスとメモリ空間を共有していなければプロセス、共有していればスレッド。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;利点はCPUのパフォーマンスを引き出すことができる点。&lt;/li&gt;
&lt;li&gt;欠点はプロセスほどではないが、OSのスレッドの場合は比較的大きなスタックメモリ（1~2MB）を必要とし、起動時間もややかかる。そのためスレッドプールを作っておき、必要になったらすぐ使えるようにする、ということが行なわれている。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;goにおける並行並列処理のパターン集&#34;&gt;Goにおける並行・並列処理のパターン集&lt;/h3&gt;
&lt;p&gt;アムダールの法則: 並列化を導入するとどれだけ効率が改善するかを表す数式&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;S(N) = 1 / ((1 - P) + P/N)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ここで&lt;code&gt;P&lt;/code&gt;は並列化できる仕事の割合、&lt;code&gt;N&lt;/code&gt;は並列数である。&lt;/p&gt;
&lt;p&gt;P = 0.5, N = ∞のとき、S(N) = 2倍になり、P = 0.9, N = ∞のとき、S(N) = 10倍になる。このことからもわかるように、並列数よりも並列化できるタスクの割合が支配的になる。&lt;/p&gt;
&lt;p&gt;Pを改善するためのアイディアとして次のような手法が考えられる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同期処理を非同期にする&lt;/li&gt;
&lt;li&gt;非同期にしたものを同期化する&lt;/li&gt;
&lt;li&gt;タスク生成と処理を分ける（Producer-Consumerパターン）&lt;/li&gt;
&lt;li&gt;開始した順で処理する（チャネルのチャネル）&lt;/li&gt;
&lt;li&gt;タスク処理が詰まったら待機（バックプレッシャー）&lt;/li&gt;
&lt;li&gt;並列なForループ&lt;/li&gt;
&lt;li&gt;決まった数のgoroutineでタスクを消化する（ワーカープール）&lt;/li&gt;
&lt;li&gt;依存関係のあるタスクを表現する（Future/Promise）&lt;/li&gt;
&lt;li&gt;イベントの流れを定義する（ReactiveX）&lt;/li&gt;
&lt;li&gt;自立した複数のシステムで協調動作（アクターモデル）&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;同期---非同期化&#34;&gt;同期 -&amp;gt; 非同期化&lt;/h4&gt;
&lt;p&gt;I/O処理などの重いタスクを非同期化する&lt;/p&gt;
&lt;h4 id=&#34;非同期---同期化&#34;&gt;非同期 -&amp;gt; 同期化&lt;/h4&gt;
&lt;p&gt;非同期化したタスクはどこかで同期化する必要がある。そのための一番簡単な手法がチャネル。&lt;/p&gt;
&lt;h4 id=&#34;タスク生成と処理を分けるproducer-consumerパターン&#34;&gt;タスク生成と処理を分ける（Producer-Consumerパターン）&lt;/h4&gt;
&lt;p&gt;GoではチャネルでProducerとConsumerを接続することで簡単に実現できる。&lt;/p&gt;
&lt;h4 id=&#34;開始した順で処理するチャネルのチャネル&#34;&gt;開始した順で処理する（チャネルのチャネル）&lt;/h4&gt;
&lt;p&gt;チャネルを用いると複数の処理を終了した順に取り出すことができる。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 終了した順に書き出し
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// チャネルに結果が投入された順に処理される
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;writeToConn&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;responses&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Response&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;conn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;net&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Conn&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;conn&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;// 順番に取り出す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;responses&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Write&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;conn&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;チャネルのチャネルを使うと処理を開始した順で処理をできる。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 開始した順に書き出し
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// チャネルにチャネルを入れた(開始した)順に処理される
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;writeToConn&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;sessionResponses&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;http&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Response&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;conn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;net&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Conn&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;conn&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;// 順番に取り出す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sessionResponse&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sessionResponses&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;// 選択された仕事が終わるまで待つ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sessionResponse&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;response&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Write&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;conn&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;タスク処理が詰まったら待機バックプレッシャー&#34;&gt;タスク処理が詰まったら待機（バックプレッシャー）&lt;/h4&gt;
&lt;p&gt;以下のようなバッファ付きチャネルを使うことで実現できる。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;tasks&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;並列forループ&#34;&gt;並列Forループ&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;forループ内の処理をgoroutineで実行することでループ処理を並列化できる。&lt;/li&gt;
&lt;li&gt;ループ内部の処理が小さすぎるとオーバーヘッドのほうが大きくなり効率が上がらないことがあるので注意が必要。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;決まった数のgoroutineでタスクを消化するワーカープール&#34;&gt;決まった数のgoroutineでタスクを消化する（ワーカープール）&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;特にCPUバウンドな処理ではCPUのコア数以上にgoroutineを作ってもスループットは上がらないため、CPUコア数分のワーカーを作成してタスクを消化するのが効果的な場合がある。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;依存関係のあるタスクを表現するfuturepromise&#34;&gt;依存関係のあるタスクを表現する（Future/Promise）&lt;/h4&gt;
&lt;p&gt;Futureをチャネルで表現すると、必要なデータが揃ったらタスクを逐次実行できる。&lt;/p&gt;
&lt;p&gt;後続の処理に結果を引き継ぎたいが、処理自体は可能な限り非同期で実行したい場合に有効そう。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;readFile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;path&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#75715e&#34;&gt;// ファイルを読み込み、その結果を返すFutureを返す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;promise&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;content&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;os&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;ReadFile&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;path&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;read error %s\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Error&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			close(&lt;span style=&#34;color:#a6e22e&#34;&gt;promise&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#75715e&#34;&gt;// 約束を果たした
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;			&lt;span style=&#34;color:#a6e22e&#34;&gt;promise&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; string(&lt;span style=&#34;color:#a6e22e&#34;&gt;content&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;promise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;printFunc&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;futureSource&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 文字列中の関数一覧を返すFutureを返す
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;promise&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt; []&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;// futureが解決するまで待って実行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;line&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Split&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;futureSource&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;HasPrefix&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;line&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;func &amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt; = append(&lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;line&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#75715e&#34;&gt;// 約束を果たした
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;promise&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;promise&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;futureSource&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;readFile&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;main.go&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;futureFuncs&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;printFunc&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;futureSource&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Join&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;futureFuncs&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;また、次のような構造体を定義することで上記のFutureの値を複数回読み取ることができる。（上記の実装ではバッファなしチャネルを使っているので複数回受信してしまうと処理がブロックされてしまう）&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;StringFuture&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;cache&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NewStringFuture&lt;/span&gt;() (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;StringFuture&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;StringFuture&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt;: make(&lt;span style=&#34;color:#66d9ef&#34;&gt;chan&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;StringFuture&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Get&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ok&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		close(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;cache&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;r&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;cache&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;StringFuture&lt;/span&gt;) &lt;span style=&#34;color:#a6e22e&#34;&gt;Close&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	close(&lt;span style=&#34;color:#a6e22e&#34;&gt;f&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;receiver&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;イベントの流れを定義するreactivex&#34;&gt;イベントの流れを定義する：ReactiveX&lt;/h4&gt;
&lt;p&gt;ここでは&lt;a href=&#34;https://github.com/ReactiveX/RxGo&#34; target=&#34;_blank&#34; &gt;RxGo&lt;/a&gt;を使ってイベントの流れを定義する方法が紹介されていた。
まずこのようにwatcherを定義する。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;watcher&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;observer&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Observer&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;NextHandler&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;item&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;any&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;line&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;item&lt;/span&gt;.(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;strings&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;HasPrefix&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;line&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;func &amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;line&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;ErrHandler&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Encountered error: %v\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;DoneHandler&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Done!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のようにすると&lt;code&gt;NextHandler&lt;/code&gt;に登録された関数に&lt;code&gt;line&lt;/code&gt;が渡される。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;emitter&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そして次のようにすると&lt;code&gt;ErrHandler&lt;/code&gt;に登録された関数が呼ばれる。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;emitter&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;err&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;渡ってきた値に応じて処理を分岐させたく、かつ何度も同一のイベントが発生するケースではこの方法を使うと良さそう。&lt;/p&gt;
&lt;h4 id=&#34;自律した複数のシステムで協調動作アクターモデル&#34;&gt;自律した複数のシステムで協調動作：アクターモデル&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;アクターと呼ばれる自律した多数のコンピューターが協調して動作するというモデル。&lt;/li&gt;
&lt;li&gt;各アクターは別のアクターから送られてくるメッセージを受け取る&lt;strong&gt;メッセージボックス&lt;/strong&gt;を持つ。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;第16章-go言語のメモリ管理&#34;&gt;第16章 Go言語のメモリ管理&lt;/h2&gt;
&lt;h3 id=&#34;仮想メモリ&#34;&gt;仮想メモリ&lt;/h3&gt;
&lt;p&gt;現代のOSではプロセスはメモリを読み書きするのに物理的なアドレスを直接扱うのではなく、プロセスごとに仮想的なメモリアドレス空間があり、それを使ってメモリにアクセスしている。この仮想的なメモリアドレス空間のことを&lt;strong&gt;仮想メモリ&lt;/strong&gt;という。&lt;/p&gt;
&lt;p&gt;仮想メモリのアドレスから実際の物理メモリにアクセスするために&lt;strong&gt;ページテーブル&lt;/strong&gt;というデータ構造が使われる。&lt;strong&gt;ページ&lt;/strong&gt;とはメモリを管理する単位のこと。&lt;/p&gt;
&lt;p&gt;仮想メモリのおかげで実際の保存領域が飛び飛びになっていたとしてもプロセスからはフラットなメモリ領域が確保されているように見える。&lt;/p&gt;
&lt;p&gt;仮想メモリは物理メモリのアドレスと1対1対応しているわけではなく、物理メモリのあるアドレスが複数の仮想メモリから参照されることもある。こうすることで共有ライブラリなどを複数のプロセスで利用でき省メモリになる。&lt;/p&gt;
&lt;h3 id=&#34;osカーネルがプロセスのメモリを確保するまで&#34;&gt;OSカーネルがプロセスのメモリを確保するまで&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;プロセスは起動時にOSからメモリをもらう。OSはプロセスごとに仮想メモリの領域を確保する。&lt;/li&gt;
&lt;li&gt;ユーザーのメモリ空間は大きく3つの連続したメモリ領域に分かれる。3つの領域の間の空きスペース分はメモリの確保が行われない。
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;| ①プログラム + 静的データ | ヒープとして使われる領域 | ②共有ライブラリ |      | ③スタックなど |
小さいアドレス                                                                大きいアドレス -&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;スタック&#34;&gt;スタック&lt;/h3&gt;
&lt;p&gt;関数を呼ぶとリターンアドレスや新しい関数のための作業メモリ領域として&lt;strong&gt;スタックフレーム&lt;/strong&gt;と呼ばれるメモリ領域が確保される。&lt;/p&gt;
&lt;p&gt;スタックフレームはスレッドごとにあらかじめ確保されているメモリブロックに対して順番に追加したり削除されたりされるだけなので割当のコストはほぼゼロ。&lt;/p&gt;
&lt;h3 id=&#34;go言語でのスタックとヒープの使い分け&#34;&gt;Go言語でのスタックとヒープの使い分け&lt;/h3&gt;
&lt;p&gt;Go言語では変数のデータをヒープに置くかスタックに置くかはコンパイラが自動的に判断する。以下はその一部。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new&lt;/code&gt;で初期化してもその関数内でしか利用されなければスタックに確保される。&lt;/li&gt;
&lt;li&gt;ローカル変数として宣言してもそのポインタを他の関数に渡したり、関数の返り値として返すような場合にはヒープに確保される。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Go言語でメモリがスタックとヒープのどちらに確保されるかを知りたい場合にはビルド時に&lt;code&gt;-gcflags -m&lt;/code&gt;を渡すことで確認できる。&lt;/p&gt;
&lt;p&gt;ということで次のコードを使って上記の挙動を確認してみる。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;strValue&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// スタックに確保される(関数内でしか利用されていないため)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;strValue&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;strPtr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; new(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#75715e&#34;&gt;// スタックに確保される(関数内でしか利用されていないため)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;strPtr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;strPtr2&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; new(&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#75715e&#34;&gt;// ヒープに確保される(他の関数に渡されているため)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;receiveStrPtr&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;strPtr2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;strPtrFromFunc&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;returnStrPtr&lt;/span&gt;() &lt;span style=&#34;color:#75715e&#34;&gt;// スタックに確保される(関数内でしか利用されていないため)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;_&lt;/span&gt; = &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;strPtrFromFunc&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;receiveStrPtr&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;argStrPtr&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;argStrPtr: %v\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;argStrPtr&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;returnStrPtr&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#a6e22e&#34;&gt;str&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello, World!&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;// ヒープに確保される(関数の返り値として返されているため)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;	&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;str&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;-gcflags -m&lt;/code&gt;をつけてビルドしてみると次のようになりコードコメント通り、&lt;code&gt;strPtr2&lt;/code&gt;と&lt;code&gt;str&lt;/code&gt;がヒープに確保されていることがわかった。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ go build -gcflags -m main.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# command-line-arguments&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:19:6: can inline receiveStrPtr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:23:6: can inline returnStrPtr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:13:15: inlining call to receiveStrPtr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:15:32: inlining call to returnStrPtr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:13:15: inlining call to fmt.Printf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:20:12: inlining call to fmt.Printf
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:7:15: strValue + &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; does not escape
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:9:15: new&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; does not escape
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:10:14: *strPtr + &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; does not escape
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:12:16: new&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; escapes to heap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:13:15: ... argument does not escape
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:16:22: *strPtrFromFunc + &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; does not escape
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:19:20: leaking param: argStrPtr
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:20:12: ... argument does not escape
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./main.go:24:2: moved to heap: str
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;ガベージコレクタ&#34;&gt;ガベージコレクタ&lt;/h3&gt;
&lt;p&gt;Goをはじめとして多くの言語ではマークアンドスイープという方式が採用されている。&lt;/p&gt;
&lt;p&gt;マークアンドスイープ方式では、まずメモリの領域をスキャンして必要なデータか否かをマークしていき、次のフェーズで不要なものを削除する。&lt;/p&gt;
&lt;p&gt;マークアンドスイープ方式では、不要なメモリを削除する間にプログラム全体を停止する必要がある。（これをストップザワールドと呼ぶ）&lt;/p&gt;
&lt;p&gt;Goではバージョンを重ねる事にストップザワールドの時間の短縮化が進んでいる。&lt;/p&gt;
&lt;h2 id=&#34;第17章-実行ファイルが起動するまで&#34;&gt;第17章 実行ファイルが起動するまで&lt;/h2&gt;
&lt;p&gt;最終的にCPUで実行されるバイナリはメモリ空間に単に命令が並んだもので、そこにはブロックのような概念は存在しない（Goでいうと&lt;code&gt;{&lt;/code&gt;と&lt;code&gt;}&lt;/code&gt;で囲まれた処理の塊）。&lt;/p&gt;
&lt;p&gt;アセンブリ言語には関数のブロックのような概念はないが、その代わりにラベルという概念がある。&lt;/p&gt;
&lt;h3 id=&#34;ランタイムの役割&#34;&gt;ランタイムの役割&lt;/h3&gt;
&lt;p&gt;Goに限らずC言語でもRustでも何かしらのプログラミング言語で生成したアプリケーションは「ランタイム」と呼ばれるライブラリを利用したプログラムになるのが一般的。&lt;/p&gt;
&lt;p&gt;ラインタイムライブラリが最終的にはOSのカーネルにシステムコールを発行して仕事を依頼し、メモリ管理やファイルやネットワークアクセスを実現する役割を担う。&lt;/p&gt;
&lt;p&gt;ラインタイムライブラリがなければ、OSに仕事を依頼するところも自分で作成する必要がある。&lt;/p&gt;
&lt;h3 id=&#34;リンカーの役割&#34;&gt;リンカーの役割&lt;/h3&gt;
&lt;p&gt;以下はWikipediaによるリンカーの説明。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a computer program that takes one or more object files generated by a compiler or generated by an assembler and links them with libraries, generating an executable program or shared library&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Linker&#34; target=&#34;_blank&#34; &gt;Linker - Wikipedia&lt;/a&gt; から引用&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;上記を翻訳すると「コンパイラまたはアセンブラによって生成された1つ以上のオブジェクトファイルをライブラリと結合し実行可能ファイルまたは共有ライブラリを生成するプログラム」といった感じだろうか。&lt;/p&gt;
&lt;p&gt;OSはリンカーが生成した実行ファイルがシェルから起動されると、実行ファイルの内容をメモリに配置する。&lt;/p&gt;
&lt;p&gt;ロードが終わったら決め打ちされた「特定のアドレス」からCPUが命令を読み込んで実行が開始される。&lt;/p&gt;
&lt;p&gt;実行中に発生する関数呼び出しはすでにリンカーによってアドレスが解決されているので示されたアドレスにジャンプするだけで高速に実行される。&lt;/p&gt;
&lt;h3 id=&#34;実行ファイルのメモリ配置&#34;&gt;実行ファイルのメモリ配置&lt;/h3&gt;
&lt;p&gt;OSがアプリケーションの実行ファイルを最初にロードしてくる部分についての解説。&lt;/p&gt;
&lt;p&gt;まず、実行ファイルのフォーマットはOSによって異なる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;LinuxなどのPOSIX系OS: ELF形式&lt;/li&gt;
&lt;li&gt;Windows: PE(Portable Executable)形式&lt;/li&gt;
&lt;li&gt;macOS: Mach-O形式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;また、実行ファイルには次のようなデータが格納されている。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;この実行ファイルが対象としているCPUアーキテクチャの種類&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;ul&gt;
&lt;li&gt;&lt;code&gt;TEXT&lt;/code&gt;: 機械語の実行コードが格納されるセクション&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DATA&lt;/code&gt;: 実行コードを含まない静的に確保された初期化済み（データがすでに入っている）のメモリ領域&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BSS&lt;/code&gt;: 変数が置かれる領域で初期化されていない（すべてゼロ）メモリ領域&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OSはこの実行ファイルフォーマットに従って実行ファイルに含まれるセクションを適切なアドレスに配置していく。&lt;sup id=&#34;fnref:8&#34;&gt;&lt;a href=&#34;#fn:8&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;8&lt;/a&gt;&lt;/sup&gt;その後実行ファイルフォーマットに書かれた初期実行アドレスを実行することでアプリケーションが起動する。&lt;/p&gt;
&lt;h3 id=&#34;goのプログラムの起動&#34;&gt;Goのプログラムの起動&lt;/h3&gt;
&lt;p&gt;Goで書かれたソースコードが実行されるまでの流れは以下。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Goで書かれたアプリケーションをコンパイルすると実行ファイルが作成される&lt;/li&gt;
&lt;li&gt;コンパイル済みのGoプログラムを実行すると実行環境のランタイムにある&lt;code&gt;$GOROOT/src/runtime/asm_(ARCH名).s&lt;/code&gt;というファイルのなかにある&lt;code&gt;_rt0_(ARCH名)&lt;/code&gt;という関数が呼ばれる。このプロシージャの中では以下のような処理が実行される。
&lt;ol&gt;
&lt;li&gt;最初のgoroutineの初期化&lt;/li&gt;
&lt;li&gt;OSから渡されるコマンドライン引数&lt;code&gt;os.Args&lt;/code&gt;のパース&lt;/li&gt;
&lt;li&gt;コンピュターで利用可能なCPUコア数の取得&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$GOROOT/src/runtime/proc.go&lt;/code&gt;の&lt;code&gt;schedinit()&lt;/code&gt;関数の中で以下のような処理が実行される。
&lt;ul&gt;
&lt;li&gt;スタックを初期化&lt;/li&gt;
&lt;li&gt;メモリマネージャを初期化し、Mを初期化&lt;/li&gt;
&lt;li&gt;mapの内部で使われるハッシュアルゴリズムの初期化&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;/li&gt;
&lt;/ol&gt;
&lt;p&gt;次に新しいgoroutineを作って&lt;code&gt;$GOROOT/src/runtime/proc.go&lt;/code&gt;の&lt;code&gt;main()&lt;/code&gt;関数が呼び出される。そこでは以下のような流れで処理が進む。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;runtime.lockOSThread()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;(ランタイムの)&lt;code&gt;init()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main・init()&lt;/code&gt;(アプリケーションのmainパッケージの&lt;code&gt;init()&lt;/code&gt;関数)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runtime.unlockOSThread()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main・main()&lt;/code&gt;(アプリケーションのmainパッケージの&lt;code&gt;main()&lt;/code&gt;関数)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;まとめ&#34;&gt;まとめ&lt;/h2&gt;
&lt;p&gt;ここまでの理解をもとにいくつかの質問に対する答えを書いてみる。&lt;/p&gt;
&lt;h3 id=&#34;プロセスとスレッドの違いは何か&#34;&gt;プロセスとスレッドの違いは何か&lt;/h3&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;/ul&gt;
&lt;h3 id=&#34;プログラムはどのような流れで実行されるか&#34;&gt;プログラムはどのような流れで実行されるか&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;コンパイラがソースコードをコンパイルする&lt;/li&gt;
&lt;li&gt;リンカーがコンパイル済みのオブジェクトファイルをリンクし実行可能ファイルを生成する&lt;/li&gt;
&lt;li&gt;ユーザーが実行可能ファイルを実行する(e.g. ターミナルから呼び出す)&lt;/li&gt;
&lt;li&gt;OSがプロセスを生成し、プロセスの実行に必要な仮想メモリ空間を割り当てる&lt;/li&gt;
&lt;li&gt;OSが実行ファイルの内容をディスクからメモリに読み込み、仮想アドレス空間に適切に配置する&lt;/li&gt;
&lt;li&gt;メインスレッドでプログラムが実行される(プロセスが生成されると自動的にメインスレッドが作成される)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;感想&#34;&gt;感想&lt;/h3&gt;
&lt;p&gt;冒頭にも書いた通りCSを体系的に学んだ経験がない自分にとってはとても勉強になった。&lt;/p&gt;
&lt;p&gt;次はこのあたりの書籍を読んでみようとおもう。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;コンピュータシステムの理論と実装&lt;/li&gt;
&lt;li&gt;Go言語による並行処理&lt;/li&gt;
&lt;li&gt;つくって、壊して、直して学ぶ Kubernetes入門&lt;/li&gt;
&lt;li&gt;Linuxで動かしながら学ぶTCP/IPネットワーク入門&lt;/li&gt;
&lt;li&gt;体系的に学ぶ 安全なWebアプリケーションの作り方&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;あるいは、 &lt;a href=&#34;https://blog.ojisan.io/server-architecture-2023/#%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9-vs-%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89&#34; target=&#34;_blank&#34; &gt;Webサーバーアーキテクチャ進化論2023 - blog.ojisan.io&lt;/a&gt;を参考に学習ロードマップを立ててみるのもいいかもしれない。&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Neovimでのデバッガの環境構築は &lt;a href=&#34;https://zenn.dev/saito9/articles/32c57f776dc369&#34; target=&#34;_blank&#34; &gt;nvim-dapでGolangのデバッグ環境構築&lt;/a&gt; を参考にした&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;code&gt;Sysfd&lt;/code&gt;の定義はgolang/go/src/internal/poll/fd_unix.go#L23(&lt;a href=&#34;https://github.com/golang/go/blob/c83b1a7013784098c2061ae7be832b2ab7241424/src/internal/poll/fd_unix.go#L23&#34; target=&#34;_blank&#34; &gt;https://github.com/golang/go/blob/c83b1a7013784098c2061ae7be832b2ab7241424/src/internal/poll/fd_unix.go#L23&lt;/a&gt;) にある。&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;&lt;code&gt;io.Pipe&lt;/code&gt;の使いどころに関しては &lt;a href=&#34;https://medium.com/eureka-engineering/file-uploads-in-go-with-io-pipe-75519dfa647b&#34; target=&#34;_blank&#34; &gt;Go言語のio.Pipeでファイルを効率よくアップロードする方法&lt;/a&gt; が大変参考になった。&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;cf. &lt;a href=&#34;https://github.com/kyu08/go-system-programming/blob/b9da4a0ce759b2df4ce884ab61248fb893b60bef/4-channel/unbufferedchannel/main.go#L8&#34; target=&#34;_blank&#34; &gt;kyu08/go-system-programming/4-channel/unbufferedchannel/main.go#L8&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;Distrolessに対して「コンテナイメージが軽量になる」以外のメリットを感じていなかったが書かれている通りセキュリティ面でもメリットがあると気付いた。&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34;&gt;
&lt;p&gt;fzf-makeの出力の一部に色を付けるために使っている。 &lt;a href=&#34;https://github.com/kyu08/fzf-make/blob/12789acd19bc24daa60ba7eb84973dab18fe7a52/src/usecase/execute_make_command.rs#L5&#34; target=&#34;_blank&#34; &gt;https://github.com/kyu08/fzf-make/blob/12789acd19bc24daa60ba7eb84973dab18fe7a52/src/usecase/execute_make_command.rs#L5&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:7&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://ufcpp.net/blog/2023/12/escape-escape/&#34; target=&#34;_blank&#34; &gt;https://ufcpp.net/blog/2023/12/escape-escape/&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:7&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:8&#34;&gt;
&lt;p&gt;仮想メモリ空間についてはκeenさんのこちらの記事がとてもわかりやすかった。&lt;a href=&#34;https://keens.github.io/blog/2017/04/30/memoritosutakkutohi_puto/&#34; target=&#34;_blank&#34; &gt;メモリとスタックとヒープとプログラミング言語&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:8&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </item>
    
    <item>
      <title>Goの静的解析に入門した</title>
      <link>https://blog.kyu08.com/pr-344/posts/hello-go-static-analisys/</link>
      <pubDate>Mon, 17 Jul 2023 05:21:29 +0000</pubDate>
      
      <guid>https://blog.kyu08.com/pr-344/posts/hello-go-static-analisys/</guid>
      <description>tenntenn Conference 2023 にスポンサーし、Goの静的解析を完全に理解した話 を読んでから静的解析が気になっていたのでこれをやってみた。 静的解析をはじめよう - Gop</description>
      <content>&lt;p&gt;&lt;a href=&#34;https://zenn.dev/team_soda/articles/8e61219eab0fc8&#34; target=&#34;_blank&#34; &gt;tenntenn Conference 2023 にスポンサーし、Goの静的解析を完全に理解した話&lt;/a&gt; を読んでから静的解析が気になっていたのでこれをやってみた。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://golangtokyo.github.io/codelab/find-gophers/?index=codelab#0&#34; target=&#34;_blank&#34; &gt;静的解析をはじめよう - Gopherをさがせ！&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;以下のようなソースコードから&lt;code&gt;Gopher&lt;/code&gt;型を探し出す簡単な解析スクリプトを通してGoでの静的解析の流れやASTの探索方法、型チェックを用いたより詳細な解析方法などを学べた。&lt;/p&gt;
&lt;blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;fmt&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Gopher&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; { &lt;span style=&#34;color:#75715e&#34;&gt;// ここ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;Gopher&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`json:&amp;#34;gopher&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;gopher&lt;/span&gt; = &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GOPHER&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;gogopher&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GOPHER&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;gogopher&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Gopher&lt;/span&gt; = &lt;span style=&#34;color:#a6e22e&#34;&gt;gopher&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;gogopher&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GOPHER&lt;/span&gt;() (&lt;span style=&#34;color:#a6e22e&#34;&gt;gopher&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Gopher&lt;/span&gt;) { &lt;span style=&#34;color:#75715e&#34;&gt;// ここ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;gopher&lt;/span&gt; = &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Gopher&lt;/span&gt;{&lt;span style=&#34;color:#a6e22e&#34;&gt;Gopher&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gopher&amp;#34;&lt;/span&gt;} &lt;span style=&#34;color:#75715e&#34;&gt;// ここ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://golangtokyo.github.io/codelab/find-gophers/?index=codelab#2&#34; target=&#34;_blank&#34; &gt;https://golangtokyo.github.io/codelab/find-gophers/?index=codelab#2&lt;/a&gt; より&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;解説がかなり丁寧でわかりやすかったので静的解析初心者にはかなりありがたかった。&lt;/p&gt;
&lt;p&gt;静的解析を使えば単なる&lt;code&gt;grep&lt;/code&gt;ではできないことができるイメージが実際に掴めたので早速linterを作ってみようと思う。&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>yamlに定義したbookmarkをfzfで選択してブラウザで開くCLIツールをGoで作った</title>
      <link>https://blog.kyu08.com/pr-344/posts/fzf-bookmark-opener/</link>
      <pubDate>Wed, 22 Feb 2023 16:15:48 +0000</pubDate>
      
      <guid>https://blog.kyu08.com/pr-344/posts/fzf-bookmark-opener/</guid>
      <description>つくったもの yamlに定義しておいたbookmarkをfzfで選択してブラウザで開くCLIツールをGoで作った。 GitHub - kyu08/fzf-bookmark-opener: A command line tool that opens bookmark using fzf.A command line</description>
      <content>&lt;h2 id=&#34;つくったもの&#34;&gt;つくったもの&lt;/h2&gt;
&lt;p&gt;yamlに定義しておいたbookmarkをfzfで選択してブラウザで開くCLIツールをGoで作った。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;blogcard&#34; data-url=&#34;https://github.com/kyu08/fzf-bookmark-opener&#34; data-auto-fetch=&#34;false&#34;&gt;
  &lt;a href=&#34;https://github.com/kyu08/fzf-bookmark-opener&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;blogcard-link&#34;&gt;&lt;div class=&#34;blogcard-thumbnail&#34;&gt;
      &lt;img src=&#34;https://opengraph.githubassets.com/d139e419d52297633132631fea0101b20a871eb91b1cb56c2a1ffb7780b41a17/kyu08/fzf-bookmark-opener&#34; alt=&#34;GitHub - kyu08/fzf-bookmark-opener: A command line tool that opens bookmark using fzf.&#34; loading=&#34;lazy&#34;&gt;
    &lt;/div&gt;&lt;div class=&#34;blogcard-content&#34;&gt;
      &lt;div class=&#34;blogcard-title&#34;&gt;GitHub - kyu08/fzf-bookmark-opener: A command line tool that opens bookmark using fzf.&lt;/div&gt;&lt;div class=&#34;blogcard-description&#34;&gt;A command line tool that opens bookmark using fzf. - kyu08/fzf-bookmark-opener&lt;/div&gt;&lt;div class=&#34;blogcard-url&#34;&gt;https://github.com/kyu08/fzf-bookmark-opener&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;こんな感じで動く。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://user-images.githubusercontent.com/49891479/218272272-e693c10d-c810-458a-bf46-9c3a4a2fe45a.gif&#34; alt=&#34;demo&#34; loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2 id=&#34;コードの話&#34;&gt;コードの話&lt;/h2&gt;
&lt;p&gt;コード自体は大変シンプルで&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;設定ファイルがなければ&lt;code&gt;~/.config/fzf-bookmark-opener/config.yaml&lt;/code&gt;に作成&lt;/li&gt;
&lt;li&gt;設定ファイルの読み込み&lt;/li&gt;
&lt;li&gt;fzfで選択&lt;/li&gt;
&lt;li&gt;選択されたブックマークをブラウザで開く&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ということをやっているだけである。(&lt;code&gt;main.go&lt;/code&gt;に120行弱だけという素朴なコード量)&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/kyu08/fzf-bookmark-opener/blob/69313bf187dcfd6127efcf75e172a34fb9b8e05a/main.go#L38-L60&#34; target=&#34;_blank&#34; &gt;fzf-bookmark-opener/main.go at main · kyu08/fzf-bookmark-opener&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;この記述量で作れたのは間違いなくktr0731/go-fuzzyfinderのおかげでした。このライブラリのおかげでgoのコードからfzfを簡単に呼び出すことができました。というかなんならこのライブラリの存在を知ったので使ってみたくなってfzf-bookmark-openerを作ったみたいなとこもあります。ありがとうございます。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ktr0731/go-fuzzyfinder&#34; target=&#34;_blank&#34; &gt;ktr0731/go-fuzzyfinder&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;ちゃっかりbrewでも公開してみた&#34;&gt;ちゃっかりbrewでも公開してみた&lt;/h2&gt;
&lt;p&gt;brewでインストールできるに越したことはないだろうってことで、brewでも公開してみたが思いのほか簡単だった。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew tap kyu08/tap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install kyu08/tap/fzf-bookmark-opener
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これだけでインストールできるので気になった方もそうでない方もぜひ。issueやPRもお待ちしています。(&lt;code&gt;go install&lt;/code&gt;でインストールしたい方はこちら(&lt;code&gt;go install github.com/kyu08/fzf-bookmark-opener@latest&lt;/code&gt;))&lt;/p&gt;
&lt;p&gt;brew公開に関してはこちらのブログを参考にしたら30分弱でサクッと公開できた(想像より簡単だった)&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;blogcard&#34; data-url=&#34;https://www.rasukarusan.com/entry/2019/11/03/211338&#34; data-auto-fetch=&#34;false&#34;&gt;
  &lt;a href=&#34;https://www.rasukarusan.com/entry/2019/11/03/211338&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;blogcard-link&#34;&gt;&lt;div class=&#34;blogcard-thumbnail&#34;&gt;
      &lt;img src=&#34;https://cdn.image.st-hatena.com/image/scale/887da0d267a399928f4f3e7a0eb22ea2278d9656/backend=imagemagick;version=1;width=1300/https%3A%2F%2Fcdn-ak.f.st-hatena.com%2Fimages%2Ffotolife%2Fr%2Frasukarusan%2F20191103%2F20191103211239.png&#34; alt=&#34;【備忘録】Homebrewで自作ツールを配布する - ハイパーマッスルエンジニア&#34; loading=&#34;lazy&#34;&gt;
    &lt;/div&gt;&lt;div class=&#34;blogcard-content&#34;&gt;
      &lt;div class=&#34;blogcard-title&#34;&gt;【備忘録】Homebrewで自作ツールを配布する - ハイパーマッスルエンジニア&lt;/div&gt;&lt;div class=&#34;blogcard-description&#34;&gt;Homebrewでの配布は簡単だが毎回忘れる Goでバイナリ作ったり、ShellScript書いて配布したいなと思ったときにHomebrew使うことが割とある。 が、その都度毎回調べてやり方を思い出しながらするのが億劫だったので、一回まとめてみる。 ざっくり手順 Homebrew配布用のリポジトリを作る tagをpushしてReleaseノートを作る Formulaファイルを作ってpush 1. Homebrew配布用のリポジトリを作る 自作ツールのインストールファイルを置くためのリポジトリを作る。このリポジトリにバイナリとかの成果物を置くわけではない。置くのはインストールファイルである.rb…&lt;/div&gt;&lt;div class=&#34;blogcard-url&#34;&gt;https://www.rasukarusan.com/entry/2019/11/03/211338&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;p&gt;詳細は↑の記事を読んでいただければわかるが、リリースにバイナリを含めて配布用のrepositoryを作るだけなので本当に簡単だったのでツールを配布したい人はぜひ。&lt;/p&gt;
&lt;h2 id=&#34;ちゃっかりヘルパースクリプトも公開した&#34;&gt;ちゃっかりヘルパースクリプトも公開した&lt;/h2&gt;
&lt;p&gt;現在お仕事ではGCPを使っているんですが、GCPのコンソールをプロジェクト、サービスを指定して直接開きたいことが多いのでプロジェクトのリストを渡すとGCPの主要なサービス(主観)のURL一覧をfzf-bookmark-openerの設定ファイルの形式で吐いてくれるスクリプトも公開した。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/kyu08/gcp-url-generator&#34; target=&#34;_blank&#34; &gt;kyu08/gcp-url-generator&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;project名のリストとregionを渡すとこういう文字列を吐いてくれるイメージ。(以下は出力の一部)(この例だとregionは関係ない)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Home stg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://console.cloud.google.com/home/dashboard?project=stg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Home dev&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://console.cloud.google.com/home/dashboard?project=dev&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Home prod&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://console.cloud.google.com/home/dashboard?project=prod&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Datastore stg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://console.cloud.google.com/datastore/entities?project=stg&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Datastore dev&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://console.cloud.google.com/datastore/entities?project=dev&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  - &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Datastore prod&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;https://console.cloud.google.com/datastore/entities?project=prod&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;現在の対応サービスは以下で、Cloud Runに関してはサービス名の配列を渡すとプロジェクト*サービスの全組み合わせのURLを吐く。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dashboard&lt;/li&gt;
&lt;li&gt;Datastore&lt;/li&gt;
&lt;li&gt;App Engine&lt;/li&gt;
&lt;li&gt;Artifact Registry&lt;/li&gt;
&lt;li&gt;Cloud Storage&lt;/li&gt;
&lt;li&gt;Spanner&lt;/li&gt;
&lt;li&gt;BigQuery&lt;/li&gt;
&lt;li&gt;Cloud Scheduler&lt;/li&gt;
&lt;li&gt;PubSub&lt;/li&gt;
&lt;li&gt;Dataflow&lt;/li&gt;
&lt;li&gt;Cloud Build&lt;/li&gt;
&lt;li&gt;Cloud Tasks&lt;/li&gt;
&lt;li&gt;Cloud Run&lt;/li&gt;
&lt;li&gt;Cloud SQL&lt;/li&gt;
&lt;li&gt;Cloud Functions&lt;/li&gt;
&lt;li&gt;IAM&lt;/li&gt;
&lt;li&gt;Secret Manager&lt;/li&gt;
&lt;li&gt;AI Platform&lt;/li&gt;
&lt;li&gt;Compute Engine&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Monitoring&lt;/li&gt;
&lt;li&gt;Workflows&lt;/li&gt;
&lt;li&gt;Firebase Realtime Database (DB)&lt;/li&gt;
&lt;li&gt;Firebase Hosting&lt;/li&gt;
&lt;li&gt;Firebase Remote Config&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これで生成したURLをfzf-bookmark-openerに食わせるとお使いのGCPプロジェクトの特定のサービスがコマンドラインからサクッと開くことができる。(詳しくは&lt;a href=&#34;https://github.com/kyu08/gcp-url-generator&#34; target=&#34;_blank&#34; &gt;kyu08/gcp-url-generatorのREADME&lt;/a&gt;を参照)
こちらもissueやPRお待ちしてます。&lt;/p&gt;
&lt;h2 id=&#34;余談1&#34;&gt;余談1&lt;/h2&gt;
&lt;p&gt;Rustだとlotabout/skimを使うとktr0731/go-fuzzyfinderと同じようなことができるらしい。最近Rust熱が高まりに高まっている(Tour of Rustやり中)ので次に何かCLIでfzfなツールをつくるときは使ってみようと思う。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/lotabout/skim&#34; target=&#34;_blank&#34; &gt;lotabout/skim&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;[追記]
Makefileに定義されたtargetをfzfで選択して実行するCLIツールをRustでつくった。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/kyu08/fzf-make&#34; target=&#34;_blank&#34; &gt;kyu08/fzf-make&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;余談2&#34;&gt;余談2&lt;/h2&gt;
&lt;p&gt;ふと気になってktr0731/go-fuzzyfinderをはじめとする依存ライブラリのライセンス表示はどうすればいいか気になって調べてみたところリポジトリに&lt;code&gt;NOTICES&lt;/code&gt;とか&lt;code&gt;CREDITS&lt;/code&gt;とか&lt;code&gt;ThirdPartyNotices&lt;/code&gt;みたいなファイルを置いてそこに依存ライブラリの著作権・ライセンス表示をするのが一般的なようだった。&lt;/p&gt;
&lt;p&gt;手作業でやるのは辛いので自動生成ツールを探したところGoだとこれが使いやすそうだったので使ってみたけど簡単でとてもよかった。ありがたや&amp;hellip;。&lt;/p&gt;
&lt;p&gt;&lt;div class=&#34;blogcard&#34; data-url=&#34;https://github.com/Songmu/gocredits&#34; data-auto-fetch=&#34;false&#34;&gt;
  &lt;a href=&#34;https://github.com/Songmu/gocredits&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34; class=&#34;blogcard-link&#34;&gt;&lt;div class=&#34;blogcard-thumbnail&#34;&gt;
      &lt;img src=&#34;https://opengraph.githubassets.com/e988441e6034bc06ec50b0ad38ca1afba52744179f5c59d77afbb6cbb6764640/Songmu/gocredits&#34; alt=&#34;GitHub - Songmu/gocredits: creates CREDITS file from LICENSE files of dependencies&#34; loading=&#34;lazy&#34;&gt;
    &lt;/div&gt;&lt;div class=&#34;blogcard-content&#34;&gt;
      &lt;div class=&#34;blogcard-title&#34;&gt;GitHub - Songmu/gocredits: creates CREDITS file from LICENSE files of dependencies&lt;/div&gt;&lt;div class=&#34;blogcard-description&#34;&gt;creates CREDITS file from LICENSE files of dependencies - Songmu/gocredits&lt;/div&gt;&lt;div class=&#34;blogcard-url&#34;&gt;https://github.com/Songmu/gocredits&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/p&gt;
&lt;h2 id=&#34;まとめ&#34;&gt;まとめ&lt;/h2&gt;
&lt;p&gt;ktr0731/go-fuzzyfinderはいいぞ〜&lt;/p&gt;
</content>
    </item>
    
  </channel>
</rss>
