上記の青い文字TonyBaiをクリックして公式アカウントを購読してください!
皆さん、こんにちは。Tony Baiです。
開発者として、私たちは毎日APIと向き合っています。それらを呼び出し、設計し、時にはひどいAPI設計に頭を悩ませることもあります。優れたAPIは、熟練したガイドのように、複雑な機能の向こう側へと明確かつ効率的に私たちを導きます。一方、粗悪なAPIは、罠だらけの迷宮のように、私たちを困難に陥れる可能性があります。
では、Go言語の世界において、「良い」APIとはどのようなものでしょうか?Go言語の簡潔さ、効率性、並行安全性の哲学をどのように体現すべきでしょうか?また、機能要件を満たしつつ、開発者にとっての使いやすさと将来の互換性をどのように維持するのでしょうか?
最近、Go公式チームはModel Context Protocol (MCP) のGo SDKの設計議論を開始し、その詳細な設計草案と初期のプロトタイプコード実装を公開しました。この設計ドキュメントとコードは、私にとって、単にMCPプロトコルのGo言語実装計画に留まらず、Go公式チームによるAPI設計に関する思考と実践の「公開授業」です。それは、強力でGoらしい (Idiomatic Go) SDKを構築する際に、どのような側面でトレードオフを行う必要があるか、そしてGoの設計哲学を細部にどのように組み込むかを生々しく示しています。
今日は、この設計ドキュメントとそのプロトタイプコードに共に踏み込み、GoチームがAPI設計で追求する「Goの境地」を探ってみましょう。
API設計の「初心」:GoチームがMCP SDKに設定した目標
詳細に入る前に、Goチームがこの公式MCP SDKに設定した主要な目標(Requirements)を見てみましょう。これらの目標自体が、あらゆる高品質なGo SDKを設計する上での重要な指針となります。
1. 完全性 (Complete): MCP仕様のすべての機能を実装し、そのセマンティクスに厳密に従うこと。これはプロトコル実装としてのSDKの基本要件です。
2. Goらしいこと (Idiomatic): これが「Goの境地」の核心です。SDKはGo言語自体の特性と標準ライブラリの設計スタイルを最大限に活用し、Goエコシステム内の類似領域(例:net/http、grpc-go)で確立された慣用的な使い方を繰り返すべきです。
3. 堅牢性 (Robust): SDK自体が適切にテストされ、安定して信頼できるものでなければならず、利用者がSDKに基づいて構築したアプリケーションを容易にテストできる必要があります。
4. 将来性 (Future-proof): 設計はMCP仕様の将来的な進化を考慮し、仕様変更によってSDK APIに互換性のない破壊的な変更が生じることを可能な限り避ける必要があります。
5. 拡張性 (Extensible) と最小化 (Minimal): 前述の4つの目標を最適に達成するため、SDKのコアAPIは最小限で直交性を保つべきです。同時に、ユーザーがシンプルで明確な方法(例:インターフェース、ミドルウェア、フックなど)で拡張できるようにし、特定の要件を満たす必要があります。
これらの目標は、Goチームが「良い」Go SDKに期待するものを明確に示しています。それは、機能が完備されているだけでなく、「Goらしく書かれ、Goらしく使われ」、そして時の試練に耐えるものでなければなりません。
庖丁解牛:MCP Go SDK設計における「Goの風味」とトレードオフ
明確なAPI設計目標を設定した後、Goチームはこれらの原則を実践に移し、MCP Go SDKの具体的な構造とインターフェースの設計に着手しました。この設計ドキュメントとそのプロトタイプコードを詳細に読み解くことで、複数の重要な決定において、濃厚な「Goの風味」を明確に味わうことができ、機能の完全性、言語慣例、現在の使いやすさ、そして将来の進化性との間で彼らが行った絶妙なトレードオフを深く理解することができます。
パッケージレイアウト
SDKの全体構造において、Goチームはパッケージのレイアウトに関して顕著な選択を行いました。これは、Goエコシステムの習慣に対する深い理解と、開発者体験を優先する彼らの姿勢を直接的に示しています。他の言語のMCP SDKがクライアント、サーバー、トランスポート層などの機能をそれぞれ独立したパッケージに細かく分割する可能性があるのに対し、GoチームはSDKのコアユーザーインターフェースを単一のmcpパッケージ内に集中させることを提案しました。
このアプローチは、Go標準ライブラリのnet/http、net/rpc、そしてコミュニティで広く採用されているgoogle.golang.org/grpcなどのコアパッケージの組織方法と高い一貫性を保っています。Go開発者にとって、これは認知負荷の低減を意味します。MCP機能を使用する必要がある場合、ほぼすべてのコアAPIが同じmcpパッケージの下で見つかるため、APIの発見性が大幅に向上します。同時に、集中化されたパッケージ構造は、集約されたパッケージドキュメントの生成にも有利であり、IDEでのよりスムーズなコード補完とナビゲーション体験を提供します。
さらに深い考慮事項は、SDKの長期的な安定性と将来への適応性です。機能を複数の粒度の細かいパッケージに過度に分割すると、将来のMCP仕様のわずかな調整でも、連鎖的なパッケージ構造の変更や複雑なパッケージ間依存性の問題を引き起こす可能性があります。一方、単一のコアパッケージ設計は、これらの変化をよりよく吸収し、ユーザーコードへの影響を軽減できます。もちろん、JSON Schemaのような、MCPのコアロジックに直接関係しないが、SDKユーザーが必要とする可能性のある補助機能は、個別のサブパッケージ(例:jsonschema/)に適切に計画され、関心の分離が図られています。この戦略は、一部の極端な「モジュール化」を追求する開発者にとってはコアパッケージがやや「肥大化」していると感じられるかもしれませんが、Goチームはここでユーザー発見性、ドキュメントの明確さ、および長期的な進化の安定性を明確にトレードオフし、それらをより高い優先順位に置いています。
JSON-RPCとトランスポート層の抽象化 (Transports)
MCPプロトコルの核心は、JSON-RPCを介してクライアントとサーバー間でメッセージを交換することであり、その下層にはstdio、ストリーミング可能なHTTP、SSEなど、多様なトランスポート方式が存在します。これらの異なる形態のトランスポート方式に対して、統一的かつ柔軟な抽象化層を設計することは、SDK設計者にとって大きな課題です。ここでGoチームは、インターフェース設計の芸術における彼らの熟練した腕前を再び示しました。
transport.goでは、彼らは非常に低レベルなTransportインターフェースを定義しています: // A Transport is used to create a bidirectional connection between MCP client // and server. type Transport interface { Connect(ctx context.Context) (Stream, error) }
その核となる責務は、Connectメソッドを介して論理接続を確立し、Streamインターフェースインスタンスを返すことだけです。このStreamインターフェースはさらに基本的で、golang.org/x/tools/internal/jsonrpc2_v2の設計から着想を得ています:
// A Stream is a bidirectional jsonrpc2 Stream. type Stream interface { jsonrpc2.Reader jsonrpc2.Writer io.Closer }
これは読み書きとクローズの機能を組み合わせたものです。この設計は「Goの風味」に満ちています。インターフェースは小さく洗練されており、最も根本的な抽象化のみを公開し、Goの「小さなインターフェースを定義し、大きな価値を実現する」という理念を完璧に体現しています。
具体的に見ると、Streamインターフェースがio.Closerを埋め込んでいるため、標準ライブラリの慣例に自然に従い、Goのリソース管理パターンにシームレスに統合できます。さらに重要なのは、Connectメソッドのシグネチャが(ctx context.Context, ...params) (...results, error)の形式に厳密に従っていることです。context.Contextが最初の引数として、操作のタイムアウトとキャンセルを優雅に処理するために使用されます。そしてerrorが最後の戻り値として、明確かつ一貫したエラー情報を伝達するために使用されます。これらはGoのI/Oとネットワークプログラミングにおける不動の標準パターンです。この低レベルインターフェースの簡潔さは、内部JSON-RPC実装の複雑な詳細(例:mcp/internal/jsonrpc2_v2の使用)を巧みに隠すだけでなく、ユーザーがカスタムのトランスポート方式(設計ドキュメントで言及されているInMemoryTransportやLoggingTransportなど)を実装する際に、非常に大きな利便性を提供します。
例えば、NewCommandTransportは、子プロセスstdioを介して通信するクライアントトランスポートを作成するために使用されます:
// NewCommandTransport returns a [CommandTransport] that runs the given command // and communicates with it over stdin/stdout. func NewCommandTransport(cmd *exec.Cmd) *CommandTransport { /* ... */ }
得られたCommandTransportのConnectメソッドはコマンドを起動し、そのstdin/stdoutに接続します。このような明確な責任分担とGo標準パターンへの準拠により、トランスポート層全体が理解しやすく、拡張しやすくなっています。
クライアントおよびサーバーAPI (Clients & Servers)
クライアントおよびサーバーのコアオブジェクトのAPI設計においても、GoチームはGoの並行処理モデルに対する深い理解を組み込んでいます。設計ドキュメントでは、Client/ServerインスタンスとClientSession/ServerSessionの概念を明確に区別しており、これはclient.goとserver.goに反映されています。ClientまたはServerインスタンスは、複数の並行接続(すなわち、複数のセッション)を処理できます。これは、私たちが慣れ親しんでいる標準ライブラリのhttp.Clientが複数のHTTPリクエストを発行でき、http.Serverが同時に複数のクライアントにサービスを提供できるパターンと全く同じです。
// In client.go type Client struct { // ... mu sync.Mutex sessions []*ClientSession // ... } func NewClient(name, version string, opts *ClientOptions) *Client { /* ... */ } func (c *Client) Connect(ctx context.Context, t Transport) (*ClientSession, error) { /* ... */ } // In server.go type Server struct { // ... mu sync.Mutex sessions []*ServerSession // ... } func NewServer(name, version string, opts *ServerOptions) *Server { /* ... */ } func (s *Server) Connect(ctx context.Context, t Transport) (*ServerSession, error) { /* ... */ }
このN:1(複数のセッションが1つのClient/Serverインスタンスに対応する)設計は、Go言語の強力な並行処理能力を自然に活用し、sync.Mutexを介して共有状態を保護しています。ClientとServer自体がステートフルであることを考慮すると(例えば、Clientは追跡しているルートリソースを動的に追加または削除でき、Serverは提供するツールを動的に追加または削除できます)、これらのコアインスタンスの状態が変化した際には、設計により、接続されているすべてのピア(すなわち、各セッション)が適切な通知を受け取り、状態の一貫性が維持されるようになっています。
設定方法に関して、GoチームはClientとServerの作成に独立したClientOptionsとServerOptions構造体の使用を選択しました。例えば:
// In client.go type ClientOptions struct { CreateMessageHandler func(context.Context, *ClientSession, *CreateMessageParams) (*CreateMessageResult, error) ToolListChangedHandler func(context.Context, *ClientSession, *ToolListChangedParams) // ... other handlers } // In server.go type ServerOptions struct { Instructions string InitializedHandler func(context.Context, *ServerSession, *InitializedParams) // ... other handlers and fields like PageSize, LoggerName, LogInterval }
これは、コミュニティのいくつかのライブラリ(設計ドキュメントで比較対象として挙げられているmcp-goを含む)のように可変引数オプション (variadic options) パターンを採用するのとは異なります。彼らは、設定項目が多く、ロジックが複雑な場合、明示的な構造体オプションの方が可読性に優れており、パッケージの公開ドキュメントも整理しやすくなると考えています。これは、APIの簡潔性(可変引数の方が短い場合もある)と明確性および長期的な保守性の間でなされた、典型的な、そして学ぶべきトレードオフです。
プロトコルタイプとJSONスキーマ
MCPプロトコルのメッセージボディはJSON Schemaに基づいて定義されています。Go SDKはこれらのスキーマをGoの構造体にマッピングする必要があります。設計ドキュメントでは、プロトコルタイプはMCP仕様のJSONスキーマから生成され、APIユーザーが必要としない限り、mcpパッケージ内ではこれらのタイプはエクスポートされないと述べられています。
content.goのContentタイプを例にとると:
// Content is the wire format for content. // It represents the protocol types TextContent, ImageContent, AudioContent // and EmbeddedResource. type Content struct { Type string `json:"type"` Text string `json:"text,omitempty"` MIMEType string `json:"mimeType,omitempty"` Data []byte `json:"data,omitempty"` Resource *ResourceContents `json:"resource,omitempty"` Annotations *Annotations `json:"annotations,omitempty"` } func (c *Content) UnmarshalJSON(data []byte) error { // ... custom unmarshaling logic to validate Type field ... } func NewTextContent(text string) *Content { return &Content{Type: "text", Text: text} } // ... other constructors like NewImageContent, NewAudioContent ...
ここには注目すべきいくつかの「Goらしい」設計があります:
- 明確な構造体定義:JSON構造に直接マッピングし、jsonstructタグを使用してシリアライゼーション動作を制御します。
- コンストラクタ関数:NewXXXContentのようなヘルパー関数を提供し、特定の種類のContentインスタンスを作成し、Typeフィールドが正しく設定されることを保証し、使いやすさと安全性を向上させます。
- カスタムJSON処理:ContentタイプはUnmarshalJSONメソッドを実装しており、デシリアライズ時にTypeフィールドを検証して、それがプロトコルで定義された有効なタイプであることを保証します。ResourceContentsに関しては、Blobフィールドがnilである場合と空のスライスである場合との微妙な違いを処理するためにMarshalJSONさえ実装しています(Go 1.24以前のomitzero動作との互換性のため)。必要に応じてエンコード/デコードプロセスに介入してデータの正確性を保証するこの方法は、Goの型システムの能力の表れです。
- json.RawMessageの使用:設計ドキュメントでは、ユーザーが提供するデータについて、SDKはjson.RawMessageを使用すると述べています。これにより、Marshal/Unmarshalの責務をクライアントまたはサーバーのビジネスロジックに委譲できます。これは遅延解析戦略であり、パフォーマンスを向上させ、柔軟性を高めます。
さらに、jsonschema/サブパッケージは、Goタイプからのスキーマ推論 (infer.go) と検証 (validate.go) を含む完全なJSON Schema実装を提供します。jsonschema/generate.go(ビルド時には無視される)は、リモートのMCP JSON Schema URLからprotocol.go内のGoタイプ定義を生成する方法を示しており、コード生成のエンジニアリング実践を体現しています。
RPCメソッドシグネチャ
MCP仕様で定義されている具体的なRPCメソッドについて、GoチームはSDK内のシグネチャ設計において、一貫性と後方互換性への執拗な追求を際立たせています。これらのメソッドはすべて、func (s *SessionType) MethodName(ctx context.Context, params *XXXParams) (*XXXResult, error)のパターンに厳密に従っています。例えば、client.goでは:
// ListPrompts lists prompts that are currently available on the server. func (c *ClientSession) ListPrompts(ctx context.Context, params *ListPromptsParams) (*ListPromptsResult, error) { return standardCall[ListPromptsResult](ctx, c.conn, methodListPrompts, params) }
ここで、context.Contextが最初の引数、errorが最後の戻り値、そして引数 (*ListPromptsParams) と結果 (*ListPromptsResult) は共にポインタ型を使用しています。これらはGo API設計の「黄金律」であり、インターフェーススタイルの統一とGoエコシステムとのシームレスな統合を保証します。
唯一の例外はClientSession.CallToolメソッドです:
// CallTool calls the tool with the given name and arguments. // Pass a [CallToolOptions] to provide additional request fields. func (c *ClientSession) CallTool(ctx context.Context, name string, args map[string]any, opts *CallToolOptions) (*CallToolResult, error) { /* ... */ }
これは、ユーザーがツールを直接呼び出す際の利便性を高めるために、ツール名文字列とmap[string]any{}型の具体的な引数、そしてオプションの*CallToolOptionsを受け入れます。事前にCallToolParams構造体をカプセル化することを要求するのではなく、厳密なパターン順守と特定のシナリオでの使いやすさの間でなされた実用的な調整です。
設計ドキュメントで特に称賛に値する詳細は、後方互換性への綿密な配慮です。チームは明確に述べています:「呼び出し元が新しいパラメータを渡す必要がある仕様変更は、後方互換性がないと見なします。したがって、現在必須ではないXXXParamsパラメータには、常にnilを渡すことができます。」これは、将来MCP仕様が特定のメソッドに新しいオプションパラメータを追加した場合でも(これらのパラメータは対応するXXXParams構造体に追加されます)、既存のnilをパラメータとして渡す呼び出しコードは変更不要で、正常に動作し続けることを意味します。このようなAPI進化への先見の明は、Goチームの互換性へのコミットメントに対する高い重視と豊富な経験を十分に示しています。完全なJSON-RPCリクエストオブジェクトを直接公開しない理由については、チームの考慮事項として、ビジネスロジックとは無関係な下位プロトコルの詳細(リクエストIDなど)を可能な限り隠蔽し、メソッド名はGoメソッド自体から暗黙的に示されるため、パラメータに冗長に含める必要がなく、APIの純粋性を保つことが挙げられています。
エラー処理 (Errors) とキャンセル (Cancellation)
エラー処理と操作キャンセルという2つの重要なメカニズムにおいて、SDKの設計は透明性を追求し、Go言語の核となる理念と高い一貫性を保っています。ツールハンドラのビジネスロジックエラーを除き、すべてのプロトコルレベルのエラーは標準のGoerror型として透過的に処理されます。例えば、サーバー側の機能ハンドラで発生したエラーは、ClientSessionの対応する呼び出しからエラーとして伝播され、逆もまた然りで、エラー処理パスが明確かつ統一されています。
上位のコードがエラーの具体的な性質をより正確に理解できるよう、設計ドキュメントではプロトコル層のエラーがJSONRPCError型(protocol.goで自動生成される定義)をラップし、基盤となるJSON-RPCエラーコードを公開して、ターゲットを絞った処理を容易にすると述べています。
// (Generated in protocol.go, but conceptually similar to design doc) type JSONRPCError struct { Code int64 `json:"code"` Message string `json:"message"` Data json.RawMessage `json:"data,omitempty"` }
一方、操作のキャンセルについては、Go標準のcontext.Contextメカニズムに完全に依存し、シームレスに統合されています。transport.goのcall関数では、次のようなロジックが見られます:
// ... (inside call function) case ctx.Err() != nil: // Notify the peer of cancellation. err := conn.Notify(xcontext.Detach(ctx), "notifications/cancelled", &CancelledParams{ Reason: ctx.Err().Error(), RequestID: call.ID().Raw(), }) return errors.Join(ctx.Err(), err) // ...
クライアントコードがSDKメソッドに渡されたcontextをキャンセルすると、SDKはサーバーに「notifications/cancelled」通知を送信し、同時にクライアントのそのメソッド呼び出しは直ちにctx.Err()を返します。対応して、サーバー側でこのリクエストを処理する際、その保持するcontextがキャンセルされ、適切なクリーンアップや操作の中止が可能になります。この設計により、Goの並行プログラミングに慣れた開発者は、キャンセルロジックを処理する際に親近感と自然さを感じ、新しいメカニズムを学ぶ必要がありません。
拡張性:ミドルウェアパターンの採用
SDK機能のカスタマイズと拡張に対するユーザーのニーズを満たしつつ、コアAPIの簡潔性を維持するため、Goチームは拡張性メカニズムの設計においても彼らの好みを反映しました。サーバー側(server.go)とクライアント側(client.go)の両方でAddMiddlewareメソッドを提供しています:
// In shared.go (conceptual definition) type MethodHandler[S ClientSession | ServerSession] func( ctx context.Context, _ *S, method string, params any) (result any, err error) type Middleware[S ClientSession | ServerSession] func(MethodHandler[S]) MethodHandler[S] // In server.go func (s *Server) AddMiddleware(middleware ...Middleware[ServerSession]) { /* ... */ } // In client.go func (c *Client) AddMiddleware(middleware ...Middleware[ClientSession]) { /* ... */ }
これらのメソッドにより、ユーザーは特定のシグネチャに従う1つまたは複数のMiddleware関数を登録できます。これらの関数は本質的に、MCPプロトコルレベルのミドルウェアチェーンを構成し、サーバー/クライアントがリクエストを受信し、解析した後、通常のビジネス処理ロジックに入る前に順次実行されます(右から左に適用、つまり最初のミドルウェアが最初に実行されます)。mcp_test.goのtraceCallsは良い例であり、ミドルウェアを使用してリクエストとレスポンスを記録する方法を示しています。
この設計は、Go Web開発(net/httpのHandlerFuncチェーンなど)や、他の多くのGoエコシステムライブラリで広く採用されているミドルウェアパターンと一貫しています。これは、ロギング、認証、リクエスト変更などの横断的な関心事を注入するための強力で柔軟な方法を提供します。対照的に、コミュニティのmcp-go実装(設計ドキュメントで言及されている)は、24もの具体的なServer Hooksを定義しており、それぞれのHookが特定のイベントポイントに対応しています。Goチームの選択は、より汎用的でパターン化された方法で拡張ニーズを満たすことに明らかに傾倒しており、その結果、コアのServer/Sessionタイプに過度に細分化されたフックメソッドを公開することを避け、そのインターフェースの最小化と直交性を維持しています。また、HTTPレベルの認証のようなMCPプロトコル自体に直接関係しない横断的な関心事については、設計ドキュメントでは標準のHTTPミドルウェアパターンを使用することを推奨しており、関心の分離と既存の成熟したエコシステムソリューションの活用という設計思想をさらに体現しています。
これらの設計詳細を「庖丁解牛」することで、GoチームがこのMCP SDKを構築する過程で、Go言語の設計哲学、慣用的なパターン、そしてエンジニアリング実践に対する深い理解をどのように組み込むかを常に考え、プロトコル仕様の完全性を満たしつつ、Go開発者に簡潔で堅牢、使いやすく、将来性のあるプログラミングインターフェースを提供しようと努めていることが容易にわかります。
API設計の「Goの境地」:私たちが学べること
GoチームによるMCP SDKの設計プロセスは、API設計における多くの考慮事項とGo言語の独特な特質を映し出す鏡のようです。そこから、私たちはいくつかの貴重な示唆を抽出できます:
1. 「Goらしさ」は目標から始まる:完全性、慣例への適合、堅牢性、将来性、拡張性、最小化 — これらの目標が、優れたGo APIを設計するための基盤を共同で形成します。
2. 標準ライブラリが最高の教師:net/http、io、contextなどのコアライブラリの設計パターンとAPIスタイルを学び、模倣することが、「Idiomatic Go」への近道です。
3. インターフェースの力:小さく美しいインターフェースを使って振る舞いを抽象化し、コンポーネントを疎結合にすることは、Go設計哲学の真髄です。
4. contextとerrorの「一級市民」としての地位:I/O、並行処理、または失敗する可能性のある操作には、それらをAPI設計に組み込むのが標準的な方法です。
5. 後方互換性は生命線:APIは一度公開されると、変更には慎重に対処する必要があります。設計段階から将来の進化を考慮し、拡張ポイントを予約しておくことは、後からパッチを当てるよりもはるかに優雅です。
6. トレードオフの芸術:API設計はトレードオフに満ちています — 簡潔さと表現力、柔軟性と使いやすさ、現在の要件と将来の可能性…絶対的な「正解」はなく、特定の文脈における「より良い」ものがあるだけです。Goチームのパッケージレイアウトや設定方法などに関する選択は、このトレードオフをすべて反映しています。
まとめ
API設計に銀の弾丸はなく、むしろ絶え間ない実践、反省、学習の中で磨かれる職人芸のようなものです。GoチームがMCP SDKに対して行ったこれらの思考と設計決定は、Goの世界で、複雑な要求を満たしつつ、簡潔さと優雅さを失わないAPIをどのように構築するかを示す貴重な学習事例を提供してくれます。
この「Goの境地」の追求 — すなわち、コードが機能するだけでなく、Goらしく書かれ、Goらしく使われ、Goらしく感じられること — こそが、Go言語の強力な生命力と独特な魅力の源泉なのです。
この記事が、あなたの今後のAPI設計に何かインスピレーションをもたらすことを願っています。API設計に対するあなたの理解や、「良いGo API」が備えるべき特性について、コメント欄で共有していただけると幸いです。
参考資料アドレス:https://github.com/orgs/modelcontextprotocol/discussions/364
精進有道、更上層樓:Go API設計の「Goの境地」を解き放つ
今日のGo API設計事例では物足りなかったですか?Goの公式設計思想をあなたのあらゆるインターフェースに体系的に学び、取り入れたいですか?
私が最近リリースしたGo言語上級講座では、特別に「API設計:ユーザーに愛され、堅牢で信頼性の高い公開インターフェースを構築する」という講義を設けています。これは、Go API設計の5つの核心要素を深く掘り下げ、より多くの実践例と組み合わせることで、「Goを使える」から「Goを習得する」へと進む手助けをします。
以下のQRコードをスキャンして、今すぐあなたの進捗の旅を始めましょう!
お読みいただきありがとうございます!
この記事がGo API設計に関して新たな気づきを与えたなら、ぜひいいね👍、注目👀、共有🚀をお願いします。より多くの友人と共に学び、進歩しましょう!
以下のタイトルをクリックして、さらに多くの洞察を読んでください!
- GOEXPERIMENT=jsonv2を実践で試す:Goの次世代JSONライブラリの初探
- AIの新寵?MCP、A2AがJSON-RPC 2.0を好む理由を解読
- Go encoding/json/v2提案:JSON処理の新しいエンジン
- Goプロジェクトの標準構造をどのようにレイアウトするか教えます
- Go標準ライブラリcontextパッケージを徹底解説
- gRPCサービスのレスポンス設計
- 「エラーは値」、異なる実装:GoとZigのエラー処理哲学比較