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

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

このコミットは、Go言語の標準ライブラリ net/rpc パッケージにおける Service.Register メソッドのドキュメントの不整合を修正するものです。具体的には、Service.Register の第一引数に関する古い、もはや真実ではない条件(ポインタである必要があるという記述)を修正しています。

コミット

net/rpc: Service.Register のドキュメントにおける不整合を修正 第一引数がポインタでなければならないという、古い、もはや真実ではない条件を誤って主張していた。 Fixes #6697

R=golang-codereviews, bradfitz CC=golang-codereviews https://golang.org/cl/53480043

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

https://github.com/golang/go/commit/f8225bdb350f5c7d249f8ed090cf7543901612fa

元コミット内容

net/rpc: fix inconsistency in documentation of Service.Register
Falsely claimed an old, no longer true condition that the first argument
must be a pointer.
Fixes #6697

R=golang-codereviews, bradfitz
CC=golang-codereviews
https://golang.org/cl/53480043

変更の背景

Go言語の net/rpc パッケージは、Goプログラム間でRPC(Remote Procedure Call)を実装するためのメカニズムを提供します。このパッケージでは、サービスを公開するために server.Register メソッドを使用します。このメソッドは、レシーバ(サービスを提供するオブジェクト)のメソッドをRPCとして利用可能にする役割を担います。

過去のある時点では、Service.Register メソッドのドキュメントには、「第一引数(レシーバ)はポインタでなければならない」という記述が含まれていました。しかし、Go言語の進化や net/rpc パッケージの内部実装の変更により、この条件はもはや必須ではなくなっていました。ドキュメントが実際の動作と乖離していると、開発者は誤解し、不必要な制約に従おうとしたり、混乱したりする可能性があります。

このコミットは、このようなドキュメントと実装の間の不整合を解消し、開発者が net/rpc をより正確に理解し、適切に使用できるようにすることを目的としています。Fixes #6697 という記述から、この問題がGoのIssueトラッカーで報告され、その解決のためにこのコミットが作成されたことがわかります。

前提知識の解説

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

net/rpc パッケージは、Goプログラムがネットワーク経由で他のGoプログラムの関数を呼び出すことを可能にするためのものです。これは、クライアント/サーバーモデルで動作し、サーバーはサービスを登録し、クライアントはそのサービスに接続してメソッドを呼び出します。

主要な概念は以下の通りです。

  • サービス (Service): RPCとして公開されるメソッドを持つGoの構造体または型。
  • レシーバ (Receiver): サービスを提供する具体的なインスタンス。Service.Register メソッドに渡されるオブジェクトです。
  • メソッドの公開条件: net/rpc で公開されるメソッドには特定のシグネチャが必要です。
    • メソッドはエクスポートされている(大文字で始まる)こと。
    • 2つの引数を持つこと。
    • 1つの戻り値(error型)を持つこと。
    • 最初の引数はリクエスト、2番目の引数はレスポンスとして扱われます。
  • Service.Register: サーバーにサービスを登録するためのメソッド。このメソッドを呼び出すことで、レシーバの適切なメソッドがRPCとして利用可能になります。

Go言語におけるポインタと値レシーバ

Go言語では、メソッドを定義する際にレシーバを「値レシーバ」または「ポインタレシーバ」として指定できます。

  • 値レシーバ: func (s MyStruct) MyMethod() {} のように定義されます。メソッド内でレシーバのフィールドを変更しても、元の値には影響しません。これはレシーバのコピーに対して操作が行われるためです。
  • ポインタレシーバ: func (s *MyStruct) MyMethod() {} のように定義されます。メソッド内でレシーバのフィールドを変更すると、元の値も変更されます。これはレシーバのポインタに対して操作が行われるためです。

net/rpc の文脈では、サービスメソッドがレシーバの状態を変更する必要がある場合や、大きな構造体をコピーするオーバーヘッドを避ける場合には、ポインタレシーバが一般的に使用されます。しかし、Service.Register 自体がレシーバの型をどのように扱うかという点では、必ずしもポインタである必要がない場合があります。このコミットは、まさにその「ポインタである必要がない」という事実をドキュメントに反映させるものです。

技術的詳細

このコミットの技術的な変更は、src/pkg/net/rpc/server.go ファイル内のコメント、特に Service.Register メソッドのドキュメント文字列の修正に限定されています。コードの動作自体を変更するものではなく、あくまでドキュメントの正確性を向上させるものです。

変更前と変更後のドキュメントの比較は以下の通りです。

変更前:

// Register publishes in the server the set of methods of the
// receiver value that satisfy the following conditions:
//	- exported method
//	- two arguments, both pointers to exported structs
//	- one return value, of type error
// It returns an error if the receiver is not an exported type or has
// no methods or unsuitable methods. It also logs the error using package log.
// The client accesses each method using a string of the form "Type.Method",
// where Type is the receiver's concrete type.
func (server *Server) Register(rcvr interface{}) error {

変更後:

// Register publishes in the server the set of methods of the
// receiver value that satisfy the following conditions:
//	- exported method
//	- two arguments, both of exported type
//	- the second argument is a pointer
//	- one return value, of type error
// It returns an error if the receiver is not an exported type or has
// no suitable methods. It also logs the error using package log.
// The client accesses each method using a string of the form "Type.Method",
// where Type is the receiver's concrete type.
func (server *Server) Register(rcvr interface{}) error {

主要な変更点は以下の2点です。

  1. // - two arguments, both pointers to exported structs// - two arguments, both of exported type に変更されました。
    • これは、RPCメソッドの引数が「エクスポートされた構造体へのポインタ」である必要はなく、「エクスポートされた型」であればよいことを示しています。つまり、ポインタである必要がない場合や、構造体以外の型(例えば、intstringなどの基本型)も引数として使用できることを示唆しています。ただし、net/rpc のメソッド引数は通常、複雑なデータ構造を扱うために構造体が使われることが多いです。
  2. 新しい行 // - the second argument is a pointer が追加されました。
    • これは、RPCメソッドの2番目の引数(通常はレスポンスを書き込むための引数)が、引き続きポインタである必要があることを明確にしています。これは、メソッドがその引数を通じて値を「書き戻す」必要があるため、値渡しではなくポインタ渡しが必要であるという net/rpc の設計原則を反映しています。

これらの変更により、Service.Register のドキュメントは、RPCメソッドの引数に関する現在の net/rpc の要件をより正確に反映するようになりました。特に、第一引数に関する誤解を解消し、第二引数に関する重要な制約を明確にしています。

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

--- a/src/pkg/net/rpc/server.go
+++ b/src/pkg/net/rpc/server.go
@@ -217,10 +217,11 @@ func isExportedOrBuiltinType(t reflect.Type) bool {
 // Register publishes in the server the set of methods of the
 // receiver value that satisfy the following conditions:
 //	- exported method
-//	- two arguments, both pointers to exported structs
+//	- two arguments, both of exported type
+//	- the second argument is a pointer
 //	- one return value, of type error
 // It returns an error if the receiver is not an exported type or has
-// no methods or unsuitable methods. It also logs the error using package log.
+// no suitable methods. It also logs the error using package log.
 // The client accesses each method using a string of the form "Type.Method",
 // where Type is the receiver\'s concrete type.\n func (server *Server) Register(rcvr interface{}) error {

コアとなるコードの解説

このコミットは、Goの net/rpc パッケージの server.go ファイル内の Register メソッドのドキュメントコメントを修正しています。

具体的には、Register メソッドのドキュメント内で、RPCとして公開されるメソッドが満たすべき条件に関する記述が変更されています。

  1. 変更前:

    //	- two arguments, both pointers to exported structs
    

    これは、RPCメソッドの2つの引数が「エクスポートされた構造体へのポインタ」でなければならないと記述していました。

  2. 変更後:

    //	- two arguments, both of exported type
    //	- the second argument is a pointer
    

    この変更は、以下の2つの点を明確にしています。

    • RPCメソッドの2つの引数は「エクスポートされた型」であればよい。つまり、必ずしも構造体である必要はなく、また、最初の引数はポインタである必要もないことを示唆しています。
    • しかし、2番目の引数(通常はレスポンスを書き込むための引数)は「ポインタ」でなければならないという条件は維持されています。これは、GoのRPCフレームワークが、2番目の引数を通じて結果を呼び出し元に返すために、その引数がポインタである必要があるためです。

また、エラーメッセージに関する記述も微修正されています。

  • 変更前: no methods or unsuitable methods.
  • 変更後: no suitable methods. これは、より簡潔で正確な表現になっています。

この変更は、net/rpc の実際の動作に合わせてドキュメントを更新し、開発者がRPCメソッドのシグネチャに関する正しい理解を持つことを助けます。特に、第一引数がポインタである必要がないという点が明確になったことで、より柔軟なRPCメソッドの定義が可能になります。

関連リンク

  • Go言語の net/rpc パッケージのドキュメント: https://pkg.go.dev/net/rpc
  • Go言語のIssueトラッカー (Issue #6697): このコミットが修正したIssueの詳細は、Goの公式Issueトラッカーで確認できる可能性がありますが、古いIssueは直接リンクされていない場合があります。

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語の net/rpc パッケージのソースコード
  • Go言語のコミット履歴
  • Go言語におけるポインタと値レシーバに関する一般的な情報源
  • https://golang.org/cl/53480043 (Goのコードレビューシステムへのリンク)