J'essaye d'utiliser le paquet net/rpc de go pour envoyer des structures de données. La structure de données inclut un pointeur sur uint64. Le pointeur n'est jamais nul, mais la valeur peut être 0. Je constate que lorsque la valeur est 0, le récepteur voit un pointeur nul. Lorsque la valeur est non-0, la réception voit un pointeur non-nul qui pointe vers une valeur correcte. Ceci est problématique, car cela signifie que le RPC brise un invariant de ma structure de données: le pointeur ne sera jamais nul.golang gob convertit le pointeur en 0 en pointeur nul
J'ai un terrain de jeu de go qui illustre ce comportement ici: 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)
}
La sortie de ce code est:
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)}
Ainsi, lorsque Ptr pointe vers 0, il devient nul sur la côté récepteur. Lorsque Ptr pointe à 1, il passe normalement.
Est-ce un bug? Y a-t-il un moyen de contourner ce problème? Je veux éviter d'avoir à unmarshall mon detastructure sur le côté récepteur pour fixer tous les pointeurs nil inattendus ...
qui ressemble à un bug, mais il pourrait être une limitation du format de paraison. Si vous avez un invariant, les pointeurs sur les entiers ne seront jamais nuls, alors pourquoi est-ce un pointeur? – JimB
@JimB La structure est le résultat de l'analyse JSON et j'ai besoin de savoir si un champ est présent ou non. La bibliothèque d'analyse JSON de Go utilise des pointeurs à cet effet. – user7678959