GaiaExGaiaEx
分散システムとマイクロサービスのための Go
開発者プログラミング10 min read

分散システムとマイクロサービスのための Go

シンプルで速く、並行処理のために作られた言語

投稿を共有

Go がクラウドインフラを支配する理由

Go は大規模なネットワークシステムのために作られた言語です。高速なコンパイル、シンプルな言語仕様、I/O に強い標準ライブラリを備えています。だからこそ Docker、Kubernetes、Terraform、etcd をはじめ、数多くのインフラツールが単一の静的バイナリとして配布されています。

CPU サイクルあたりの速度では最速ではありません。しかし RPC・シリアライズ・ファンアウトに時間を費やすサービス——マッチングコアを除く大半の取引所バックエンドがまさにこれです——を本番投入するまでの速さでは、最も優れた言語の一つです。

GaiaEx のようなスタックでは、ホットループから最後のナノ秒を削り出すことよりもスループットとシンプルさが勝る場面で Go を採用しています。

goroutine と channel: シンプルな並行処理

goroutine は軽量なユーザースペースタスクであり、channel はそれらの間でメッセージを渡す仕組みです。CSP 流の格言——「メモリを共有するより、メッセージを送る方を選べ」——は今も規律であって魔法ではありません。

func processOrders(orders <-chan Order) {
    for order := range orders {
        go handleOrder(order)
    }
}

channel は型付きの値を運び、select は複数の待機を多重化します。go test -race と組み合わせて使いましょう——金融コードで競合が起きているなら、それは「いずれ整合する」状態ではなく、単純に間違っています。

並行処理を書くこと自体は簡単です。正しさはテストとレビューによって初めて得られます。

Goroutines fan out (conceptual) main() go worker go worker go worker channels coordinate without shared locks (idealized)
軽量なタスクと明示的な引き渡し——これが Go のネットワークサービスの標準的な形です。

Go で HTTP サービスと gRPC を構築する

net/http だけで多くの API はまかなえます。ルーターを使えばマルチプレクシングとミドルウェアが加わります。データセンター内では gRPC + protobuf が有利です——ペイロードが小さく、コード生成があり、ストリーミングもできます。内部呼び出しが外部の JSON トラフィックをはるかに上回る場合に便利です。

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("GET /api/v1/ticker/{symbol}", handleTicker)
    mux.HandleFunc("POST /api/v1/orders", handleNewOrder)
    server := &http.Server{Addr: ":8443", Handler: mux, ReadTimeout: 5 * time.Second}
    log.Fatal(server.ListenAndServeTLS("cert.pem", "key.pem"))
}

Go のインターフェースは暗黙的です——重量級のフレームワークを使わずに、テスト内でストレージをモックできます。

Typical Go service sandwich HTTP / gRPC transport + middleware domain logic (risk checks, authz, orchestration) storage & clients (SQL, cache, message bus)
トランスポート層は薄く保ち、資金を扱うロジックはリスニングソケットなしでテストできる状態にしておきましょう。

ブロックチェーンノードと取引所バックエンドにおける Go

Geth、Cosmos/Tendermint 系のスタック、Fabric、Cockroach——チェーンとデータベースの世界では Go がいたるところに使われています。取引所を繋ぐ接続層——ゲートウェイ、リスクの事前チェック、WebSocket のファンアウト——は Go にとって自然な適用領域です。

1マイクロ秒未満を争うマッチングエンジンは、依然として C++ や Rust の領域であることが多いです。その周辺にあるものはすべて Go が担って構いません。

GaiaEx は API のエッジ層とリアルタイムフィードに Go を使っています。Hyperliquid L1 上での実行は別のレイヤーです——自分がどのレイテンシ予算を担っているのかを把握しておきましょう。

エラー処理・テスト・Go Modules

明示的な error の戻り値は冗長ですが誠実です——資金移動において、握り潰されたエラーは許されません。%w でラップして、呼び出し側が失敗の種類を分類できるようにしましょう。

go test、ベンチマーク、pprof は一級の存在です。テーブル駆動テストはケースを分かりやすく保ちます。

モジュールは go.modgo.sum でバージョンを固定します——本番環境が自分のノート PC ではない以上、再現可能なビルドが重要になります。

Go を選ぶべき場面——そして選ぶべきでない場面

向いているケース: ネットワークサービス、CLI、オペレーター、I/O が重く CPU 負荷が中程度のもの。

向いていないケース: 最低レイテンシが求められるマッチング、GC の一時停止を許さないハードリアルタイム保証、重い数値計算を伴う ML——道具は正しく選びましょう。

Go が勝つのは、出荷と運用が理論上のピーク QPS と同じくらい重要な場面です——それはトレーディングを取り巻くインフラの大半に当たります。