diff --git a/src/pkg/gob/codec_test.go b/src/pkg/gob/codec_test.go
index a5fb91cda7841988382c20ebe4d5f8c525d777a0..2bcbf82a3093c8b85ad00a0cb019ef8b9adf3772 100644
--- a/src/pkg/gob/codec_test.go
+++ b/src/pkg/gob/codec_test.go
@@ -544,7 +544,7 @@ func TestScalarDecInstructions(t *testing.T) {
 		var data struct {
 			a []byte
 		}
-		instr := &decInstr{decUint8Array, 6, 0, 0, ovfl}
+		instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl}
 		state := newDecodeStateFromData(bytesResult)
 		execDec("bytes", instr, state, t, unsafe.Pointer(&data))
 		if string(data.a) != "hello" {
diff --git a/src/pkg/gob/decode.go b/src/pkg/gob/decode.go
index bf7cb95f22ca9102e55fd19ba82058cfbee65eab..9bbe1286e041528bde6a9b969f3362d361278dc3 100644
--- a/src/pkg/gob/decode.go
+++ b/src/pkg/gob/decode.go
@@ -385,19 +385,29 @@ func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
 	*(*complex128)(p) = complex(real, imag)
 }
 
-// decUint8Array decodes byte array and stores through p a slice header
+// decUint8Slice decodes a byte slice and stores through p a slice header
 // describing the data.
-// uint8 arrays are encoded as an unsigned count followed by the raw bytes.
-func decUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
+// uint8 slices are encoded as an unsigned count followed by the raw bytes.
+func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
 	if i.indir > 0 {
 		if *(*unsafe.Pointer)(p) == nil {
 			*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
 		}
 		p = *(*unsafe.Pointer)(p)
 	}
-	b := make([]uint8, state.decodeUint())
-	state.b.Read(b)
-	*(*[]uint8)(p) = b
+	n := int(state.decodeUint())
+	if n < 0 {
+		errorf("negative length decoding []byte")
+	}
+	slice := (*[]uint8)(p)
+	if cap(*slice) < n {
+		*slice = make([]uint8, n)
+	} else {
+		*slice = (*slice)[0:n]
+	}
+	if _, err := state.b.Read(*slice); err != nil {
+		errorf("error decoding []byte: %s", err)
+	}
 }
 
 // decString decodes byte array and stores through p a string header
@@ -653,12 +663,15 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
 		}
 		p = *(*uintptr)(up)
 	}
-	// Allocate storage for the slice elements, that is, the underlying array.
+	// Allocate storage for the slice elements, that is, the underlying array,
+	// if the existing slice does not have the capacity.
 	// Always write a header at p.
 	hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p))
-	hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n))
+	if hdrp.Cap < n {
+		hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n))
+		hdrp.Cap = n
+	}
 	hdrp.Len = n
-	hdrp.Cap = n
 	dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
 }
 
@@ -842,7 +855,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
 		case reflect.Slice:
 			name = "element of " + name
 			if t.Elem().Kind() == reflect.Uint8 {
-				op = decUint8Array
+				op = decUint8Slice
 				break
 			}
 			var elemId typeId
diff --git a/src/pkg/gob/doc.go b/src/pkg/gob/doc.go
index a9284ced7f97743795b61760ee79e32bc4444652..05ebef195932775e2e99962ef38cc09d05fe4900 100644
--- a/src/pkg/gob/doc.go
+++ b/src/pkg/gob/doc.go
@@ -68,7 +68,10 @@ the destination variable must be able to represent the value or the decode
 operation will fail.
 
 Structs, arrays and slices are also supported.  Strings and arrays of bytes are
-supported with a special, efficient representation (see below).
+supported with a special, efficient representation (see below).  When a slice is
+decoded, if the existing slice has capacity the slice will be extended in place;
+if not, a new array is allocated.  Regardless, the length of the resuling slice
+reports the number of elements decoded.
 
 Functions and channels cannot be sent in a gob.  Attempting
 to encode a value that contains one will fail.
diff --git a/src/pkg/gob/encoder_test.go b/src/pkg/gob/encoder_test.go
index f5ee423cb2b6e5abc7e2302f3ff29e0f44a460ad..79d28970100d7cfc6f3837331fa68d5c53b45915 100644
--- a/src/pkg/gob/encoder_test.go
+++ b/src/pkg/gob/encoder_test.go
@@ -575,6 +575,56 @@ func TestGobMapInterfaceEncode(t *testing.T) {
 	enc := NewEncoder(buf)
 	err := enc.Encode(m)
 	if err != nil {
-		t.Errorf("gob.Encode map: %s", err)
+		t.Errorf("encode map: %s", err)
+	}
+}
+
+func TestSliceReusesMemory(t *testing.T) {
+	buf := bytes.NewBuffer(nil)
+	// Bytes
+	{
+		x := []byte("abcd")
+		enc := NewEncoder(buf)
+		err := enc.Encode(x)
+		if err != nil {
+			t.Errorf("bytes: encode: %s", err)
+		}
+		// Decode into y, which is big enough.
+		y := []byte("ABCDE")
+		addr := &y[0]
+		dec := NewDecoder(buf)
+		err = dec.Decode(&y)
+		if err != nil {
+			t.Fatal("bytes: decode:", err)
+		}
+		if !bytes.Equal(x, y) {
+			t.Errorf("bytes: expected %q got %q\n", x, y)
+		}
+		if addr != &y[0] {
+			t.Errorf("bytes: unnecessary reallocation")
+		}
+	}
+	// general slice
+	{
+		x := []int("abcd")
+		enc := NewEncoder(buf)
+		err := enc.Encode(x)
+		if err != nil {
+			t.Errorf("ints: encode: %s", err)
+		}
+		// Decode into y, which is big enough.
+		y := []int("ABCDE")
+		addr := &y[0]
+		dec := NewDecoder(buf)
+		err = dec.Decode(&y)
+		if err != nil {
+			t.Fatal("ints: decode:", err)
+		}
+		if !reflect.DeepEqual(x, y) {
+			t.Errorf("ints: expected %q got %q\n", x, y)
+		}
+		if addr != &y[0] {
+			t.Errorf("ints: unnecessary reallocation")
+		}
 	}
 }