Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 16701] ファイルの概要

このコミットは、Go言語の標準ライブラリ net/rpc パッケージ内の server.go ファイルから不要なコードを削除するものです。具体的には、Server 型の register メソッドにおける s.method マップの初期化が冗長であったため、その行が削除されました。

コミット

commit 456f6df96a9f5ece7c064163c3d2e2d0b487714e
Author: ChaiShushan <chaishushan@gmail.com>
Date:   Tue Jul 2 17:29:21 2013 -0700

    net/rpc: remove unnecessary code
    
    Fixes #5760.
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/10871043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/456f6df96a9f5ece7c064163c3d2e2d0b487714e

元コミット内容

net/rpc: remove unnecessary code

このコミットは、net/rpc パッケージから不要なコードを削除することを目的としています。コミットメッセージには Fixes #5760 と記載されていますが、公開されているGoのIssueトラッカーではこの番号のIssueは見つかりませんでした。これは、内部的なIssue番号であるか、あるいは記載ミスである可能性があります。

変更の背景

この変更の背景には、コードの冗長性の排除と効率化があります。net/rpc パッケージの Server 構造体には、登録されたサービスメソッドを管理するための method というマップフィールドがあります。このマップは、サービスが登録される際に初期化され、適切なメソッドが格納されます。

コミット前のコードでは、register メソッド内で s.method = make(map[string]*methodType) という行で一度マップが初期化された後、すぐに次の行で s.method = suitableMethods(s.typ, true) という行で suitableMethods 関数によって返される新しいマップで上書きされていました。

これは、最初の make による初期化が完全に無意味であり、メモリの割り当てと初期化という余分な処理を発生させていたことを意味します。この冗長な処理を削除することで、コードの可読性が向上し、わずかながらパフォーマンスの改善にも繋がります。

前提知識の解説

Go言語の net/rpc パッケージ

net/rpc パッケージは、Go言語でRPC(Remote Procedure Call)サービスを構築するための標準ライブラリです。RPCは、異なるアドレス空間にあるプロセス間でプロシージャ(関数やメソッド)を呼び出すための技術であり、分散システムにおいて非常に重要な役割を果たします。

net/rpc パッケージを使用すると、開発者はネットワーク越しにGoの関数やメソッドを呼び出すことができます。主なコンポーネントは以下の通りです。

  • Server: RPCリクエストを受け付け、登録されたサービスメソッドを実行するエンティティです。
  • Client: RPCリクエストを送信し、サーバーからレスポンスを受け取るエンティティです。
  • Service: サーバーに登録されるGoの構造体であり、公開したいメソッドを含みます。これらのメソッドは特定のシグネチャ(func (t *T) Method(argType T1, replyType *T2) error)に従う必要があります。

Go言語の map

map はGo言語におけるハッシュテーブル(連想配列)の実装です。キーと値のペアを格納し、キーを使って値にアクセスします。map を使用する前に、make 関数を使って初期化する必要があります。

例:

m := make(map[string]int) // stringをキー、intを値とするマップを初期化

マップが初期化されていない(nil)状態でアクセスしようとすると、ランタイムパニックが発生します。しかし、このコミットで削除された行のように、make で初期化した直後に別の値で上書きする場合、最初の make は冗長となります。

suitableMethods 関数

suitableMethods 関数は、net/rpc パッケージの内部関数であり、指定された型(reflect.Type)からRPCサービスとして公開するのに適したメソッドを抽出し、それらを map[string]*methodType の形式で返します。この関数は、メソッドのシグネチャ(引数の数と型、戻り値の型)がRPCの要件を満たしているかを確認します。

技術的詳細

このコミットは、src/pkg/net/rpc/server.go ファイル内の Server 構造体の register メソッドに対する変更です。

register メソッドは、RPCサーバーに新しいサービスを登録する際に呼び出されます。このメソッドの目的は、与えられたレシーバー(サービスの実体)からRPC呼び出しに適したメソッドを抽出し、それらを Server 構造体内の s.method マップに格納することです。

変更前のコードスニペットは以下のようになっていました。

func (server *Server) register(rcvr interface{}, name string, useName bool) error {
    // ... (前略) ...
    s.name = sname
    s.method = make(map[string]*methodType) // 削除された行
    // Install the methods
    s.method = suitableMethods(s.typ, true) // この行で上書きされる
    // ... (後略) ...
}

ここで注目すべきは、s.method = make(map[string]*methodType) の直後に s.method = suitableMethods(s.typ, true) が続いている点です。

  1. s.method = make(map[string]*methodType): この行は、s.method フィールドに新しい空のマップを割り当てます。
  2. s.method = suitableMethods(s.typ, true): この行は、suitableMethods 関数が返す新しいマップを s.method に割り当てます。

つまり、最初の make によって割り当てられたマップは、次の行で即座に新しいマップで上書きされていました。これにより、最初の make は不要なメモリ割り当てと初期化のオーバーヘッドを発生させていました。

このコミットでは、この冗長な s.method = make(map[string]*methodType) の行が削除されました。これにより、コードはより簡潔になり、無駄な処理がなくなりました。機能的な影響は全くなく、RPCサービスの登録ロジックは以前と変わらず正しく動作します。

コアとなるコードの変更箇所

--- a/src/pkg/net/rpc/server.go
+++ b/src/pkg/net/rpc/server.go
@@ -258,7 +258,6 +258,6 @@ func (server *Server) register(rcvr interface{}, name string, useName bool) erro
 	return errors.New("rpc: service already defined: " + sname)
    }
    s.name = sname
-   s.method = make(map[string]*methodType)
 
    // Install the methods
    s.method = suitableMethods(s.typ, true)

コアとなるコードの解説

変更は src/pkg/net/rpc/server.go ファイルの register 関数内で行われています。

register 関数は、RPCサーバーにサービスを登録する際に呼び出される重要な関数です。この関数は、rcvr (レシーバー、つまりサービスの実体となるGoの構造体) と name (サービス名) を引数として受け取ります。

削除された行 s.method = make(map[string]*methodType) は、s (現在の Server インスタンスに登録されるサービスを表す service 構造体) の method フィールドを初期化していました。しかし、その直後の行 s.method = suitableMethods(s.typ, true) で、s.typ (サービスの型情報) から適切なメソッドを抽出し、その結果として得られるマップを s.method に再代入していました。

この再代入により、make で作成された空のマップはすぐに捨てられ、suitableMethods が返すマップが代わりに使われることになります。したがって、最初の make は完全に無駄な処理であり、削除しても機能に影響はありません。この変更は、コードのクリーンアップと効率化を目的としています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のソースコード
  • Go言語の net/rpc パッケージに関する一般的な解説記事
  • Go言語の map 型に関する解説記事
  • Go言語の reflect パッケージに関する解説記事
  • GitHubのコミットページ: https://github.com/golang/go/commit/456f6df96a9f5ece7c064163c3d2e2d0b487714e
  • Go CL (Change List) 10871043: https://golang.org/cl/10871043 (これは古いGo CLのURL形式であり、現在はGoのコードレビューシステムGerritにリダイレクトされる可能性があります。)
  • Go Issue #5760 (ただし、公開されているGoのIssueトラッカーでは見つからなかったため、内部的なものか記載ミスである可能性が高い)