summaryrefslogtreecommitdiff
path: root/src/encoding/gob/example_interface_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/encoding/gob/example_interface_test.go')
-rw-r--r--src/encoding/gob/example_interface_test.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/encoding/gob/example_interface_test.go b/src/encoding/gob/example_interface_test.go
new file mode 100644
index 000000000..4681e6307
--- /dev/null
+++ b/src/encoding/gob/example_interface_test.go
@@ -0,0 +1,81 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gob_test
+
+import (
+ "bytes"
+ "encoding/gob"
+ "fmt"
+ "log"
+ "math"
+)
+
+type Point struct {
+ X, Y int
+}
+
+func (p Point) Hypotenuse() float64 {
+ return math.Hypot(float64(p.X), float64(p.Y))
+}
+
+type Pythagoras interface {
+ Hypotenuse() float64
+}
+
+// This example shows how to encode an interface value. The key
+// distinction from regular types is to register the concrete type that
+// implements the interface.
+func Example_interface() {
+ var network bytes.Buffer // Stand-in for the network.
+
+ // We must register the concrete type for the encoder and decoder (which would
+ // normally be on a separate machine from the encoder). On each end, this tells the
+ // engine which concrete type is being sent that implements the interface.
+ gob.Register(Point{})
+
+ // Create an encoder and send some values.
+ enc := gob.NewEncoder(&network)
+ for i := 1; i <= 3; i++ {
+ interfaceEncode(enc, Point{3 * i, 4 * i})
+ }
+
+ // Create a decoder and receive some values.
+ dec := gob.NewDecoder(&network)
+ for i := 1; i <= 3; i++ {
+ result := interfaceDecode(dec)
+ fmt.Println(result.Hypotenuse())
+ }
+
+ // Output:
+ // 5
+ // 10
+ // 15
+}
+
+// interfaceEncode encodes the interface value into the encoder.
+func interfaceEncode(enc *gob.Encoder, p Pythagoras) {
+ // The encode will fail unless the concrete type has been
+ // registered. We registered it in the calling function.
+
+ // Pass pointer to interface so Encode sees (and hence sends) a value of
+ // interface type. If we passed p directly it would see the concrete type instead.
+ // See the blog post, "The Laws of Reflection" for background.
+ err := enc.Encode(&p)
+ if err != nil {
+ log.Fatal("encode:", err)
+ }
+}
+
+// interfaceDecode decodes the next interface value from the stream and returns it.
+func interfaceDecode(dec *gob.Decoder) Pythagoras {
+ // The decode will fail unless the concrete type on the wire has been
+ // registered. We registered it in the calling function.
+ var p Pythagoras
+ err := dec.Decode(&p)
+ if err != nil {
+ log.Fatal("decode:", err)
+ }
+ return p
+}