1// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package gob_test
6
7import (
8	"bytes"
9	"encoding/gob"
10	"fmt"
11	"log"
12	"math"
13)
14
15type Point struct {
16	X, Y int
17}
18
19func (p Point) Hypotenuse() float64 {
20	return math.Hypot(float64(p.X), float64(p.Y))
21}
22
23type Pythagoras interface {
24	Hypotenuse() float64
25}
26
27// This example shows how to encode an interface value. The key
28// distinction from regular types is to register the concrete type that
29// implements the interface.
30func Example_interface() {
31	var network bytes.Buffer // Stand-in for the network.
32
33	// We must register the concrete type for the encoder and decoder (which would
34	// normally be on a separate machine from the encoder). On each end, this tells the
35	// engine which concrete type is being sent that implements the interface.
36	gob.Register(Point{})
37
38	// Create an encoder and send some values.
39	enc := gob.NewEncoder(&network)
40	for i := 1; i <= 3; i++ {
41		interfaceEncode(enc, Point{3 * i, 4 * i})
42	}
43
44	// Create a decoder and receive some values.
45	dec := gob.NewDecoder(&network)
46	for i := 1; i <= 3; i++ {
47		result := interfaceDecode(dec)
48		fmt.Println(result.Hypotenuse())
49	}
50
51	// Output:
52	// 5
53	// 10
54	// 15
55}
56
57// interfaceEncode encodes the interface value into the encoder.
58func interfaceEncode(enc *gob.Encoder, p Pythagoras) {
59	// The encode will fail unless the concrete type has been
60	// registered. We registered it in the calling function.
61
62	// Pass pointer to interface so Encode sees (and hence sends) a value of
63	// interface type. If we passed p directly it would see the concrete type instead.
64	// See the blog post, "The Laws of Reflection" for background.
65	err := enc.Encode(&p)
66	if err != nil {
67		log.Fatal("encode:", err)
68	}
69}
70
71// interfaceDecode decodes the next interface value from the stream and returns it.
72func interfaceDecode(dec *gob.Decoder) Pythagoras {
73	// The decode will fail unless the concrete type on the wire has been
74	// registered. We registered it in the calling function.
75	var p Pythagoras
76	err := dec.Decode(&p)
77	if err != nil {
78		log.Fatal("decode:", err)
79	}
80	return p
81}
82