Home | History | Annotate | Download | only in gob
      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 
      5 package gob_test
      6 
      7 import (
      8 	"bytes"
      9 	"encoding/gob"
     10 	"fmt"
     11 	"log"
     12 	"math"
     13 )
     14 
     15 type Point struct {
     16 	X, Y int
     17 }
     18 
     19 func (p Point) Hypotenuse() float64 {
     20 	return math.Hypot(float64(p.X), float64(p.Y))
     21 }
     22 
     23 type 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.
     30 func 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.
     58 func 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.
     72 func 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