golang gob 将指向 0 的指针转换为 nil 指针
golang gob converts pointer to 0 into nil pointer
我正在尝试使用 go 的 net/rpc 包来发送数据结构。数据结构包括指向 uint64 的指针。指针永远不会为 nil,但值可能为 0。我发现当值为 0 时,接收方会看到一个 nil 指针。当该值为非 0 时,接收方会看到一个指向正确值的非零指针。这是有问题的,因为这意味着 RPC 正在破坏我的数据结构的不变量:指针永远不会为 nil。
我有一个演示此行为的围棋游乐场: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 指针...
根据 2013 年提出的缺陷,此行为是 gob 协议的限制 - 请参阅 https://github.com/golang/go/issues/4609
请记住,gob 不发送指针,指针被解除引用并传递值。因此,当 p.Ptr 设置为 &p.One 时,您会发现 q.Ptr != &q.One
我正在尝试使用 go 的 net/rpc 包来发送数据结构。数据结构包括指向 uint64 的指针。指针永远不会为 nil,但值可能为 0。我发现当值为 0 时,接收方会看到一个 nil 指针。当该值为非 0 时,接收方会看到一个指向正确值的非零指针。这是有问题的,因为这意味着 RPC 正在破坏我的数据结构的不变量:指针永远不会为 nil。
我有一个演示此行为的围棋游乐场: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 指针...
根据 2013 年提出的缺陷,此行为是 gob 协议的限制 - 请参阅 https://github.com/golang/go/issues/4609
请记住,gob 不发送指针,指针被解除引用并传递值。因此,当 p.Ptr 设置为 &p.One 时,您会发现 q.Ptr != &q.One