Source file src/encoding/gob/example_interface_test.go

     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  

View as plain text