私はgoのnet/rpcパッケージを使用してデータ構造を送信しようとしています。データ構造には、uint64へのポインタが含まれています。ポインタは決してゼロではありませんが、値は0かもしれません。値が0の場合、受信側は無限のポインタを見ています。値が0以外の場合、受信者は適切な値を指す非nilポインタを参照します。これは、RPCが私のデータ構造の不変条件を破っていることを意味するため、問題になります。ポインタは決してゼロにならないでしょう。golang gobはポインタを0から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を指すときに、それは上ゼロとなり受信側。 Ptrが1を指すとき、それは通常通り通過する。
これはバグですか?この問題を回避する方法はありますか?私はすべての予想外のnilにポインタを修正するために、受信側で私のdetastructureをアンマーシャリングすることを避けるためにしたい...
というようになりますが、これはゴブのように見えますが、ゴブの形式には限界があります。整数へのポインタが決して無限にならない不変式を持っているなら、それはなぜポインタですか? – JimB
@JimB構造体はJSONを解析した結果であり、フィールドが存在するかどうかを知る必要があります。 GoのJSON解析ライブラリは、この目的のためにポインタを使用します。 – user7678959