Go で作成しているアプリケーションのさまざまなモジュールに渡そうとしている接続へのホスト名のマップがあります。
var conns_ map[string]net.Conn // tcp connections per node
メインの server.go ファイルで、ネットワーク内の他のサーバーにダイヤルし、接続を次のマップに保存します。
conn, err := net.Dial("tcp", address)
conns_[hostname] = conn
次に、このマップを他のモジュールに送信して、接続を再利用したいと考えています。学習者モジュールに送信する方法の例を次に示します。
go learner.ListenForNotifies(conns_, selfname_)
学習者モジュールでは、マップを取得し、マップに含まれる各接続で gob.Decoder の使用を試みます。
func ListenForNotifies(conns map[string]net.Conn, selfname string) {
for hostname, conn := range conns {
go listen(hostname, conn, lChan)
}
// etc.
}
そしてリッスン機能内:
func listen(hostname string, conn net.Conn, lChan chan string) {
decoder := gob.NewDecoder(conn)
proposal := &utils.Proposal{}
err := decoder.Decode(proposal)
// etc.
}
問題は、decoder.Decode(proposal) をここで呼び出すと、パニックが発生することです。
panic: runtime error: invalid memory address or nil pointer dereference
私はこの同じエンコード/デコード コードを他の場所で問題なく使用しています。唯一の違いは、同じ関数内で新しい接続を確立した直後にデコードを呼び出すのではなく、接続を再利用しようとしていることです。私はこれを何時間も機能させようとしてきました。参照によって物事を渡したり、map[string]interface{} を使用したり、あらゆる種類の運が悪いです。Gob.decode は、基になる net.Conn オブジェクトで何かがエンコードされるまでブロックする必要がありますよね? この時点で、 net.Conn オブジェクトが何らかの形で無効化されているとしか思えません。
接続オブジェクトを渡す方法に何か問題がありますか? net.Conn は非常に単純なオブジェクトであり、値渡しに適していると読みましたが、何かが欠けているに違いありません。type interface{} を使用して参照渡ししようとすると、次のようなエラーが発生しました。
interface {} does not implement net.Conn (missing Close method)
gob.Decode を誤用している場合、net.Conn オブジェクトをマップに配置する際に問題がある場合、または問題がまったく別のものである場合、接続オブジェクトの何が問題なのかを突き止めようとしています。 .
何か案は?
編集: 完全なパニック トレースバックは以下のとおりです。
goroutine 16 [running]:
runtime.panic(0x527040, 0x6afe68)
/usr/local/go/src/pkg/runtime/panic.c:266 +0xb6
bufio.(*Reader).fill(0xc21004a180)
/usr/local/go/src/pkg/bufio/bufio.go:91 +0x10a
bufio.(*Reader).Read(0xc21004a180, 0xc21000aa30, 0x1, 0x9, 0x1, ...)
/usr/local/go/src/pkg/bufio/bufio.go:159 +0x1a4
io.ReadAtLeast(0x7f2e22e8a360, 0xc21004a180, 0xc21000aa30, 0x1, 0x9, ...)
/usr/local/go/src/pkg/io/io.go:288 +0xf6
io.ReadFull(0x7f2e22e8a360, 0xc21004a180, 0xc21000aa30, 0x1, 0x9, ...)
/usr/local/go/src/pkg/io/io.go:306 +0x71
encoding/gob.decodeUintReader(0x7f2e22e8a360, 0xc21004a180, 0xc21000aa30, 0x9, 0x9, ...)
/usr/local/go/src/pkg/encoding/gob/decode.go:66 +0x98
encoding/gob.(*Decoder).recvMessage(0xc210069000, 0x0)
/usr/local/go/src/pkg/encoding/gob/decoder.go:73 +0x57
encoding/gob.(*Decoder).decodeTypeSequence(0xc210069000, 0xc210045f00, 0x160)
/usr/local/go/src/pkg/encoding/gob/decoder.go:159 +0x49
encoding/gob.(*Decoder).DecodeValue(0xc210069000, 0x4ea300, 0xc210045f60, 0x160, 0x0, ...)
/usr/local/go/src/pkg/encoding/gob/decoder.go:223 +0x12e
encoding/gob.(*Decoder).Decode(0xc210069000, 0x4ea300, 0xc210045f60, 0xb, 0x0)
/usr/local/go/src/pkg/encoding/gob/decoder.go:202 +0x1c5
group10/lab5/learner.listen(0x565f90, 0x12, 0x0, 0x0, 0xc21004a120)
/home/dev/go/src/learner/learner.go:51 +0x163
created by group10/lab5/learner.ListenForNotifies
/home/dev/go/src/learner/learner.go:26 +0x18a
更新: 問題が見つかりました! fmt.Println(conn) だけでより多くの情報を取得できることに気づかず、conn が nil であることがわかり、それがパニックを引き起こしました。お手数をおかけいたしますが、よろしくお願いいたします。