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