سؤال

I have a map of hostnames to connections that I am trying to pass around to different modules for an application that I am writing in Go.

var conns_ map[string]net.Conn // tcp connections per node

In the main server.go file, I dial the other servers in my network and save the connections to this map:

conn, err := net.Dial("tcp", address)
conns_[hostname] = conn

Then I want to send this map to other modules to re-use the connections. Here is an example for how I send it to the learner module:

go learner.ListenForNotifies(conns_, selfname_)

In the learner module I take the map and start trying to use a gob.Decoder on each connection that it contains:

func ListenForNotifies(conns map[string]net.Conn, selfname string) {
    for hostname, conn := range conns {
        go listen(hostname, conn, lChan)
    }
    // etc.
}

And within the listen function:

func listen(hostname string, conn net.Conn, lChan chan string) {
    decoder := gob.NewDecoder(conn)
    proposal := &utils.Proposal{}
    err := decoder.Decode(proposal)
    // etc.
}

The problem is that when I call decoder.Decode(proposal) here, a panic happens:

panic: runtime error: invalid memory address or nil pointer dereference

I use this same encode/decode code elsewhere without problems, and the only difference is that I'm trying to re-use a connection instead of calling decode immediately after establishing a new one within the same function. I've been trying to make this work for hours, trying to pass things by reference, using map[string]interface{}, and all sorts of things without luck. Gob.decode should block until something is encoded on the underlying net.Conn object, right? I can only guess that the net.Conn object has gotten invalidated somehow by this point.

Am I doing something wrong with how I am passing around connection objects? I read that a net.Conn was a very simple object that was fine to pass by value, but I must be missing something. When attempting to pass it by reference using type interface{}, I got errors like:

interface {} does not implement net.Conn (missing Close method)

I'm at a loss now, trying to figure out what could be wrong with the connection objects, if I'm misusing gob.Decode, there's an issue with putting net.Conn objects into maps, or if the problem is something completely different.

Any ideas?

edit: The full panic traceback is below:

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

Update: The problem was found! I didn't realize that you could just fmt.Println(conn) to get more information out of it, and discovered that the conn was nil, and that caused the panic. Sorry for the trouble, and thanks for your help.

هل كانت مفيدة؟

المحلول

Update: The problem was found! I didn't realize that you could just fmt.Println(conn) to get more information out of it, and discovered that the conn was nil, and that caused the panic. Sorry for the trouble, and thanks for your help.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top