Carpe Diem

備忘録

Go

ポインタを図で理解する

Go

概要 Goのポインタを図で理解することで ダブルポインタとは Goは全て値渡し ポインタレシーバと値レシーバの違い がどういうことかを理解でき、参照渡しの時に x = y だと更新されず *x = *y だと更新される理由が分かります。

structのメモリ割り当て

Go

概要 Goにおけるstructのメモリ構造を知ることでフィールド順序に対する意識が変わったり、なぜunsafe.Sizeof(string)が16bytesでunsafe.Sizeof(slice)が24bytesになるかが理解できます。 環境 Go 1.15.6 darwin 20.1.0 x86_64 各型のメモリ割り当て unsafe.…

GoでShutdown Hook

Go

背景 以前Graceful shutdown機能の使い方を紹介しました。 christina04.hatenablog.com これによって処理途中のリクエストが残っていても、きちんと完了するまで待ってからプロセスを終了してくれます。 しかしPubSubのPublish()のような非同期処理であれば…

継続的プロファイリング

背景 過去にいくつかpprofの使い方を紹介しましたが、実際に運用する上では以下の課題があります。 何かしら問題が発生して初めてプロファイリング開始するという後手になりがち 問題の再現が難しく、再び発生するまで様子見という流れになりがち プロファイ…

GCPのCloud PubSubで考慮すること

概要 GCPのCloud PubSubはメッセージング基盤として非常に有用です。 ただし利用する上で考慮すべきことも多々あるのでまとめておきます。 パラメータに関しては主にGoのクライアントライブラリをベースに説明します。 環境 Go 1.15.2 google-cloud-go v0.72…

データ暗号化で考慮すること(鍵編)

概要 前回の続きです。 christina04.hatenablog.com 今回は暗号化における鍵(共通鍵)について説明します。 前提知識 鍵とは 鍵とはとても大きな数です。 鍵のビット長が大きい=鍵空間が大きいことを意味します。つまり可能な鍵の総数が大きいため総当り攻…

データ暗号化で考慮すること(暗号アルゴリズム編)

概要 ユーザのメールアドレスといった機密情報を暗号化・復号したいユースケースがあるとします。 メール送信などに利用するためパスワードのようにハッシュ化するのでなく、復号して利用したいケースです。 機密情報の管理全般については以前↓で話しました…

GoのCLIで標準入力とファイル読み込みの両方に対応する

Go

概要 Goでは簡単にコマンドラインツールが作れますが、人によって引数やオプションといったインタフェースがバラバラになりがちです。 POSIX Utility Syntax Guidelinesというガイドラインがあるので、これに則るとUnixライクな統一されたインタフェースのCL…

gRPCのkeepaliveで気をつけること

概要 gRPCでは1つのHTTP/2コネクション上でstreamを多重化します。 しかしidleなコネクションは、LBなど間に介在するネットワーク機器によって気づいたら切断されているケースがあります。 そうならないよう、定期的にパケット(PINGフレーム)を流して「id…

GoGo Protobufのメリット・デメリット

概要 Goでprotobufのコードを生成する際には公式のgolang/protbuf以外にgogo/protobufが候補に挙がると思います。 メリット 大きなメリットはパフォーマンスとカスタマイズ性です。 marshalling と unmarshalling が高速 去年のベンチマークですが、公式より…

Go でサーバレスポンスの内容を表示

Go

概要 開発中にサーバレスポンスの内容を表示したい時があると思いますが クライアントが受け取ったレスポンス サーバが送ったレスポンス のそれぞれをログなどで表示する方法を紹介します。 環境 go 1.14.3 クライアントが受け取ったレスポンスを表示 クライ…

Goのioパッケージのメソッドを図示

Go

概要 Goのioパッケージにはio.Reader、io.Writerのインタフェースを有効活用するため以下のような便利なメソッドが用意されています。 io.Copy io.Pipe io.MultiReader io.MultiWriter io.TeeReader しかし普段から使っていないと、これらメソッドの方が簡単…

CPU CFS Quotaを制限している場合の適切なGOMAXPROCS

概要 christina04.hatenablog.com 以前上の記事でGOMAXPROCSはCPU数程度が適切に動くという話をしました。 これはこれで正しいのですが、一方でdockerのようにcgroupsでCPU Quotaを制限するケースではこれに当てはまらなくなります。 Kubernetesでいうと Kub…

Go Module MirrorとChecksum Database

Go

概要 Go 1.13から、goコマンドはデフォルトでGo Module MirrorとChecksum Databaseを使用してモジュールをダウンロード&認証するようになりました。 環境 go 1.14.1 Module Mirror (Module Proxy) Module Mirrorは公開モジュールをキャッシュし、go modでの…

go generateでモックを生成する

Go

背景 Clean Architecture に則ってレイヤ間をプラガブルにするためにインタフェースを使っていくと、テストのために各インタフェースのモックが欲しくなります。 そのモックを生成する際にgolang/mockを使用するわけですが、毎回 $ mockgen -source user.go …

gRPCでのLoad Balancing

背景 gRPCでは主に Proxy Model Balancing-aware Client External Load Balancing Service といったLBアプローチがあります。 それぞれの特徴や実装方法を調べてみました。 Load Balancingアプローチ こちらで定義されてます。 grpc/load-balancing.md at ma…

gRPCでのClient-Side LB実装の変遷

概要 gRPCでのバランシングをClient-Sideで直接実装する方法の紹介です。 gRPCはPolyglot(様々な言語で扱う)を意識しているので、gRPC自体の仕様が策定→各言語がそれに則って実装となります。 なので「元々はこういう実装だったけど、他の言語と統一してこ…

go modulesでコマンドラインツールのバージョン管理をする

Go

概要 goはModulesでリポジトリのライブラリのバージョン管理を行えます。 ただコマンドラインツールに関してはgo getしてgo.modに追加されても、goファイルで扱っているわけではないのでgo mod tidyすると消えてしまいます。 しかしながら「この機能は最新の…

GoのDIツールwireで知っておくと良いこと

Go DI

概要 christina04.hatenablog.com こういった設計のようにレイヤ間の依存関係を抽象化していると、DIの初期化処理が段々冗長になっていきます。 google/wireはそういったDIの初期化を自動的にやってくれるコード生成ツールです。 今回はwireを使う上で知って…

vim-goからvim-lspへ移行しました

概要 vim-goからvim-lspへ移行する時に問題になってたところを全部mattnさんが解決してくださってたのでようやく完全移行したという話です。 環境 vim 8.2 go 1.13.5 これまでの課題 vim-goの問題点 2014年からgoを触っていましたが当時はvim-go一択で、しか…

cgoを使わないGoのクロスコンパイル時に -installsuffix cgo が不要になってた

背景 以前Docker multi stage buildなどビルド環境と実行環境が異なる(クロスコンパイル)時に、単純にGOOSやGOARCHをセットするだけではなく $ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ go build -a -installsuffix cgo -o main main.go のように CGO_ENA…

Go の http.Server は各種 Timeout をセットした方が良い

Go

概要 以前↓の記事を紹介しましたが、 christina04.hatenablog.com http.Serverの各Timeoutを使わないと TCPハンドシェイクをしたあと全くリクエストを送ってこないクライアント Slowloris DDoS attack による大量接続攻撃を受けた時に困るので注意してくださ…

pipeエラーのハンドリング

概要 write: broken pipeといったクライアント側の強制的なコネクション切断でのエラーハンドリングをする際の知見まとめ。 環境 golang/go 1.13.3 事前知識 知っておくと良い知識を先に説明します。 そもそもpipeとは pipeはプロセス間通信をするための単方…

Goのnet/httpのkeep-aliveで気をつけること

概要 Idle connectionをプールするkeep-aliveの仕組みですが、Goで適切に使用するためにはいくつか注意があります。 環境 golang/go 1.13.1 TCP Keep-Aliveの挙動をパケットキャプチャで確認する 例えば以下のようにDefaultTransportの一部の設定(①、②)を…

Goのnet/httpのtimeoutについて

Go

概要 タイムアウトと一口に言ってもサーバ・クライアント、そして各フェーズによって細かく設定があります。 今回はGoのnet/httpのtimeoutについて1つ1つ説明していきます。 環境 golang/go 1.13 Server 全体図 サーバ系timeoutと各フェーズは以下の関係に…

gRPC Unary Interceptorを複数設定した時の実行順序

概要 以前 christina04.hatenablog.com にてgRPCのUnary Interceptorの基本的な使い方を説明しました。 このInterceptorを複数設定したい時に使われるのがgo-grpc-middlewareの出している ChainUnaryServer ChainUnaryClient です。READMEにありますが、以下…

Go言語でプラグイン機構【RPC編】

概要 オブジェクト指向についてClean Architectureでは OOとは「ポリモーフィズムを使用することで、システムにあるすべてのソースコードの依存関係を絶対的に制御する能力」である。 これにより、アーキテクトは「プラグインアーキテクチャ」を作成できる。…

rand.Readerはいつエラーを返すのか

概要 Go言語のuuid生成で有名な satori/go.uuid はこちらのコミットでUUIDv4を生成する際にエラーを返すように変わりました。 理由は github.com このissueに対応するためなのですが、内部で使っているrand.Read()はそもそもどんな時にエラーが起きるのだろ…

Goの実プロジェクトでのエラーハンドリングの悩みどころと解決案

概要 Go言語に限らずではありますが レイヤ間のエラー伝搬 外部APIを叩いた時のエラーコードハンドリング HTTPやgRPCとしてレスポンスを返す時のエラーハンドリング で悩むことは多いと思います。 今回はそれの1つの方針を紹介します。 課題 レイヤ間のエラ…

singleflight でキャッシュのOriginへのリクエストを抑制

Go

概要 Goにはsingleflightという重複した関数呼び出しを抑制する仕組みがあります。 例えばキャッシュが切れた時にOriginへのアクセスが並行して走ってしまう(Cache Stampede)ケースでサーバやDBがスローダウンする問題がありますが、こういった時にsinglefli…