]> Cypherpunks repositories - gostls13.git/commitdiff
gob: send empty but non-nil maps.
authorRob Pike <r@golang.org>
Thu, 21 Jul 2011 00:27:11 +0000 (10:27 +1000)
committerRob Pike <r@golang.org>
Thu, 21 Jul 2011 00:27:11 +0000 (10:27 +1000)
Fixes #2082.

R=golang-dev, dsymonds, r
CC=golang-dev
https://golang.org/cl/4798042

src/pkg/gob/codec_test.go
src/pkg/gob/doc.go
src/pkg/gob/encode.go

index 03fec261a1ee962196b9f374d4ad6be93b7c6122..a5fb91cda7841988382c20ebe4d5f8c525d777a0 100644 (file)
@@ -573,30 +573,32 @@ func TestEndToEnd(t *testing.T) {
        s1 := "string1"
        s2 := "string2"
        type T1 struct {
-               A, B, C int
-               M       map[string]*float64
-               N       *[3]float64
-               Strs    *[2]string
-               Int64s  *[]int64
-               RI      complex64
-               S       string
-               Y       []byte
-               T       *T2
+               A, B, C  int
+               M        map[string]*float64
+               EmptyMap map[string]int // to check that we receive a non-nil map.
+               N        *[3]float64
+               Strs     *[2]string
+               Int64s   *[]int64
+               RI       complex64
+               S        string
+               Y        []byte
+               T        *T2
        }
        pi := 3.14159
        e := 2.71828
        t1 := &T1{
-               A:      17,
-               B:      18,
-               C:      -5,
-               M:      map[string]*float64{"pi": &pi, "e": &e},
-               N:      &[3]float64{1.5, 2.5, 3.5},
-               Strs:   &[2]string{s1, s2},
-               Int64s: &[]int64{77, 89, 123412342134},
-               RI:     17 - 23i,
-               S:      "Now is the time",
-               Y:      []byte("hello, sailor"),
-               T:      &T2{"this is T2"},
+               A:        17,
+               B:        18,
+               C:        -5,
+               M:        map[string]*float64{"pi": &pi, "e": &e},
+               EmptyMap: make(map[string]int),
+               N:        &[3]float64{1.5, 2.5, 3.5},
+               Strs:     &[2]string{s1, s2},
+               Int64s:   &[]int64{77, 89, 123412342134},
+               RI:       17 - 23i,
+               S:        "Now is the time",
+               Y:        []byte("hello, sailor"),
+               T:        &T2{"this is T2"},
        }
        b := new(bytes.Buffer)
        err := NewEncoder(b).Encode(t1)
@@ -611,6 +613,13 @@ func TestEndToEnd(t *testing.T) {
        if !reflect.DeepEqual(t1, &_t1) {
                t.Errorf("encode expected %v got %v", *t1, _t1)
        }
+       // Be absolutely sure the received map is non-nil.
+       if t1.EmptyMap == nil {
+               t.Errorf("nil map sent")
+       }
+       if _t1.EmptyMap == nil {
+               t.Errorf("nil map received")
+       }
 }
 
 func TestOverflow(t *testing.T) {
index aaf429c43203fed635df03bc9087b7d2b6d7be34..35d882afb7ad290863e27378d4fbeea80d6cab93 100644 (file)
@@ -113,6 +113,11 @@ uninterpreted bytes of the value.
 All other slices and arrays are sent as an unsigned count followed by that many
 elements using the standard gob encoding for their type, recursively.
 
+Maps are sent as an unsigned count followed by that man key, element
+pairs. Empty but non-nil maps are sent, so if the sender has allocated
+a map, the receiver will allocate a map even no elements are
+transmitted.
+
 Structs are sent as a sequence of (field number, field value) pairs.  The field
 value is sent using the standard gob encoding for its type, recursively.  If a
 field has the zero value for its type, it is omitted from the transmission.  The
index 78455981ebca886d97623be04d5c30f50b9887b7..c4c8219cf3b91358ca0f521a11418d6ee4e017c0 100644 (file)
@@ -557,7 +557,9 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
                                // the iteration.
                                v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p)))
                                mv := reflect.Indirect(v)
-                               if !state.sendZero && mv.Len() == 0 {
+                               // We send zero-length (but non-nil) maps because the
+                               // receiver might want to use the map.  (Maps don't use append.)
+                               if !state.sendZero && mv.IsNil() {
                                        return
                                }
                                state.update(i)