duanbing6955 2017-03-08 15:14
浏览 77
已采纳

golang gob将指针从0转换为nil指针

I'm trying to use go's net/rpc package to send data structures. The data structure includes a pointer to uint64. The pointer is never nil, but the value may be 0. I'm finding that when the value is 0, the receiver sees a nil pointer. When the value is non-0, the receives sees a non-nil pointer that points to a proper value. This is problematic, because it means that the RPC is breaking an invariant of my data structure: the pointer will never be nil.

I have a go playground that demonstrates this behavior here: 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
", 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
", q)

    p.Ptr = &p.One
    fmt.Printf("p1: %s
", 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
", q)
}

The output from this code is:

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)}

So when Ptr points to a 0, it becomes nil on the receiver side. When Ptr points to 1, it is passed through normally.

Is this a bug? Is there a way around this problem? I want to avoid having to unmarshall my detastructure on the receiver side to fix all the unexpected nil pointers...

  • 写回答

1条回答 默认 最新

  • doutan5337 2017-03-08 23:54
    关注

    This behaviour is a limitation of the gob protocol according the defect raised back in 2013 - see https://github.com/golang/go/issues/4609

    Bear in mind that gob doesn't send pointers, the pointer is dereferenced and the value is passed. As such when the p.Ptr is set to &p.One, you'll find that q.Ptr != &q.One

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘