2017-03-08 17 views
1

私は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をアンマーシャリングすることを避けるためにしたい...

+0

というようになりますが、これはゴブのように見えますが、ゴブの形式には限界があります。整数へのポインタが決して無限にならない不変式を持っているなら、それはなぜポインタですか? – JimB

+0

@JimB構造体はJSONを解析した結果であり、フィールドが存在するかどうかを知る必要があります。 GoのJSON解析ライブラリは、この目的のためにポインタを使用します。 – user7678959

答えて

1

この動作は、2013年に戻って上げ欠陥に従ってゴブプロトコルの制限である - https://github.com/golang/go/issues/4609

を見ますゴブはポインタを送信せず、ポインタは逆参照され、値が渡されることに注意してください。したがって、p.Ptrが& p.Oneに設定されていると、q.Ptr!= & q.One

関連する問題