【问题标题】:golang gob converts pointer to 0 into nil pointergolang gob 将指向 0 的指针转换为 nil 指针
【发布时间】:2017-03-08 15:14:58
【问题描述】:

我正在尝试使用 go 的 net/rpc 包来发送数据结构。数据结构包括一个指向 uint64 的指针。指针从不为零,但值可能为 0。我发现当值为 0 时,接收方会看到一个 nil 指针。当值为非 0 时,接收方会看到一个指向正确值的非零指针。这是有问题的,因为这意味着 RPC 破坏了我的数据结构的一个不变量:指针永远不会为 nil。

我有一个 go playground 在这里演示了这种行为:https://play.golang.org/p/Un3bTe5F-P

package main

import (
    "bytes"
    "encoding/gob"
    "fmt"
    "log"
)

type P struct {
    Zero, One int
    Ptr    *int
}

func main() {
    // Initialize the encoder and decoder.  Normally enc and dec would be
    // bound to network connections and the encoder and decoder would
    // run in different processes.
    var network bytes.Buffer        // Stand-in for a network connection
    enc := gob.NewEncoder(&network) // Will write to network.
    dec := gob.NewDecoder(&network) // Will read from network.
    // Encode (send) the value.
    var p P
    p.Zero = 0
    p.One = 1
    p.Ptr = &p.Zero
    fmt.Printf("p0: %s\n", p)
    err := enc.Encode(p)
    if err != nil {
        log.Fatal("encode error:", err)
    }
    // Decode (receive) the value.
    var q P
    err = dec.Decode(&q)
    if err != nil {
        log.Fatal("decode error:", err)
    }
    fmt.Printf("q0: %s\n", q)

    p.Ptr = &p.One
    fmt.Printf("p1: %s\n", p)
    err = enc.Encode(p)
    if err != nil {
        log.Fatal("encode error:", err)
    }

    err = dec.Decode(&q)
    if err != nil {
        log.Fatal("decode error:", err)
    }
    fmt.Printf("q1: %s\n", q)
}

这段代码的输出是:

p0: {%!s(int=0) %!s(int=1) %!s(*int=0x1050a780)}
q0: {%!s(int=0) %!s(int=1) %!s(*int=<nil>)}
p1: {%!s(int=0) %!s(int=1) %!s(*int=0x1050a784)}
q1: {%!s(int=0) %!s(int=1) %!s(*int=0x1050aba8)}

所以当 Ptr 指向 0 时,它在接收端变为 nil。当Ptr指向1时,正常通过。

这是一个错误吗?有没有办法解决这个问题?我想避免在接收方解组我的 detastructure 以修复所有意外的 nil 指针...

【问题讨论】:

  • 这看起来像一个错误,但它可能是 gob 格式的限制。如果你有一个指向整数的指针永远不会是 nil 的不变量,那为什么它是一个指针呢?
  • @JimB 该结构是解析JSON的结果,我需要知道一个字段是否存在。 Go 的 JSON 解析库为此使用了指针。

标签: go encoding gob


【解决方案1】:

根据 2013 年提出的缺陷,此行为是 gob 协议的限制 - 请参阅 https://github.com/golang/go/issues/4609

请记住,gob 不发送指针,指针被取消引用并且值被传递。因此,当 p.Ptr 设置为 &p.One 时,您会发现 q.Ptr != &q.One

【讨论】:

    猜你喜欢
    • 2015-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2014-07-22
    相关资源
    最近更新 更多