如何将 TCP 连接对象传递给其他 Go 模块?

huangapple go评论113阅读模式
英文:

How do you pass TCP connection objects to other Go modules?

问题

我有一个主机名到连接的映射,我正在尝试将其传递给不同模块的应用程序中。以下是我在Go中编写的应用程序的一部分代码:

var conns_ map[string]net.Conn // 每个节点的TCP连接

在主服务器文件server.go中我拨号到网络中的其他服务器并将连接保存到这个映射中

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

然后我想将这个映射发送给其他模块以重用这些连接以下是将其发送给learner模块的示例

go learner.ListenForNotifies(conns_, selfname_)

在learner模块中我接收这个映射并尝试对其中包含的每个连接使用gob.Decoder

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

在listen函数中

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

问题是当我在这里调用decoder.Decode(proposal)会发生panic

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

我在其他地方使用相同的编码/解码代码没有问题唯一的区别是我尝试重用连接而不是在同一个函数中立即建立一个新连接后调用解码我已经尝试了几个小时尝试通过引用传递东西使用map[string]interface{}以及各种方法但都没有成功Gob.decode应该会阻塞直到底层net.Conn对象上有东西被编码对吗我只能猜测net.Conn对象在这一点上已经失效了

我在传递连接对象时是否做错了什么我读到net.Conn是一个非常简单的对象可以通过值传递但我肯定是漏掉了什么当我尝试使用类型interface{}进行引用传递时我会遇到错误例如

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

我现在很困惑试图弄清楚连接对象可能出了什么问题是否我在错误使用gob.Decode是否将net.Conn对象放入映射中存在问题或者问题完全不同

有什么想法吗

编辑完整的panic回溯如下

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这导致了panic对此给你带来的麻烦表示抱歉感谢你的帮助

<details>
<summary>英文:</summary>

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(&quot;tcp&quot;, 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 := &amp;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&#39;m trying to re-use a connection instead of calling decode immediately after establishing a new one within the same function. I&#39;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&#39;m at a loss now, trying to figure out what could be wrong with the connection objects, if I&#39;m misusing gob.Decode, there&#39;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&#39;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.

</details>


# 答案1
**得分**: 1

更新问题已找到我没有意识到可以使用fmt.Println(conn)来获取更多信息发现conn是空的这导致了恐慌对于给你带来的麻烦我表示抱歉并感谢你的帮助

<details>
<summary>英文:</summary>

Update: The problem was found! I didn&#39;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.

</details>



huangapple
  • 本文由 发表于 2014年3月20日 05:11:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/22518211.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定