1

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 であることがわかり、それがパニックを引き起こしました。お手数をおかけいたしますが、よろしくお願いいたします。

4

1 に答える 1